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/.github/CODEOWNERS b/.github/CODEOWNERS index 85850848b220c4e61b447dc022657065bb914ab1..77ba81c58c5d63f7e5e054d9503e882afd3ae468 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,21 @@ # 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 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/issue-write.yml b/.github/workflows/issue-write.yml new file mode 100644 index 0000000000000000000000000000000000000000..02a5f7c213e898d32d5e5f4d3d42db11df7359c7 --- /dev/null +++ b/.github/workflows/issue-write.yml @@ -0,0 +1,128 @@ +name: Comment on an issue + +on: + workflow_run: + workflows: ["Check code formatting"] + 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) { + 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); + 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..2ed9b05cac120f8fef58c3802502a2d3fea2f6a3 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: + reository: ${{ 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 @@ -77,8 +75,16 @@ jobs: # the merge base. run: | 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/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..2279a070263ef97d3293f5adf43a35ebff57b732 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 @@ -79,6 +78,8 @@ Hot indices are delta encoded, implicitly starting at zero. | ------ | ------| ----------- | | `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 | +| `FuncHash` | 8b | Hot functions only: function hash for input function | +| `NumBlocks` | ULEB128 | Hot functions only: number of basic blocks in the original function | | `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 | @@ -90,10 +91,12 @@ current function. ### 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 | `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 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/DebugNames.h b/bolt/include/bolt/Core/DebugNames.h index 84c448aa1354cc866a8c484e11c808724ad4d550..fbaa7f4e68aac9281989f8432346b1eb9546c3cb 100644 --- a/bolt/include/bolt/Core/DebugNames.h +++ b/bolt/include/bolt/Core/DebugNames.h @@ -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/MCPlus.h b/bolt/include/bolt/Core/MCPlus.h index b6a9e73f2347e71faa09beb4ae2aad9ff7fc5747..1d2360c180335f9f2b1d243153dc1c6f5f92b6fd 100644 --- a/bolt/include/bolt/Core/MCPlus.h +++ b/bolt/include/bolt/Core/MCPlus.h @@ -73,6 +73,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..198a8d8bf48f8222cf4863d7d6d928f5ff160c6e 100644 --- a/bolt/include/bolt/Core/MCPlusBuilder.h +++ b/bolt/include/bolt/Core/MCPlusBuilder.h @@ -487,10 +487,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"); } @@ -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/Profile/BoltAddressTranslation.h b/bolt/include/bolt/Profile/BoltAddressTranslation.h index 844f0c54e68fb2fccfb3e804ea2b66fcc633c305..51fdadce808558e5ed5810f63c80eecc8c73a3a4 100644 --- a/bolt/include/bolt/Profile/BoltAddressTranslation.h +++ b/bolt/include/bolt/Profile/BoltAddressTranslation.h @@ -115,13 +115,16 @@ 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); } + 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 +147,123 @@ 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; /// 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..f7840b49199f90ab0bf33b4f9478d34490affb90 100644 --- a/bolt/include/bolt/Profile/DataAggregator.h +++ b/bolt/include/bolt/Profile/DataAggregator.h @@ -463,6 +463,10 @@ 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; + /// Filter out binaries based on PID void filterBinaryMMapInfo(); 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/lib/Core/BinaryContext.cpp b/bolt/lib/Core/BinaryContext.cpp index b29ebbbfa18c4bc3eff2c0aa54de6d6bb7c0b940..267f43f65e206e65d6f65d9579f66ae2772d61a2 100644 --- a/bolt/lib/Core/BinaryContext.cpp +++ b/bolt/lib/Core/BinaryContext.cpp @@ -1939,7 +1939,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..fdadef9dcd384828db57559b8be5dc76b9d9b29d 100644 --- a/bolt/lib/Core/BinaryFunction.cpp +++ b/bolt/lib/Core/BinaryFunction.cpp @@ -3350,6 +3350,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 +3368,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(); diff --git a/bolt/lib/Core/DIEBuilder.cpp b/bolt/lib/Core/DIEBuilder.cpp index 42287978a8576feb868f82cd38496adb41504658..354fe5059443cca6d56a3dde6a1fe0948a666355 100644 --- a/bolt/lib/Core/DIEBuilder.cpp +++ b/bolt/lib/Core/DIEBuilder.cpp @@ -377,20 +377,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 +412,8 @@ uint32_t DIEBuilder::finalizeDIEs(DWARFUnit &CU, DIE &Die, } Die.setSize(CurSize); + if (NameEntry) + Parents.pop_back(); return CurSize; } @@ -410,7 +424,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 +545,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 +558,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/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/MCPlusBuilder.cpp b/bolt/lib/Core/MCPlusBuilder.cpp index bd9bd0c45922a5d4a92fe280fc97d34cf7decb64..5b14ad5cdb880f307c12d4e72d959a9a9b432a55 100644 --- a/bolt/lib/Core/MCPlusBuilder.cpp +++ b/bolt/lib/Core/MCPlusBuilder.cpp @@ -303,6 +303,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/ShrinkWrapping.cpp b/bolt/lib/Passes/ShrinkWrapping.cpp index 9a1f9d72623a388a275f204a72a0a092cf962123..c9706500758d1f223f5d71de45e310755f021f78 100644 --- a/bolt/lib/Passes/ShrinkWrapping.cpp +++ b/bolt/lib/Passes/ShrinkWrapping.cpp @@ -680,16 +680,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 +1652,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 +1668,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/Profile/BoltAddressTranslation.cpp b/bolt/lib/Profile/BoltAddressTranslation.cpp index 5477d3b7d1c366f02a05fa7810144844702c97d0..57d2aff7197736cee8367951f8715493fc3d6ada 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,28 @@ 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; + // TBD: handle BAT functions w/multiple entry points. + if (Function.isMultiEntry()) + continue; + 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))); 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 +111,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 +126,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,6 +175,10 @@ 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" @@ -166,6 +190,15 @@ void BoltAddressTranslation::writeMaps(std::map &Maps, 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); } encodeULEB128(NumEntries, OS); // For hot fragments only: encode the number of equal offsets @@ -187,8 +220,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 +232,17 @@ 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)); + } } } } @@ -239,12 +285,24 @@ 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; 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))); } const uint32_t NumEntries = DE.getULEB128(&Offset, &Err); // Equal offsets, hot fragments only. @@ -275,6 +333,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,12 +347,27 @@ 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)); } @@ -303,8 +377,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,6 +393,8 @@ 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"; } OS << "\n"; @@ -432,12 +515,14 @@ 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()); } } + } // namespace bolt } // namespace llvm diff --git a/bolt/lib/Profile/DataAggregator.cpp b/bolt/lib/Profile/DataAggregator.cpp index 6a64bcde911e668eca8ff2693501e0dabb744006..b0f1cccc32569cbd25ed478ee0e52ef529358de1 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,21 @@ 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()) { + 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 +2271,99 @@ DataAggregator::writeAggregatedFile(StringRef OutputFilename) const { return std::error_code(); } +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); + }; + + 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); + if (YamlBB.ExecCount || !YamlBB.Successors.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/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..6fcc4a956fa1a19400f9159c38d22686816102c7 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,15 @@ extern llvm::cl::opt ProfileUseDFS; namespace llvm { namespace bolt { -namespace { -void convert(const BinaryFunction &BF, - yaml::bolt::BinaryFunctionProfile &YamlBF) { +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 +43,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) { @@ -106,20 +105,14 @@ void convert(const BinaryFunction &BF, 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 +158,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 +215,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..601a2105fc264f7af2168528d29af291991de27f 100644 --- a/bolt/lib/Rewrite/DWARFRewriter.cpp +++ b/bolt/lib/Rewrite/DWARFRewriter.cpp @@ -283,10 +283,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 +375,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 +402,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 +492,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 +1272,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)) { diff --git a/bolt/lib/Rewrite/LinuxKernelRewriter.cpp b/bolt/lib/Rewrite/LinuxKernelRewriter.cpp index 331a61e7c3c2cdc0f344adc12f10be5fed6cea29..42df9681727590044205e3031fcc293f1b449752 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" @@ -55,11 +57,26 @@ static cl::opt DumpParavirtualPatchSites( "dump-para-sites", cl::desc("dump Linux kernel paravitual patch sites"), cl::init(false), cl::Hidden, cl::cat(BoltCategory)); +static cl::opt + DumpPCIFixups("dump-pci-fixups", + cl::desc("dump Linux kernel PCI fixup table"), + cl::init(false), cl::Hidden, cl::cat(BoltCategory)); + static cl::opt DumpStaticCalls("dump-static-calls", cl::desc("dump Linux kernel 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"), @@ -146,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; @@ -181,6 +212,10 @@ class LinuxKernelRewriter final : public MetadataRewriter { /// Size of bug_entry struct. static constexpr size_t BUG_TABLE_ENTRY_SIZE = 12; + /// .pci_fixup section. + ErrorOr PCIFixupSection = std::errc::bad_address; + static constexpr size_t PCI_FIXUP_ENTRY_SIZE = 16; + /// Insert an LKMarker for a given code pointer \p PC from a non-code section /// \p SectionName. void insertLKMarker(uint64_t PC, uint64_t SectionOffset, @@ -190,9 +225,6 @@ class LinuxKernelRewriter final : public MetadataRewriter { /// Process linux kernel special sections and their relocations. void processLKSections(); - /// Process special linux kernel section, .pci_fixup. - void processLKPCIFixup(); - /// Process __ksymtab and __ksymtab_gpl. void processLKKSymtab(bool IsGPL = false); @@ -220,11 +252,25 @@ class LinuxKernelRewriter final : public MetadataRewriter { /// Paravirtual instruction patch sites. Error readParaInstructions(); + Error rewriteParaInstructions(); Error readBugTable(); - /// Read alternative instruction info from .altinstructions. + /// Do no process functions containing instruction annotated with + /// \p Annotation. + void skipFunctionsWithAnnotation(StringRef Annotation) const; + + /// 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(); @@ -256,6 +302,12 @@ public: if (Error E = readAltInstructions()) return E; + if (Error E = readPCIFixupTable()) + return E; + + if (Error E = readStaticKeysJumpTable()) + return E; + return Error::success(); } @@ -272,18 +324,30 @@ 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; + return Error::success(); } Error postEmitFinalizer() override { updateLKMarkers(); + if (Error E = updateStaticKeysJumpTablePostEmit()) + return E; + return Error::success(); } }; @@ -318,41 +382,11 @@ void LinuxKernelRewriter::insertLKMarker(uint64_t PC, uint64_t SectionOffset, } void LinuxKernelRewriter::processLKSections() { - processLKPCIFixup(); processLKKSymtab(); processLKKSymtab(true); processLKSMPLocks(); } -/// Process .pci_fixup section of Linux Kernel. -/// This section contains a list of entries for different PCI devices and their -/// corresponding hook handler (code pointer where the fixup -/// code resides, usually on x86_64 it is an entry PC relative 32 bit offset). -/// Documentation is in include/linux/pci.h. -void LinuxKernelRewriter::processLKPCIFixup() { - ErrorOr SectionOrError = - BC.getUniqueSectionByName(".pci_fixup"); - if (!SectionOrError) - return; - - const uint64_t SectionSize = SectionOrError->getSize(); - const uint64_t SectionAddress = SectionOrError->getAddress(); - assert((SectionSize % 16) == 0 && ".pci_fixup size is not a multiple of 16"); - - for (uint64_t I = 12; I + 4 <= SectionSize; I += 16) { - const uint64_t PC = SectionAddress + I; - ErrorOr Offset = BC.getSignedValueAtAddress(PC, 4); - assert(Offset && "cannot read value from .pci_fixup"); - const int32_t SignedOffset = *Offset; - const uint64_t HookupAddress = PC + SignedOffset; - BinaryFunction *HookupFunction = - BC.getBinaryFunctionAtAddress(HookupAddress); - assert(HookupFunction && "expected function for entry in .pci_fixup"); - BC.addRelocation(PC, HookupFunction->getSymbol(), Relocation::getPC32(), 0, - *Offset); - } -} - /// Process __ksymtab[_gpl] sections of Linux Kernel. /// This section lists all the vmlinux symbols that kernel modules can access. /// @@ -1104,6 +1138,31 @@ 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. /// Each entry in the section is a struct bug_entry that contains a pointer to @@ -1283,6 +1342,439 @@ 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 +/// list of the following structures defined in include/linux/pci.h: +/// +/// struct pci_fixup { +/// u16 vendor; /* Or PCI_ANY_ID */ +/// u16 device; /* Or PCI_ANY_ID */ +/// u32 class; /* Or PCI_ANY_ID */ +/// unsigned int class_shift; /* should be 0, 8, 16 */ +/// int hook_offset; +/// }; +/// +/// Normally, the hook will point to a function start and we don't have to +/// update the pointer if we are not relocating functions. Hence, while reading +/// the table we validate this assumption. If a function has a fixup code in the +/// middle of its body, we issue a warning and ignore it. +Error LinuxKernelRewriter::readPCIFixupTable() { + PCIFixupSection = BC.getUniqueSectionByName(".pci_fixup"); + if (!PCIFixupSection) + return Error::success(); + + if (PCIFixupSection->getSize() % PCI_FIXUP_ENTRY_SIZE) + return createStringError(errc::executable_format_error, + "PCI fixup table size error"); + + const uint64_t Address = PCIFixupSection->getAddress(); + DataExtractor DE = DataExtractor(PCIFixupSection->getContents(), + BC.AsmInfo->isLittleEndian(), + BC.AsmInfo->getCodePointerSize()); + uint64_t EntryID = 0; + DataExtractor::Cursor Cursor(0); + while (Cursor && !DE.eof(Cursor)) { + const uint16_t Vendor = DE.getU16(Cursor); + const uint16_t Device = DE.getU16(Cursor); + const uint32_t Class = DE.getU32(Cursor); + const uint32_t ClassShift = DE.getU32(Cursor); + const uint64_t HookAddress = + Address + Cursor.tell() + (int32_t)DE.getU32(Cursor); + + if (!Cursor) + return createStringError(errc::executable_format_error, + "out of bounds while reading .pci_fixup: %s", + toString(Cursor.takeError()).c_str()); + + ++EntryID; + + if (opts::DumpPCIFixups) { + BC.outs() << "PCI fixup entry: " << EntryID << "\n\tVendor 0x" + << Twine::utohexstr(Vendor) << "\n\tDevice: 0x" + << Twine::utohexstr(Device) << "\n\tClass: 0x" + << Twine::utohexstr(Class) << "\n\tClassShift: 0x" + << Twine::utohexstr(ClassShift) << "\n\tHookAddress: 0x" + << Twine::utohexstr(HookAddress) << '\n'; + } + + BinaryFunction *BF = BC.getBinaryFunctionContainingAddress(HookAddress); + if (!BF && opts::Verbosity) { + BC.outs() << "BOLT-INFO: no function matches address 0x" + << Twine::utohexstr(HookAddress) + << " of hook from .pci_fixup\n"; + } + + if (!BF || !BC.shouldEmit(*BF)) + continue; + + if (const uint64_t Offset = HookAddress - BF->getAddress()) { + BC.errs() << "BOLT-WARNING: PCI fixup detected in the middle of function " + << *BF << " at offset 0x" << Twine::utohexstr(Offset) << '\n'; + BF->setSimple(false); + } + } + + BC.outs() << "BOLT-INFO: parsed " << EntryID << " PCI fixup entries\n"; + + 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/RewriteInstance.cpp b/bolt/lib/Rewrite/RewriteInstance.cpp index cde195c1739074394726214f8c185c1d237ceaa4..2ead51ff6a1286ffbc2a0c7b873c532c4aa4ea01 100644 --- a/bolt/lib/Rewrite/RewriteInstance.cpp +++ b/bolt/lib/Rewrite/RewriteInstance.cpp @@ -81,6 +81,7 @@ 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 TimeBuild; @@ -199,10 +200,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", @@ -732,6 +730,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,13 +2033,8 @@ 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 && !opts::KeepNops.getNumOccurrences()) + opts::KeepNops = true; } namespace { @@ -3126,12 +3126,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/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..ab9623d5c51b287f4a1e6e58e1ff0784eb6508a7 100644 --- a/bolt/lib/Target/RISCV/RISCVMCPlusBuilder.cpp +++ b/bolt/lib/Target/RISCV/RISCVMCPlusBuilder.cpp @@ -219,46 +219,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..15f95f8217776514ffc7253f0da7b840607a6668 100644 --- a/bolt/lib/Target/X86/X86MCPlusBuilder.cpp +++ b/bolt/lib/Target/X86/X86MCPlusBuilder.cpp @@ -336,6 +336,9 @@ public: } bool isUnsupportedBranch(const MCInst &Inst) const override { + if (isDynamicBranch(Inst)) + return true; + switch (Inst.getOpcode()) { default: return false; @@ -2230,7 +2233,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 +2244,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 +2264,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 +2292,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 +2302,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 +2326,6 @@ public: else Inst.addOperand(MCOperand::createImm(Offset)); // Displacement Inst.addOperand(MCOperand::createReg(AddrSegmentReg)); // AddrSegmentReg - return true; } InstructionListType createLoadImmediate(const MCPhysReg Dest, @@ -2338,7 +2339,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 +2363,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 +2729,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 +2766,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 +2888,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 +2896,6 @@ public: MCSymbolRefExpr::create(Target, MCSymbolRefExpr::VK_None, *Ctx))); if (IsTailCall) setTailCall(Inst); - return true; } void createShortJmp(InstructionListType &Seq, const MCSymbol *Target, @@ -3066,6 +3091,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 +3104,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 +3567,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 +3579,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 +3593,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..be3bcb2a0c6dd17f7603413ba76962d61619f351 --- /dev/null +++ b/bolt/test/X86/bolt-address-translation-yaml.test @@ -0,0 +1,52 @@ +# 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): 380 + +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 - 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..5c1db89e3c6b25a66f953a8e5d73523ed92cec38 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): 920 # # 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-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-pci-fixup.s b/bolt/test/X86/linux-pci-fixup.s new file mode 100644 index 0000000000000000000000000000000000000000..a574ba84c4df11efac6a28e0decf68041dce1d4f --- /dev/null +++ b/bolt/test/X86/linux-pci-fixup.s @@ -0,0 +1,41 @@ +# REQUIRES: system-linux + +# 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 -o %t.out |& FileCheck %s + +## Check that BOLT correctly parses the Linux kernel .pci_fixup section and +## verify that PCI fixup hook in the middle of a function is detected. + +# CHECK: BOLT-INFO: Linux kernel binary detected +# CHECK: BOLT-WARNING: PCI fixup detected in the middle of function _start +# CHECK: BOLT-INFO: parsed 2 PCI fixup entries + + .text + .globl _start + .type _start, %function +_start: + nop +.L0: + ret + .size _start, .-_start + +## PCI fixup table. + .section .pci_fixup,"a",@progbits + + .short 0x8086 # vendor + .short 0xbeef # device + .long 0xffffffff # class + .long 0x0 # class shift + .long _start - . # fixup + + .short 0x8086 # vendor + .short 0xbad # device + .long 0xffffffff # class + .long 0x0 # class shift + .long .L0 - . # fixup + +## Fake Linux Kernel sections. + .section __ksymtab,"a",@progbits + .section __ksymtab_gpl,"a",@progbits 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/unittests/Core/MCPlusBuilder.cpp b/bolt/unittests/Core/MCPlusBuilder.cpp index 63448039c53e677e33bdb2e7f4472f22e297a748..daf9f392b8228198fcf77807ef1e5a9a557288a5 100644 --- a/bolt/unittests/Core/MCPlusBuilder.cpp +++ b/bolt/unittests/Core/MCPlusBuilder.cpp @@ -134,9 +134,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 +150,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/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/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/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/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..2392ccaf65754f6c907aea8eefd3022104bcf888 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -110,6 +110,13 @@ 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. @@ -132,6 +139,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,6 +176,10 @@ Changes in existing checks giving false positives for deleted functions and fix false negative when some parameters are forwarded, but other aren't. +- Improved :doc:`cppcoreguidelines-owning-memory + ` check to properly handle + return type in lambdas and in nested functions. + - Cleaned up :doc:`cppcoreguidelines-prefer-member-initializer ` by removing enforcement of rule `C.48 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..79e81dd174e4f3d4eace4161f9023142d3648210 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" 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/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/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 fe925901eb3dce7759578b57c7bc76f0130431e9..df69d7d0dd414beb8be6752acae171cf6fd5272e 100644 --- a/clang/cmake/caches/Fuchsia.cmake +++ b/clang/cmake/caches/Fuchsia.cmake @@ -65,6 +65,8 @@ set(_FUCHSIA_BOOTSTRAP_PASSTHROUGH LLDB_EMBED_PYTHON_HOME 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..2ee36f24d7ce4b37c4bdf56ba318549b48696a80 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:`¶ ` @@ -6158,6 +6303,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/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..5711972b55e6c03de349a7bc39157b34acb1e27e 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 ------------------------------ 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 6c30af304d981df545c34262d4b4dcd126f5d9a3..7fbe2fec6ca06580363fbadd2536b691bcf33a56 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,8 @@ 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. + New Compiler Flags ------------------ @@ -187,13 +204,49 @@ 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 -------------------------- +- Introduced a new function attribute ``__attribute__((amdgpu_max_num_work_groups(x, y, z)))`` or + ``[[clang::amdgpu_max_num_work_groups(x, y, z)]]`` for the AMDGPU target. This attribute can be + attached to HIP or OpenCL kernel function definitions to provide an optimization hint. The parameters + ``x``, ``y``, and ``z`` specify the maximum number of workgroups for the respective dimensions, + 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. Improvements to Clang's diagnostics ----------------------------------- @@ -231,6 +284,17 @@ 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. + Improvements to Clang's time-trace ---------------------------------- @@ -261,6 +325,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). @@ -268,6 +335,16 @@ 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. + Bug Fixes to Compiler Builtins ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -354,9 +431,24 @@ Bug Fixes to C++ Support when one of the function had more specialized templates. Fixes (`#82509 `_) 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). Bug Fixes to AST Handling ^^^^^^^^^^^^^^^^^^^^^^^^^ +- Clang now properly preserves ``FoundDecls`` within a ``ConceptReference``. (#GH82628) Miscellaneous Bug Fixes ^^^^^^^^^^^^^^^^^^^^^^^ @@ -400,6 +492,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 ^^^^^^^^^^^^^^^ @@ -407,6 +501,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 ^^^^^^^^^^^^^^^^^ @@ -414,6 +528,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 ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -450,6 +565,8 @@ AST Matchers - ``isInStdNamespace`` now supports Decl declared with ``extern "C++"``. - Add ``isExplicitObjectMemberFunction``. +- Fixed ``forEachArgumentWithParam`` and ``forEachArgumentWithParamType`` to + not skip the explicit object parameter for operator calls. clang-format ------------ @@ -465,6 +582,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 ^^^^^^^^^^^^ @@ -499,6 +621,8 @@ 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..129e75fc9a785a65a3a3028eeb439f7f8075858b 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: @@ -4227,7 +4258,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..66da1c7b35f28b507d11ccfab4aa6ccad958edb1 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++) @@ -2139,30 +2184,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++) 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..60db3cf0966c0263083b82e1dec923ffe42bcff2 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, diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index ff6b64c7f72d57f59172eb0d7155ffa8e5da76c4..002f36ecbbaa3f3a1dca7e02b6f3e913f6eaa07c 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 @@ -1341,6 +1343,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; 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/Expr.h b/clang/include/clang/AST/Expr.h index 446bec4081e86908b337ae17bdaf0c9ac6340815..6e153ebe024b42eeb19bdfe178889ce272c25d56 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(); } @@ -3561,6 +3562,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/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..4a1ff222ecadcda0b37c231c3a243c8d40d922b7 100644 --- a/clang/include/clang/AST/RecursiveASTVisitor.h +++ b/clang/include/clang/AST/RecursiveASTVisitor.h @@ -1110,6 +1110,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())); }) @@ -1401,6 +1407,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/Type.h b/clang/include/clang/AST/Type.h index 1942b0e67f65a3157a36ae1b7dbf55bf9398a10f..b3bf23227a47f2c1d8ed876bc3c722b04987cdf4 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; @@ -2000,6 +2001,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 +2038,7 @@ protected: DependentTemplateSpecializationTypeBitfields DependentTemplateSpecializationTypeBits; PackExpansionTypeBitfields PackExpansionTypeBits; + CountAttributedTypeBitfields CountAttributedTypeBits; }; private: @@ -2244,6 +2261,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 +2281,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; @@ -2722,6 +2742,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 +2948,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. @@ -7452,6 +7610,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); } diff --git a/clang/include/clang/AST/TypeLoc.h b/clang/include/clang/AST/TypeLoc.h index 32028e877fc8dc0f0efa0cc0e9f0c631cd9635ae..b09eb3539a4badb306ec2e3abe6c82164028eacc 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; }; diff --git a/clang/include/clang/AST/TypeProperties.td b/clang/include/clang/AST/TypeProperties.td index 0ba172a4035fdb441b07f564bf38b0942a89a087..f3906cb7f86fbfebdfc8572aa2c41f1d49f8ef42 100644 --- a/clang/include/clang/AST/TypeProperties.td +++ b/clang/include/clang/AST/TypeProperties.td @@ -25,6 +25,25 @@ let Class = PointerType in { def : Creator<[{ return ctx.getPointerType(pointeeType); }]>; } +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() }]; diff --git a/clang/include/clang/ASTMatchers/ASTMatchers.h b/clang/include/clang/ASTMatchers/ASTMatchers.h index 96dbcdc344e131acadb629276434854a011d92df..2f71053d030f688f6921d15e265072a8b0cbf759 100644 --- a/clang/include/clang/ASTMatchers/ASTMatchers.h +++ b/clang/include/clang/ASTMatchers/ASTMatchers.h @@ -5032,6 +5032,25 @@ AST_POLYMORPHIC_MATCHER_P2(hasParameter, && InnerMatcher.matches(*Node.parameters()[N], Finder, Builder)); } +/// Matches if the given method declaration declares a member function with an +/// explicit object parameter. +/// +/// Given +/// \code +/// struct A { +/// int operator-(this A, int); +/// void fun(this A &&self); +/// static int operator()(int); +/// int operator+(int); +/// }; +/// \endcode +/// +/// cxxMethodDecl(isExplicitObjectMemberFunction()) matches the first two +/// methods but not the last two. +AST_MATCHER(CXXMethodDecl, isExplicitObjectMemberFunction) { + return Node.isExplicitObjectMemberFunction(); +} + /// Matches all arguments and their respective ParmVarDecl. /// /// Given @@ -5060,10 +5079,12 @@ AST_POLYMORPHIC_MATCHER_P2(forEachArgumentWithParam, // argument of the method which should not be matched against a parameter, so // we skip over it here. BoundNodesTreeBuilder Matches; - unsigned ArgIndex = cxxOperatorCallExpr(callee(cxxMethodDecl())) - .matches(Node, Finder, &Matches) - ? 1 - : 0; + unsigned ArgIndex = + cxxOperatorCallExpr( + callee(cxxMethodDecl(unless(isExplicitObjectMemberFunction())))) + .matches(Node, Finder, &Matches) + ? 1 + : 0; int ParamIndex = 0; bool Matched = false; for (; ArgIndex < Node.getNumArgs(); ++ArgIndex) { @@ -5121,11 +5142,12 @@ AST_POLYMORPHIC_MATCHER_P2(forEachArgumentWithParamType, // argument of the method which should not be matched against a parameter, so // we skip over it here. BoundNodesTreeBuilder Matches; - unsigned ArgIndex = cxxOperatorCallExpr(callee(cxxMethodDecl())) - .matches(Node, Finder, &Matches) - ? 1 - : 0; - + unsigned ArgIndex = + cxxOperatorCallExpr( + callee(cxxMethodDecl(unless(isExplicitObjectMemberFunction())))) + .matches(Node, Finder, &Matches) + ? 1 + : 0; const FunctionProtoType *FProto = nullptr; if (const auto *Call = dyn_cast(&Node)) { @@ -6366,25 +6388,6 @@ AST_MATCHER(CXXMethodDecl, isConst) { return Node.isConst(); } -/// Matches if the given method declaration declares a member function with an -/// explicit object parameter. -/// -/// Given -/// \code -/// struct A { -/// int operator-(this A, int); -/// void fun(this A &&self); -/// static int operator()(int); -/// int operator+(int); -/// }; -/// \endcode -/// -/// cxxMethodDecl(isExplicitObjectMemberFunction()) matches the first two -/// methods but not the last two. -AST_MATCHER(CXXMethodDecl, isExplicitObjectMemberFunction) { - return Node.isExplicitObjectMemberFunction(); -} - /// Matches if the given method declaration declares a copy assignment /// operator. /// 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/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 080340669b60a04bbb38d33671a7e8d18594c57b..3e03e55612645bd8c521524bfc29e70756d1e317 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -2054,6 +2054,13 @@ def AMDGPUNumVGPR : InheritableAttr { let Subjects = SubjectList<[Function], ErrorDiag, "kernel functions">; } +def AMDGPUMaxNumWorkGroups : InheritableAttr { + let Spellings = [Clang<"amdgpu_max_num_work_groups", 0>]; + let Args = [ExprArgument<"MaxNumWorkGroupsX">, ExprArgument<"MaxNumWorkGroupsY", 1>, ExprArgument<"MaxNumWorkGroupsZ", 1>]; + let Documentation = [AMDGPUMaxNumWorkGroupsDocs]; + let Subjects = SubjectList<[Function], ErrorDiag, "kernel functions">; +} + def AMDGPUKernelCall : DeclOrTypeAttr { let Spellings = [Clang<"amdgpu_kernel">]; let Documentation = [Undocumented]; @@ -2186,6 +2193,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". @@ -2927,7 +2943,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 { @@ -4480,21 +4496,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 2c07cd09b0d5b71727d4fd6f3bc421ef6cbe6256..9de14f608fd114792d10bffc04f3fa64be3a3a41 100644 --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -2741,6 +2741,33 @@ An error will be given if: }]; } +def AMDGPUMaxNumWorkGroupsDocs : Documentation { + let Category = DocCatAMDGPUAttributes; + let Content = [{ +This attribute specifies the max number of work groups when the kernel +is dispatched. + +Clang supports the +``__attribute__((amdgpu_max_num_work_groups(, , )))`` or +``[[clang::amdgpu_max_num_work_groups(, , )]]`` attribute for the +AMDGPU target. This attribute may be attached to HIP or OpenCL kernel function +definitions and is an optimization hint. + +The ```` parameter specifies the maximum number of work groups in the x dimension. +Similarly ```` and ```` are for the y and z dimensions respectively. +Each of the three values must be greater than 0 when provided. The ```` parameter +is required, while ```` and ```` are optional with default value of 1. + +If specified, the AMDGPU target backend might be able to produce better machine +code. + +An error will be given if: + - Specified values violate subtarget specifications; + - Specified values are not compatible with values provided through other + attributes. + }]; +} + def DocCatCallingConvs : DocumentationCategory<"Calling Conventions"> { let Content = [{ Clang supports several different calling conventions, depending on the target @@ -5110,10 +5137,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. }]; } @@ -5160,6 +5188,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)``. }]; } 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..21ab9bb86d1b8ca080e23e6155cc172aa9a34546 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, 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, 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,12 @@ def HLSLWaveActiveCountBits : LangBuiltin<"HLSL_LANG"> { let Prototype = "unsigned int(bool)"; } +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 +4623,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 +4647,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..4153b316c22b1d25103a009a976db6fcc0e6b3fa 100644 --- a/clang/include/clang/Basic/BuiltinsAMDGPU.def +++ b/clang/include/clang/Basic/BuiltinsAMDGPU.def @@ -432,13 +432,15 @@ 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_b128_v8f16, "V8hV8h*1", "nc", "gfx12-insts,wavefrontsize32") +TARGET_BUILTIN(__builtin_amdgcn_global_load_tr_b128_v8bf16, "V8yV8y*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") +TARGET_BUILTIN(__builtin_amdgcn_global_load_tr_b128_v4f16, "V4hV4h*1", "nc", "gfx12-insts,wavefrontsize64") +TARGET_BUILTIN(__builtin_amdgcn_global_load_tr_b128_v4bf16, "V4yV4y*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..e33a1f4c45b949733798ab5fb648260bcaddd7f3 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; 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..44035e2fd16f2e8277f3f5dab0ea9395e86fb6bc 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). @@ -1037,6 +1041,7 @@ def Extra : DiagGroup<"extra", [ EmptyInitStatement, StringConcatation, FUseLdPath, + CastFunctionTypeMismatch, ]>; def Most : DiagGroup<"most", [ @@ -1507,3 +1512,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..a4c6e630ac5fd82617e8f34889561e8124093070 --- /dev/null +++ b/clang/include/clang/Basic/DiagnosticInstallAPIKinds.td @@ -0,0 +1,44 @@ +//==--- 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">; +} // 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..fc727cef9cd835805ad1641f7045aa3a447c912f 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">, @@ -6503,12 +6519,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 +9058,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< @@ -11516,8 +11538,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 +12020,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..b41aadc73f205d5db241bdbdd5638f76e3272cb9 100644 --- a/clang/include/clang/Basic/Features.def +++ b/clang/include/clang/Basic/Features.def @@ -101,7 +101,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 +261,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/TargetInfo.h b/clang/include/clang/Basic/TargetInfo.h index 7682f84e491c7bc15d07c2e399a80769a9740916..374595edd2ce4a2e8f92842ccce97b066291e0b8 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" @@ -1571,6 +1572,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..3625f063758915f285f96d93871d55c0ebb11b2c 100644 --- a/clang/include/clang/Basic/TypeNodes.td +++ b/clang/include/clang/Basic/TypeNodes.td @@ -108,6 +108,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..b0d90c776b58a9620e3b3de416623805964c7c81 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,6 +3608,27 @@ 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>; +let Group = f_Group in { + let Visibility = [ClangOption,CC1Option] in { + def fptrauth_intrinsics : Flag<["-"], "fptrauth-intrinsics">, + HelpText<"Enable pointer authentication intrinsics">; + } + def fno_ptrauth_intrinsics : Flag<["-"], "fno-ptrauth-intrinsics">; +} + def fenable_matrix : Flag<["-"], "fenable-matrix">, Group, Visibility<[ClangOption, CC1Option]>, HelpText<"Enable matrix data type and related builtin functions">, @@ -4675,21 +4703,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 +5398,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 +6440,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 +6688,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>; @@ -8557,6 +8582,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/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..0720c8283cd75c4b778f010df50569530958ee15 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 @@ -4728,6 +4743,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 +4894,8 @@ struct FormatStyle { AlignConsecutiveMacros == R.AlignConsecutiveMacros && AlignConsecutiveShortCaseStatements == R.AlignConsecutiveShortCaseStatements && + AlignConsecutiveTableGenBreakingDAGArgColons == + R.AlignConsecutiveTableGenBreakingDAGArgColons && AlignConsecutiveTableGenCondOperatorColons == R.AlignConsecutiveTableGenCondOperatorColons && AlignConsecutiveTableGenDefinitionColons == @@ -4980,9 +5051,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/FrontendActions.h b/clang/include/clang/Frontend/FrontendActions.h index 8441af2ee3e718603ac9dd2898dcee4b14b38d01..a620ddfc40447d7795df64c407300b6ca8da5d44 100644 --- a/clang/include/clang/Frontend/FrontendActions.h +++ b/clang/include/clang/Frontend/FrontendActions.h @@ -125,7 +125,7 @@ protected: StringRef InFile) override; TranslationUnitKind getTranslationUnitKind() override { - return TU_Module; + return TU_ClangModule; } bool hasASTFileSupport() const override { return false; } @@ -138,7 +138,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 +161,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; }; diff --git a/clang/include/clang/InstallAPI/Context.h b/clang/include/clang/InstallAPI/Context.h index 4e9e90e5d2dbec18c6f11ca3a4e64c4fd8ff30b5..54e517544b8edf526097afd66347b9e55998c0f3 100644 --- a/clang/include/clang/InstallAPI/Context.h +++ b/clang/include/clang/InstallAPI/Context.h @@ -11,9 +11,10 @@ #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" -#include "llvm/TextAPI/InterfaceFile.h" namespace clang { namespace installapi { @@ -25,7 +26,7 @@ class FrontendRecordsSlice; struct InstallAPIContext { /// Library attributes that are typically passed as linker inputs. - llvm::MachO::RecordsSlice::BinaryAttrs BA; + BinaryAttrs BA; /// All headers that represent a library. HeaderSeq InputHeaders; @@ -45,11 +46,14 @@ 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{}; /// What encoding to write output as. - llvm::MachO::FileType FT = llvm::MachO::FileType::TBD_V5; + FileType FT = FileType::TBD_V5; /// Populate entries of headers that should be included for TextAPI /// generation. diff --git a/clang/include/clang/InstallAPI/DylibVerifier.h b/clang/include/clang/InstallAPI/DylibVerifier.h new file mode 100644 index 0000000000000000000000000000000000000000..49de24763f1f938d88ba6e2f2ab41d593fc34a38 --- /dev/null +++ b/clang/include/clang/InstallAPI/DylibVerifier.h @@ -0,0 +1,164 @@ +//===- 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; + +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); + + VerifierContext() = default; + VerifierContext(DiagnosticsEngine *Diag) : Diag(Diag) {} + }; + + DylibVerifier() = default; + + DylibVerifier(llvm::MachO::Records &&Dylib, DiagnosticsEngine *Diag, + VerificationMode Mode, bool Demangle) + : Dylib(std::move(Dylib)), Mode(Mode), Demangle(Demangle), + 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); + + // 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; + + // Valid symbols in final text file. + std::unique_ptr Exports = std::make_unique(); + + // Track current state of verification while traversing AST. + VerifierContext Ctx; +}; + +} // 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 cbc2b159ebd17a3b92c27c5ea391c96120ad9f8c..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" @@ -25,100 +25,6 @@ namespace clang { namespace installapi { -using SymbolFlags = llvm::MachO::SymbolFlags; -using RecordLinkage = llvm::MachO::RecordLinkage; -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; - -// Represents a collection of frontend records for a library that are tied to a -// darwin target triple. -class FrontendRecordsSlice : public llvm::MachO::RecordsSlice { -public: - FrontendRecordsSlice(const llvm::Triple &T) - : llvm::MachO::RecordsSlice({T}) {} - - /// Add non-ObjC global record with attributes from AST. - /// - /// \param Name The name of symbol. - /// \param Linkage The linkage of symbol. - /// \param GV The kind of global. - /// \param Avail The availability information tied to the active target - /// triple. - /// \param D The pointer to the declaration from traversing AST. - /// \param Access The intended access level of symbol. - /// \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); - - /// Add ObjC Class record with attributes from AST. - /// - /// \param Name The name of class, not symbol. - /// \param Linkage The linkage of symbol. - /// \param Avail The availability information tied to the active target - /// triple. - /// \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); - - /// Add ObjC Category record with attributes from AST. - /// - /// \param ClassToExtend The name of class that is extended by category, not - /// symbol. - /// \param CategoryName The name of category, not symbol. - /// \param Avail The availability information tied - /// 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); - - /// Add ObjC IVar record with attributes from AST. - /// - /// \param Container The owning pointer for instance variable. - /// \param Name The name of ivar, not symbol. - /// \param Linkage The linkage of symbol. - /// \param Avail The availability information tied to the active target - /// triple. - /// \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); - -private: - /// Frontend information captured about records. - struct FrontendAttrs { - const AvailabilityInfo Avail; - const Decl *D; - const HeaderType Access; - }; - - /// Mapping of records stored in slice to their frontend attributes. - llvm::DenseMap FrontendRecords; -}; - /// Create a buffer that contains all headers to scan /// for global symbols with. std::unique_ptr createInputBuffer(InstallAPIContext &Ctx); @@ -129,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 new file mode 100644 index 0000000000000000000000000000000000000000..59271e81e230c2f022e1bec0894e0529e3f3a0e2 --- /dev/null +++ b/clang/include/clang/InstallAPI/FrontendRecords.h @@ -0,0 +1,112 @@ +//===- InstallAPI/FrontendRecords.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_FRONTENDRECORDS_H +#define LLVM_CLANG_INSTALLAPI_FRONTENDRECORDS_H + +#include "clang/AST/Availability.h" +#include "clang/AST/DeclObjC.h" +#include "clang/InstallAPI/HeaderFile.h" +#include "clang/InstallAPI/MachO.h" + +namespace clang { +namespace installapi { + +/// Frontend information captured about records. +struct FrontendAttrs { + const AvailabilityInfo Avail; + const Decl *D; + const HeaderType Access; +}; + +// Represents a collection of frontend records for a library that are tied to a +// darwin target triple. +class FrontendRecordsSlice : public llvm::MachO::RecordsSlice { +public: + FrontendRecordsSlice(const llvm::Triple &T) + : llvm::MachO::RecordsSlice({T}) {} + + /// Add non-ObjC global record with attributes from AST. + /// + /// \param Name The name of symbol. + /// \param Linkage The linkage of symbol. + /// \param GV The kind of global. + /// \param Avail The availability information tied to the active target + /// triple. + /// \param D The pointer to the declaration from traversing AST. + /// \param Access The intended access level of symbol. + /// \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 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. + /// + /// \param Name The name of class, not symbol. + /// \param Linkage The linkage of symbol. + /// \param Avail The availability information tied to the active target + /// triple. + /// \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 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. + /// + /// \param ClassToExtend The name of class that is extended by category, not + /// symbol. + /// \param CategoryName The name of category, not symbol. + /// \param Avail The availability information tied + /// 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 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. + /// + /// \param Container The owning pointer for instance variable. + /// \param Name The name of ivar, not symbol. + /// \param Linkage The linkage of symbol. + /// \param Avail The availability information tied to the active target + /// triple. + /// \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 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. + llvm::DenseMap FrontendRecords; +}; + +} // namespace installapi +} // namespace clang + +#endif // LLVM_CLANG_INSTALLAPI_FRONTENDRECORDS_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 new file mode 100644 index 0000000000000000000000000000000000000000..f0dea8bbd24ccd6ac34cc7b43fa128c696838e1c --- /dev/null +++ b/clang/include/clang/InstallAPI/MachO.h @@ -0,0 +1,46 @@ +//===- InstallAPI/MachO.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 +// +//===----------------------------------------------------------------------===// +// +// Imports and forward declarations for llvm::MachO types. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_INSTALLAPI_MACHO_H +#define LLVM_CLANG_INSTALLAPI_MACHO_H + +#include "llvm/TextAPI/Architecture.h" +#include "llvm/TextAPI/InterfaceFile.h" +#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" + +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 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 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/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index 64e031d5094c74cd0dbef96df55e479661b033b2..bba8ef4ff017391f7aa912ec89653658a5591866 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -3073,6 +3073,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/Sema.h b/clang/include/clang/Sema/Sema.h index 267c79cc057cbae140f349eac955d6a9655c677b..5ecd2f9eb2881f3d6e5e19a0409b8b8f5d533117 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -2152,14 +2152,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, @@ -3059,6 +3060,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); @@ -3911,6 +3914,16 @@ public: void addAMDGPUWavesPerEUAttr(Decl *D, const AttributeCommonInfo &CI, Expr *Min, Expr *Max); + /// Create an AMDGPUMaxNumWorkGroupsAttr attribute. + AMDGPUMaxNumWorkGroupsAttr * + CreateAMDGPUMaxNumWorkGroupsAttr(const AttributeCommonInfo &CI, Expr *XExpr, + Expr *YExpr, Expr *ZExpr); + + /// addAMDGPUMaxNumWorkGroupsAttr - Adds an amdgpu_max_num_work_groups + /// attribute to a particular declaration. + void addAMDGPUMaxNumWorkGroupsAttr(Decl *D, const AttributeCommonInfo &CI, + Expr *XExpr, Expr *YExpr, Expr *ZExpr); + DLLImportAttr *mergeDLLImportAttr(Decl *D, const AttributeCommonInfo &CI); DLLExportAttr *mergeDLLExportAttr(Decl *D, const AttributeCommonInfo &CI); MSInheritanceAttr *mergeMSInheritanceAttr(Decl *D, @@ -3918,8 +3931,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); @@ -5232,6 +5243,7 @@ public: enum ExpressionKind { EK_Decltype, EK_TemplateArgument, + EK_BoundsAttrArgument, EK_Other } ExprContext; @@ -5349,6 +5361,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. @@ -8054,13 +8072,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. @@ -9204,7 +9222,7 @@ public: bool AttachTypeConstraint(NestedNameSpecifierLoc NS, DeclarationNameInfo NameInfo, - ConceptDecl *NamedConcept, + ConceptDecl *NamedConcept, NamedDecl *FoundDecl, const TemplateArgumentListInfo *TemplateArgs, TemplateTypeParmDecl *ConstrainedParameter, SourceLocation EllipsisLoc); @@ -11734,6 +11752,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); 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..3c82dfed9497d587a6eaf985b809e9263d2a78c5 100644 --- a/clang/include/clang/Serialization/TypeBitCodes.def +++ b/clang/include/clang/Serialization/TypeBitCodes.def @@ -65,6 +65,6 @@ 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) #undef TYPE_BIT_CODE diff --git a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td index 686e5e99f4a62c4a2649ea40849998968aa3e92b..bf46766d44b39126026c13b72646393f922ad794 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">, 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/CheckerManager.h b/clang/include/clang/StaticAnalyzer/Core/CheckerManager.h index a45ba1bc573e1e0d7ab5b416af5595bf4615497e..ad25d18f280700033874474f7ff1efe70b51d89a 100644 --- a/clang/include/clang/StaticAnalyzer/Core/CheckerManager.h +++ b/clang/include/clang/StaticAnalyzer/Core/CheckerManager.h @@ -49,7 +49,7 @@ class ExplodedNodeSet; class ExprEngine; struct EvalCallOptions; class MemRegion; -struct NodeBuilderContext; +class NodeBuilderContext; class ObjCMethodCall; class RegionAndSymbolInvalidationTraits; class SVal; 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/CoreEngine.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h index 8e392421fef9bb1cb270f7816df358879bca66b7..0ef353bf9731cadd9144808526f50c94f1d32fb5 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h @@ -59,7 +59,7 @@ class CoreEngine { friend class ExprEngine; friend class IndirectGotoNodeBuilder; friend class NodeBuilder; - friend struct NodeBuilderContext; + friend class NodeBuilderContext; friend class SwitchNodeBuilder; public: @@ -193,12 +193,12 @@ public: DataTag::Factory &getDataTags() { return DataTags; } }; -// TODO: Turn into a class. -struct NodeBuilderContext { +class NodeBuilderContext { const CoreEngine &Eng; const CFGBlock *Block; const LocationContext *LC; +public: NodeBuilderContext(const CoreEngine &E, const CFGBlock *B, const LocationContext *L) : Eng(E), Block(B), LC(L) { @@ -208,9 +208,15 @@ struct NodeBuilderContext { NodeBuilderContext(const CoreEngine &E, const CFGBlock *B, ExplodedNode *N) : NodeBuilderContext(E, B, N->getLocationContext()) {} + /// Return the CoreEngine associated with this builder. + const CoreEngine &getEngine() const { return Eng; } + /// Return the CFGBlock associated with this builder. const CFGBlock *getBlock() const { return Block; } + /// Return the location context associated with this builder. + const LocationContext *getLocationContext() const { return LC; } + /// Returns the number of times the current basic block has been /// visited on the exploded graph path. unsigned blockCount() const { diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h index f7894fb83ce65cd30b165ce5aa8b73242bfa75a3..e38a3bb56ece26f6b0ea326dcc364b5c79415f97 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h @@ -85,7 +85,7 @@ class ExplodedNodeSet; class ExplodedNode; class IndirectGotoNodeBuilder; class MemRegion; -struct NodeBuilderContext; +class NodeBuilderContext; class NodeBuilderWithSinks; class ProgramState; class ProgramStateManager; @@ -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/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 5a8fae76a43a4d5cfd2b81a7d7f357f3d5689ce0..fcf801adeaf5ef55e05393f6426eabae18e4cfcd 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -2348,6 +2348,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 +3125,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) @@ -13234,6 +13263,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"); } diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index 023aaa7f0572b4328bded417486b65d3e9979484..786695f00fadccc37cc67fcb83dc03ff45cf25c9 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -1527,6 +1527,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 +9327,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..226e0aa38ece70bb990dee34bcf2de8eda6b2957 100644 --- a/clang/lib/AST/ASTStructuralEquivalence.cpp +++ b/clang/lib/AST/ASTStructuralEquivalence.cpp @@ -1069,6 +1069,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/Decl.cpp b/clang/lib/AST/Decl.cpp index 8626f04012f7d497af9d0b222b3c11842262e752..95900afdd2c5d8e17e68a0fe38f9fd38a751c4da 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, 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..6221ebd5c9b4e99371d4998f7381e5673de10a67 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) { @@ -4604,8 +4624,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..592d43597dc1b45a4f325602f80bb39da5758c78 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -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; @@ -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); @@ -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 @@ -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); @@ -12923,6 +12943,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); diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp index 86304a54473ceaef838db08179681a0061da9949..73831eefba45687a9a469cd722f3aedf312c8fd7 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; @@ -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; } @@ -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) @@ -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..ab7a591fb798ee6fb8e1d97c12d7a491fe84c536 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); 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/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..da6f72c62115dd94a3c216ce9cbbc2351aaadf3e 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; } 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..f619d657ae9f50c4491532d497eaf7d54522acdd 100644 --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/lib/AST/ItaniumMangle.cpp @@ -2431,6 +2431,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: diff --git a/clang/lib/AST/MicrosoftMangle.cpp b/clang/lib/AST/MicrosoftMangle.cpp index b272a546573a31bb3bfeee2afd9411779988966d..cf9c2093a8f6a1eb6a336fb5f5928abc53451a20 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); @@ -3911,7 +3911,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 +3921,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"; } diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp index 22666184c56ccfc9579fb2b6d28eb49c165e667d..c6fe90ba5e292736976286bffcdc5caa30b1f508 100644 --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -385,6 +385,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. @@ -559,6 +579,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 +669,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()) @@ -3709,6 +3741,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())), 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..7032ff2f18468c2a23c6a2dd4fa9041cc0b0bf2b 100644 --- a/clang/lib/AST/TypePrinter.cpp +++ b/clang/lib/AST/TypePrinter.cpp @@ -286,6 +286,7 @@ bool TypePrinter::canPrefixQualifiers(const Type *T, case Type::PackExpansion: case Type::SubstTemplateTypeParm: case Type::MacroQualified: + case Type::CountAttributed: CanPrefixQualifiers = false; break; @@ -1635,6 +1636,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 +1729,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 +1889,7 @@ void TypePrinter::printAttributedAfter(const AttributedType *T, // AttributedType nodes for them. break; + case attr::CountedBy: case attr::LifetimeBound: case attr::TypeNonNull: case attr::TypeNullable: @@ -2260,10 +2303,15 @@ printTo(raw_ostream &OS, ArrayRef Args, const PrintingPolicy &Policy, } else { if (!FirstArg) OS << Comma; - // Tries to print the argument with location info if exists. - printArgument(Arg, Policy, ArgOS, - TemplateParameterList::shouldIncludeTypeForArgument( - Policy, TPL, ParmIndex)); + if (!Policy.SuppressTagKeyword && + Argument.getKind() == TemplateArgument::Type && + isa(Argument.getAsType())) + OS << Argument.getAsType().getAsString(); + else + // Tries to print the argument with location info if exists. + printArgument(Arg, Policy, ArgOS, + TemplateParameterList::shouldIncludeTypeForArgument( + Policy, TPL, ParmIndex)); } StringRef ArgString = ArgOS.str(); 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..cc1ebd511191a93d76a0528ee95ba6dd1907044c 100644 --- a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp +++ b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp @@ -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 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..dbf4878622eba93f731927987cad6153478af198 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, @@ -843,13 +927,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 +936,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..960e9688ffb725977dc035f2c43e594e52537c01 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 @@ -836,27 +846,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/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..5d9055174c089ad8d11bdf32e0eb46b952527d82 100644 --- a/clang/lib/Basic/TargetInfo.cpp +++ b/clang/lib/Basic/TargetInfo.cpp @@ -925,6 +925,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..1c3199bd76eed6591574013cdb4f4e7293a626d2 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" @@ -199,13 +201,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 { @@ -680,7 +692,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) @@ -1450,6 +1463,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..542894c66412dc88b09302fc526aed653678f576 100644 --- a/clang/lib/Basic/Targets/AArch64.h +++ b/clang/lib/Basic/Targets/AArch64.h @@ -195,10 +195,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/BPF.cpp b/clang/lib/Basic/Targets/BPF.cpp index e3fbbb720d0694c48f3f731232dc71ba5fa2998f..b5ba11a3bdca9d709eef35c5ce531923c425aa01 100644 --- a/clang/lib/Basic/Targets/BPF.cpp +++ b/clang/lib/Basic/Targets/BPF.cpp @@ -35,6 +35,9 @@ void BPFTargetInfo::getTargetDefines(const LangOptions &Opts, Builder.defineMacro("__BPF_CPU_VERSION__", "0"); return; } + + Builder.defineMacro("__BPF_FEATURE_ADDR_SPACE_CAST"); + if (CPU.empty() || CPU == "generic" || CPU == "v1") { Builder.defineMacro("__BPF_CPU_VERSION__", "1"); return; @@ -42,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/CodeGen/CGBlocks.cpp b/clang/lib/CodeGen/CGBlocks.cpp index 0cbace7b7f7bbd5068c4cfe9c7b639e0100d7aea..ad0b50d799618ed7ec7ecb581dd1bec84538a40c 100644 --- a/clang/lib/CodeGen/CGBlocks.cpp +++ b/clang/lib/CodeGen/CGBlocks.cpp @@ -1540,7 +1540,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. diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 93ab465079777bf9ad70c2bae38a0e4b4d1a39fe..2eaceeba6177003b223bc2ce3b6b66bf279fe767 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -858,7 +858,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 +956,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 +975,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; @@ -3128,36 +3128,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: @@ -5208,6 +5238,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()); @@ -10686,6 +10783,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( @@ -17963,6 +18066,17 @@ llvm::Value *CodeGenFunction::EmitScalarOrConstFoldImmArg(unsigned ICEArguments, return Arg; } +Intrinsic::ID getDotProductIntrinsic(QualType QT) { + if (QT->hasSignedIntegerRepresentation()) + return Intrinsic::dx_sdot; + if (QT->hasUnsignedIntegerRepresentation()) + return Intrinsic::dx_udot; + + assert(QT->hasFloatingRepresentation()); + return Intrinsic::dx_dot; + ; +} + Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID, const CallExpr *E) { if (!getLangOpts().HLSL) @@ -17975,6 +18089,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)); @@ -18008,45 +18137,19 @@ 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()), 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 +18159,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 +18200,14 @@ 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"); + } } return nullptr; } @@ -18406,35 +18531,45 @@ 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_v4bf16: + case AMDGPU::BI__builtin_amdgcn_global_load_tr_b128_v4f16: + case AMDGPU::BI__builtin_amdgcn_global_load_tr_b128_v4i16: + case AMDGPU::BI__builtin_amdgcn_global_load_tr_b128_v8bf16: + case AMDGPU::BI__builtin_amdgcn_global_load_tr_b128_v8f16: + case AMDGPU::BI__builtin_amdgcn_global_load_tr_b128_v8i16: { llvm::Type *ArgTy; switch (BuiltinID) { - case AMDGPU::BI__builtin_amdgcn_global_load_tr_i32: + case AMDGPU::BI__builtin_amdgcn_global_load_tr_b64_i32: ArgTy = llvm::Type::getInt32Ty(getLLVMContext()); break; - case AMDGPU::BI__builtin_amdgcn_global_load_tr_v2i32: + case AMDGPU::BI__builtin_amdgcn_global_load_tr_b64_v2i32: ArgTy = llvm::FixedVectorType::get( llvm::Type::getInt32Ty(getLLVMContext()), 2); break; - case AMDGPU::BI__builtin_amdgcn_global_load_tr_v4f16: + case AMDGPU::BI__builtin_amdgcn_global_load_tr_b128_v4bf16: + ArgTy = llvm::FixedVectorType::get( + llvm::Type::getBFloatTy(getLLVMContext()), 4); + break; + case AMDGPU::BI__builtin_amdgcn_global_load_tr_b128_v4f16: ArgTy = llvm::FixedVectorType::get( llvm::Type::getHalfTy(getLLVMContext()), 4); break; - case AMDGPU::BI__builtin_amdgcn_global_load_tr_v4i16: + case AMDGPU::BI__builtin_amdgcn_global_load_tr_b128_v4i16: ArgTy = llvm::FixedVectorType::get( llvm::Type::getInt16Ty(getLLVMContext()), 4); break; - case AMDGPU::BI__builtin_amdgcn_global_load_tr_v8f16: + case AMDGPU::BI__builtin_amdgcn_global_load_tr_b128_v8bf16: + ArgTy = llvm::FixedVectorType::get( + llvm::Type::getBFloatTy(getLLVMContext()), 8); + break; + case AMDGPU::BI__builtin_amdgcn_global_load_tr_b128_v8f16: ArgTy = llvm::FixedVectorType::get( llvm::Type::getHalfTy(getLLVMContext()), 8); break; - case AMDGPU::BI__builtin_amdgcn_global_load_tr_v8i16: + case AMDGPU::BI__builtin_amdgcn_global_load_tr_b128_v8i16: ArgTy = llvm::FixedVectorType::get( llvm::Type::getInt16Ty(getLLVMContext()), 8); break; diff --git a/clang/lib/CodeGen/CGCUDANV.cpp b/clang/lib/CodeGen/CGCUDANV.cpp index 49f93451db7bbba07c8dcc93a99074fad177bc85..b756318c46a900abc16eb9f01b2a0947749e57c3 100644 --- a/clang/lib/CodeGen/CGCUDANV.cpp +++ b/clang/lib/CodeGen/CGCUDANV.cpp @@ -491,7 +491,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 +605,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 +1083,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 +1094,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 +1152,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/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index c2c01439f2dc99319f08a1bbb276e9ff5532b360..7453ed14aef4141ae316ebd78aa9a408fb2a07c0 100644 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -3463,6 +3463,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; @@ -3658,6 +3661,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..2ef5ed04af30b6e99b59e2570e0c27da25500777 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; } } diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index 59a7fe8925001cc497bfa8d8b8ba9ddf9fea2051..85f5d739cef457a49d143d33c6689efe82b48696 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -1136,38 +1136,19 @@ llvm::Value *CodeGenFunction::EmitCountedByFieldExpr( } const FieldDecl *CodeGenFunction::FindCountedByField(const FieldDecl *FD) { - if (!FD || !FD->hasAttr<CountedByAttr>()) + if (!FD) return nullptr; - const auto *CBA = FD->getAttr<CountedByAttr>(); - if (!CBA) + const auto *CAT = FD->getType()->getAs<CountAttributedType>(); + if (!CAT) 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) - return nullptr; - - DeclarationName DName(CBA->getCountedByField()); - DeclContext::lookup_result Lookup = EnclosingRD->lookup(DName); - - if (Lookup.empty()) - 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, @@ -4259,7 +4240,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 = diff --git a/clang/lib/CodeGen/CGExprComplex.cpp b/clang/lib/CodeGen/CGExprComplex.cpp index 0266ba934da62c416fcbf61e81570126c7c2d63e..b873bc6737bb0a61d17d2eaa6e29db0abca12619 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 = dyn_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; \ } @@ -794,8 +841,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 +1034,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/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp index 8898e3f22a7df6d6ff8cd69b5255279d3ed8005a..cb5a004e4f4a6cf802758169cb211728b6d0e42e 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) diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp index 452ce6983f6ac195785cbc0e508e5b46941dd206..f37ac549d10a827ea0ad5b71fc656d0240d6c03a 100644 --- a/clang/lib/CodeGen/CGStmtOpenMP.cpp +++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp @@ -4749,10 +4749,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 +4760,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; + } } } } 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/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp index 4a3ff49b0007a3c6d70d9ef8974a1d7e00cc73ff..fad26c43da3d348b7ea2970bba1377d24c29d107 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -1361,6 +1361,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 @@ -2407,6 +2409,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; diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 967319bdfc4571168f370c42b3b6ad26d21b8c6c..ac81df8cf7adfed9a4ba3c3bea367006e2f7eacb 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,8 @@ void CodeGenModule::EmitGlobal(GlobalDecl GD) { // Forward declarations are emitted lazily on first use. if (!FD->doesThisDeclarationHaveABody()) { - if (!FD->doesDeclarationForceExternallyVisibleDefinition()) + if (!FD->doesDeclarationForceExternallyVisibleDefinition() && + !FD->isTargetVersionMultiVersion()) return; StringRef MangledName = getMangledName(GD); @@ -3969,10 +4001,13 @@ void CodeGenModule::EmitMultiVersionFunctionDefinition(GlobalDecl GD, 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 +4093,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,66 +4117,54 @@ void CodeGenModule::emitMultiVersionFunctions() { const auto *FD = cast<FunctionDecl>(GD.getDecl()); assert(FD && "Expected a FunctionDecl"); + 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); + }; + + bool HasDefaultDecl = !FD->isTargetVersionMultiVersion(); + bool ShouldEmitResolver = !FD->isTargetVersionMultiVersion(); 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; + FD, [&](const FunctionDecl *CurFD) { + llvm::SmallVector<StringRef, 8> Feats; + llvm::Function *Func = createFunction(CurFD); + + if (const auto *TA = CurFD->getAttr<TargetAttr>()) { 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; + 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); - Options.emplace_back(cast<llvm::Function>(Func), - /*Architecture*/ "", Feats); - } + Options.emplace_back(Func, /*Architecture*/ "", Feats); + } else + llvm_unreachable("unexpected MultiVersionKind"); }); - } else if (FD->isTargetClonesMultiVersion()) { - const auto *TC = FD->getAttr<TargetClonesAttr>(); - for (unsigned VersionIndex = 0; VersionIndex < TC->featuresStrs_size(); - ++VersionIndex) { - if (!TC->isFirstOfVersion(VersionIndex)) + } else if (const auto *TC = FD->getAttr<TargetClonesAttr>()) { + for (unsigned I = 0; I < TC->featuresStrs_size(); ++I) { + if (!TC->isFirstOfVersion(I)) 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"); - } + llvm::Function *Func = createFunction(FD, I); + StringRef Version = TC->getFeatureStr(I); StringRef Architecture; llvm::SmallVector<StringRef, 1> Feature; @@ -4142,29 +4182,41 @@ void CodeGenModule::emitMultiVersionFunctions() { Feature.push_back(Version); } - Options.emplace_back(cast<llvm::Function>(Func), Architecture, Feature); + Options.emplace_back(Func, Architecture, Feature); } } else { assert(0 && "Expected a target or target_clones multiversion function"); continue; } + 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); if (auto *IFunc = dyn_cast<llvm::GlobalIFunc>(ResolverConstant)) { 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 +4373,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()) { + 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 +4426,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 +4489,9 @@ llvm::Constant *CodeGenModule::GetOrCreateLLVMFunction( if (FD->isMultiVersion()) { UpdateMultiVersionNames(GD, FD, MangledName); - if (!IsForDefinition) + if (FD->isTargetVersionMultiVersion() && !FD->isUsed()) + AddDeferredMultiVersionResolverToEmit(GD); + else if (!IsForDefinition) return GetOrCreateMultiVersionResolver(GD); } } 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/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp index 60b45ee78d9316769481a64599b728050fe64b5f..bdd53a192f828adbe2999a7f54d3d805c4892146 100644 --- a/clang/lib/CodeGen/ItaniumCXXABI.cpp +++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp @@ -1885,19 +1885,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 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/TargetInfo.h b/clang/lib/CodeGen/TargetInfo.h index 7682f197041c748a4daebc0e15fe19d73eeccaea..6893b50a3cfe90861432da5f4a8055e534204a36 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, @@ -416,6 +421,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/AMDGPU.cpp b/clang/lib/CodeGen/Targets/AMDGPU.cpp index 03ac6b78598fc8477e6756b4c64f5936fd0daedb..44e86c0b40f6864e00893968e420a5127b2add63 100644 --- a/clang/lib/CodeGen/Targets/AMDGPU.cpp +++ b/clang/lib/CodeGen/Targets/AMDGPU.cpp @@ -356,6 +356,29 @@ void AMDGPUTargetCodeGenInfo::setFunctionDeclAttributes( if (NumVGPR != 0) F->addFnAttr("amdgpu-num-vgpr", llvm::utostr(NumVGPR)); } + + if (const auto *Attr = FD->getAttr<AMDGPUMaxNumWorkGroupsAttr>()) { + uint32_t X = Attr->getMaxNumWorkGroupsX() + ->EvaluateKnownConstInt(M.getContext()) + .getExtValue(); + // Y and Z dimensions default to 1 if not specified + uint32_t Y = Attr->getMaxNumWorkGroupsY() + ? Attr->getMaxNumWorkGroupsY() + ->EvaluateKnownConstInt(M.getContext()) + .getExtValue() + : 1; + uint32_t Z = Attr->getMaxNumWorkGroupsZ() + ? Attr->getMaxNumWorkGroupsZ() + ->EvaluateKnownConstInt(M.getContext()) + .getExtValue() + : 1; + + llvm::SmallString<32> AttrVal; + llvm::raw_svector_ostream OS(AttrVal); + OS << X << ',' << Y << ',' << Z; + + F->addFnAttr("amdgpu-max-num-workgroups", AttrVal.str()); + } } /// Emits control constants used to change per-architecture behaviour in the diff --git a/clang/lib/CodeGen/Targets/PPC.cpp b/clang/lib/CodeGen/Targets/PPC.cpp index 40dddde508c1772da1fcf0475af07b5977b26490..00b04723f17dd2e0a2ed392b57aab43300379c1e 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 = dyn_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. diff --git a/clang/lib/CodeGen/Targets/RISCV.cpp b/clang/lib/CodeGen/Targets/RISCV.cpp index dec6540230a60fb4d29a0aee42b0111c33e3fe18..9a79424c4612ceb45c2f386c28d878d6b66ea655 100644 --- a/clang/lib/CodeGen/Targets/RISCV.cpp +++ b/clang/lib/CodeGen/Targets/RISCV.cpp @@ -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/X86.cpp b/clang/lib/CodeGen/Targets/X86.cpp index 2291c991fb11076632ab6419250d7f0b0f90e2e5..1ec0f159ebcb8af2f5c8a209df4a095708bec83f 100644 --- a/clang/lib/CodeGen/Targets/X86.cpp +++ b/clang/lib/CodeGen/Targets/X86.cpp @@ -3019,6 +3019,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/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp index 190782a79a24562d9058de0b53d8edf16b49cdbe..7a53764364ce4dd91f09e5fc677261a7874f58c1 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()) @@ -6185,6 +6197,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 +6734,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..6e089903a3158a4e79e4cd4f516be2df19d4e6dd 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. + llvm::StringSet<> 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 llvm::StringSet<> &ExplicitValues, + const char *OptionSpelling) { + std::string Option(OptionSpelling); + bool IsFirst = true; + for (const auto &E : ExplicitValues) { + if (!IsFirst) + Option += ","; + + IsFirst = false; + Option += E.first(); + } + 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..86a287db72a4eb8a95522aab0d7e102e6ff669ec 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -2687,60 +2687,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 +2775,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 +2791,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 +2818,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 +3311,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)) @@ -5804,8 +5863,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()) { @@ -7199,6 +7258,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // -fno-common is the default, set -fcommon only when that flag is set. Args.addOptInFlag(CmdArgs, options::OPT_fcommon, options::OPT_fno_common); + if (Args.hasFlag(options::OPT_fptrauth_intrinsics, + options::OPT_fno_ptrauth_intrinsics, false)) + CmdArgs.push_back("-fptrauth-intrinsics"); + // -fsigned-bitfields is default, and clang doesn't yet support // -funsigned-bitfields. if (!Args.hasFlag(options::OPT_fsigned_bitfields, @@ -8477,6 +8540,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/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp index 100e71245394d845430bb371ff289d53c5e4af92..6b1fbba7abd031574e306805ef2fddceb9503c7f 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; } @@ -1141,7 +1142,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)); @@ -2829,7 +2834,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/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/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/HLSL.cpp b/clang/lib/Driver/ToolChains/HLSL.cpp index c6ad862b229420b79a852660104d74bf0fe7c349..05aac9caa7fb296f893318e2f59d9706ab151f6d 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); } 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/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..46ed5baaeaceadc7ad739e657de60a2c6eb63641 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", @@ -1120,6 +1102,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 +1410,7 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) { LLVMStyle.AlignConsecutiveDeclarations = {}; LLVMStyle.AlignConsecutiveMacros = {}; LLVMStyle.AlignConsecutiveShortCaseStatements = {}; + LLVMStyle.AlignConsecutiveTableGenBreakingDAGArgColons = {}; LLVMStyle.AlignConsecutiveTableGenCondOperatorColons = {}; LLVMStyle.AlignConsecutiveTableGenDefinitionColons = {}; LLVMStyle.AlignEscapedNewlines = FormatStyle::ENAS_Right; @@ -1580,6 +1567,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..2ddcd5259446f6e4ba08d7892fbd93612454c49c 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) \ 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..4c83a7a3a323be59d4c11445665c854a3205f018 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; @@ -2704,10 +2753,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 +2788,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 +3644,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 +3690,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 +4322,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 +4356,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 +4395,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 +4413,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 +4482,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 +4505,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 +4677,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); } @@ -5077,12 +5144,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)) { @@ -5459,6 +5533,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 +5959,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..710bf8d8a8ec700d8323435436f9ea02006acd06 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(); } @@ -981,6 +982,11 @@ void WhitespaceManager::alignConsecutiveShortCaseStatements() { Changes); } +void WhitespaceManager::alignConsecutiveTableGenBreakingDAGArgColons() { + alignConsecutiveColons(Style.AlignConsecutiveTableGenBreakingDAGArgColons, + TT_TableGenDAGArgListColonToAlign); +} + void WhitespaceManager::alignConsecutiveTableGenCondOperatorColons() { alignConsecutiveColons(Style.AlignConsecutiveTableGenCondOperatorColons, TT_TableGenCondOperatorColon); @@ -1485,7 +1491,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..019f847ccbaad0278e1ec9b010ea22beb9a7d22d 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. diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index 451bdb9386f58779ef0c6ab4e6e3b96bece176a7..7bd91d4791ecf0b9d9657c9937c0d71940b8837e 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) @@ -3665,7 +3697,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. @@ -4014,6 +4047,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 || @@ -4612,6 +4646,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 +4878,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/FrontendActions.cpp b/clang/lib/Frontend/FrontendActions.cpp index 50338bfa670f8302e529c614d85eb2f82446e858..3fd1cdd3b4794262979ae19f7baed673e8dbc220 100644 --- a/clang/lib/Frontend/FrontendActions.cpp +++ b/clang/lib/Frontend/FrontendActions.cpp @@ -293,11 +293,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 +1083,7 @@ void PrintPreambleAction::ExecuteAction() { case Language::CUDA: case Language::HIP: case Language::HLSL: + case Language::CIR: break; case Language::Unknown: 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..d9f27c0db57ce4ffdf7aa14a2356d2cd11961adc 100644 --- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h +++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h @@ -252,6 +252,116 @@ 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 //===----------------------------------------------------------------------===// @@ -525,6 +635,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 +737,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 +770,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 +803,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 +1147,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 //===----------------------------------------------------------------------===// @@ -1153,6 +1260,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 //===----------------------------------------------------------------------===// @@ -1217,15 +1357,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 //===----------------------------------------------------------------------===// @@ -1274,15 +1405,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 //===----------------------------------------------------------------------===// 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..894db699578f209a3300cd53fa7527b70d1229bd 100644 --- a/clang/lib/InstallAPI/CMakeLists.txt +++ b/clang/lib/InstallAPI/CMakeLists.txt @@ -1,10 +1,12 @@ set(LLVM_LINK_COMPONENTS Support TextAPI + 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..94b8e9cd3233a9213562b243d204208ef1e268e4 --- /dev/null +++ b/clang/lib/InstallAPI/DylibVerifier.cpp @@ -0,0 +1,661 @@ +#include "clang/InstallAPI/DylibVerifier.h" +#include "clang/InstallAPI/FrontendRecords.h" +#include "clang/InstallAPI/InstallAPIDiagnostic.h" +#include "llvm/Demangle/Demangle.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; +}; + +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) { + if (!DiscoveredFirstError) { + Diag->Report(diag::warn_target) + << (PrintArch ? getArchitectureName(Target.Arch) + : getTargetTripleName(Target)); + DiscoveredFirstError = true; + } + + 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; + } + + // All checks at this point classify as some kind of violation that should be + // reported. + + // Regardless of verification mode, error out on mismatched special linker + // symbols. + if (SymbolName.starts_with("$ld$")) { + Ctx.emitDiag([&]() { + Ctx.Diag->Report(diag::err_header_symbol_missing) + << getAnnotatedName(&R, SymCtx, /*ValidSourceLoc=*/false); + }); + 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, /*ValidSourceLoc=*/false); + }); + 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, /*ValidSourceLoc=*/false); + }); + 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::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"); + + 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 0d526fe1da666794d57278cdbbdae9dc4ee4189f..12cd5fcbc22bf73fd40225d8c2b3457efeacf2c7 100644 --- a/clang/lib/InstallAPI/Frontend.cpp +++ b/clang/lib/InstallAPI/Frontend.cpp @@ -8,6 +8,7 @@ #include "clang/InstallAPI/Frontend.h" #include "clang/AST/Availability.h" +#include "clang/InstallAPI/FrontendRecords.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringRef.h" @@ -15,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) { @@ -58,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> diff --git a/clang/lib/InstallAPI/Visitor.cpp b/clang/lib/InstallAPI/Visitor.cpp index aded94f7a94a3227bd6983f74d08ba58bbc7ccc6..452c8f2fb1e489b76666b1657ceb213834524612 100644 --- a/clang/lib/InstallAPI/Visitor.cpp +++ b/clang/lib/InstallAPI/Visitor.cpp @@ -11,7 +11,8 @@ #include "clang/AST/ParentMapContext.h" #include "clang/AST/VTableBuilder.h" #include "clang/Basic/Linkage.h" -#include "clang/InstallAPI/Frontend.h" +#include "clang/InstallAPI/DylibVerifier.h" +#include "clang/InstallAPI/FrontendRecords.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringRef.h" #include "llvm/IR/DataLayout.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,8 +205,8 @@ 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); + auto [Category, FA] = Ctx.Slice->addObjCCategory(InterfaceName, CategoryName, + Avail, D, *Access); recordObjCInstanceVariables(D->getASTContext(), Category, InterfaceName, D->ivars()); return true; @@ -236,8 +240,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; } @@ -287,8 +293,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 +486,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 +500,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 +529,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 +629,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 +651,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 +680,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 +714,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/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/Lex/ModuleMap.cpp b/clang/lib/Lex/ModuleMap.cpp index afb2948f05ae5b4c30073f1b8dc9dad08b0c0be2..10c475f617d48549b2b0943bf8b2851c59a70a4c 100644 --- a/clang/lib/Lex/ModuleMap.cpp +++ b/clang/lib/Lex/ModuleMap.cpp @@ -2498,9 +2498,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) 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..63fe678cbb29e232b49191f82db1ce0023109b56 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()) 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/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/Sema.cpp b/clang/lib/Sema/Sema.cpp index 720d5fd5f0428dda84bc7c90008debb5e0c7ba89..cd0c42d5ffbacd3de3e7a744fa48762293d3cff6 100644 --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -1207,26 +1207,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 +1260,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 +1345,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()), diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index a5f42b630c3fa2459b7d6e360838597d22028186..246e3577809a795f939ea223d739351437b141a7 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -1971,6 +1971,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 +2399,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 +2910,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 +3229,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 +5236,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 +5338,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 +5480,6 @@ bool CheckVectorElementCallArgs(Sema *S, CallExpr *TheCall) { TheCall->getArg(1)->getEndLoc()); retValue = true; } - - if (!retValue) - TheCall->setType(VecTyA->getElementType()); - return retValue; } } @@ -5250,11 +5493,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 +5511,45 @@ 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); +} + +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 +5559,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 +5577,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 +5611,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,7 +5620,9 @@ 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; } } @@ -16351,12 +16664,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 8d75239009401e22a2f57370b2be4f5725852098..73e6baa5278262e29397f9b617e512ffa5d8423c 100644 --- a/clang/lib/Sema/SemaCodeComplete.cpp +++ b/clang/lib/Sema/SemaCodeComplete.cpp @@ -764,6 +764,10 @@ getRequiredQualification(ASTContext &Context, const DeclContext *CurContext, // Filter out names reserved for the implementation if they come from a // system header. static bool shouldIgnoreDueToReservedName(const NamedDecl *ND, Sema &SemaRef) { + // Debuggers want access to all identifiers, including reserved ones. + if (SemaRef.getLangOpts().DebuggerSupport) + return false; + ReservedIdentifierStatus Status = ND->isReserved(SemaRef.getLangOpts()); // Ignore reserved names for compiler provided decls. if (isReservedInAllContexts(Status) && ND->getLocation().isInvalid()) diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp index a8e387e35fb4c90095cb18212f413a34c6b7f87a..1c546e9f5894f024521d2410062e35204f35fa0b 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); diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 1f4a041e88dfff1b2fea8154c549322808beb66d..73ea155053d737f31d9500db4737b17a5b23b0c1 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, @@ -11443,9 +11441,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)) { @@ -16111,7 +16109,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(); diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index c00120b59d396ebaf31c42fc88148f59b9f12576..0a62c656d824ffc47d7c28a989dd5dfa4a13e54b 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)); } @@ -8079,6 +8103,65 @@ static void handleAMDGPUNumVGPRAttr(Sema &S, Decl *D, const ParsedAttr &AL) { D->addAttr(::new (S.Context) AMDGPUNumVGPRAttr(S.Context, AL, NumVGPR)); } +static bool +checkAMDGPUMaxNumWorkGroupsArguments(Sema &S, Expr *XExpr, Expr *YExpr, + Expr *ZExpr, + const AMDGPUMaxNumWorkGroupsAttr &Attr) { + if (S.DiagnoseUnexpandedParameterPack(XExpr) || + (YExpr && S.DiagnoseUnexpandedParameterPack(YExpr)) || + (ZExpr && S.DiagnoseUnexpandedParameterPack(ZExpr))) + return true; + + // Accept template arguments for now as they depend on something else. + // We'll get to check them when they eventually get instantiated. + if (XExpr->isValueDependent() || (YExpr && YExpr->isValueDependent()) || + (ZExpr && ZExpr->isValueDependent())) + return false; + + uint32_t NumWG = 0; + Expr *Exprs[3] = {XExpr, YExpr, ZExpr}; + for (int i = 0; i < 3; i++) { + if (Exprs[i]) { + if (!checkUInt32Argument(S, Attr, Exprs[i], NumWG, i, + /*StrictlyUnsigned=*/true)) + return true; + if (NumWG == 0) { + S.Diag(Attr.getLoc(), diag::err_attribute_argument_is_zero) + << &Attr << Exprs[i]->getSourceRange(); + return true; + } + } + } + + return false; +} + +AMDGPUMaxNumWorkGroupsAttr * +Sema::CreateAMDGPUMaxNumWorkGroupsAttr(const AttributeCommonInfo &CI, + Expr *XExpr, Expr *YExpr, Expr *ZExpr) { + AMDGPUMaxNumWorkGroupsAttr TmpAttr(Context, CI, XExpr, YExpr, ZExpr); + + if (checkAMDGPUMaxNumWorkGroupsArguments(*this, XExpr, YExpr, ZExpr, TmpAttr)) + return nullptr; + + return ::new (Context) + AMDGPUMaxNumWorkGroupsAttr(Context, CI, XExpr, YExpr, ZExpr); +} + +void Sema::addAMDGPUMaxNumWorkGroupsAttr(Decl *D, const AttributeCommonInfo &CI, + Expr *XExpr, Expr *YExpr, + Expr *ZExpr) { + if (auto *Attr = CreateAMDGPUMaxNumWorkGroupsAttr(CI, XExpr, YExpr, ZExpr)) + D->addAttr(Attr); +} + +static void handleAMDGPUMaxNumWorkGroupsAttr(Sema &S, Decl *D, + const ParsedAttr &AL) { + Expr *YExpr = (AL.getNumArgs() > 1) ? AL.getArgAsExpr(1) : nullptr; + Expr *ZExpr = (AL.getNumArgs() > 2) ? AL.getArgAsExpr(2) : nullptr; + S.addAMDGPUMaxNumWorkGroupsAttr(D, AL, AL.getArgAsExpr(0), YExpr, ZExpr); +} + static void handleX86ForceAlignArgPointerAttr(Sema &S, Decl *D, const ParsedAttr &AL) { // If we try to apply it to a function pointer, don't warn, but don't @@ -8473,133 +8556,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, @@ -9183,6 +9247,9 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL, case ParsedAttr::AT_AMDGPUNumVGPR: handleAMDGPUNumVGPRAttr(S, D, AL); break; + case ParsedAttr::AT_AMDGPUMaxNumWorkGroups: + handleAMDGPUMaxNumWorkGroupsAttr(S, D, AL); + break; case ParsedAttr::AT_AVRSignal: handleAVRSignalAttr(S, D, AL); break; @@ -9618,7 +9685,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: diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index e258a4f7c894154a062757bb06924166709df94f..ee732679417e37c5c5584a6591e16f87c2ebd54e 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -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: diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 93f82e68ab644047ec31fbc03150060bda3358f9..5f03b981428251ca23c34d5cd96b4bec370222b2 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -1099,12 +1099,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 +1115,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 +1159,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 +2737,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 +2911,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 +3568,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 +3760,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); @@ -4707,6 +4729,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; 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/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index 0cc0cbacb375489dd7d2d596d81bb7a4dfe8745d..e9ad7bbde0f9b5d71e51e929a825b0e253d43cb3 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 diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index f6bd85bdc64692e3de882b9006694bdf40e505eb..51450e486eaeb45b8ea3e913d7a0ecde6ac268f9 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -6865,6 +6865,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 +6996,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 +7659,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 +8145,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; } diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index d62095558d0ffbd29b1703e8f9fba23153062432..005529a53270c30a25124e94559ed190f32bf86e 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)); @@ -2906,18 +2909,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 @@ -4343,9 +4355,13 @@ QualType Sema::CheckTemplateIdType(TemplateName Name, if (Inst.isInvalid()) return QualType(); - CanonType = SubstType(Pattern->getUnderlyingType(), - TemplateArgLists, AliasTemplate->getLocation(), - AliasTemplate->getDeclName()); + std::optional<ContextRAII> SavedContext; + if (!AliasTemplate->getDeclContext()->isFileContext()) + SavedContext.emplace(*this, AliasTemplate->getDeclContext()); + + CanonType = + SubstType(Pattern->getUnderlyingType(), TemplateArgLists, + AliasTemplate->getLocation(), AliasTemplate->getDeclName()); if (CanonType.isNull()) { // If this was enable_if and we failed to find the nested type // within enable_if in a SFINAE context, dig out the specific @@ -5402,7 +5418,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); } 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 20c2c93ac9c7b415ece248f4119532bde1b0ab5e..dc972018e7b2815042708edf6a3cab1942f096f3 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -607,6 +607,29 @@ static void instantiateDependentAMDGPUWavesPerEUAttr( S.addAMDGPUWavesPerEUAttr(New, Attr, MinExpr, MaxExpr); } +static void instantiateDependentAMDGPUMaxNumWorkGroupsAttr( + Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs, + const AMDGPUMaxNumWorkGroupsAttr &Attr, Decl *New) { + EnterExpressionEvaluationContext Unevaluated( + S, Sema::ExpressionEvaluationContext::ConstantEvaluated); + + ExprResult ResultX = S.SubstExpr(Attr.getMaxNumWorkGroupsX(), TemplateArgs); + if (!ResultX.isUsable()) + return; + ExprResult ResultY = S.SubstExpr(Attr.getMaxNumWorkGroupsY(), TemplateArgs); + if (!ResultY.isUsable()) + return; + ExprResult ResultZ = S.SubstExpr(Attr.getMaxNumWorkGroupsZ(), TemplateArgs); + if (!ResultZ.isUsable()) + return; + + Expr *XExpr = ResultX.getAs<Expr>(); + Expr *YExpr = ResultY.getAs<Expr>(); + Expr *ZExpr = ResultZ.getAs<Expr>(); + + S.addAMDGPUMaxNumWorkGroupsAttr(New, Attr, XExpr, YExpr, ZExpr); +} + // This doesn't take any template parameters, but we have a custom action that // needs to happen when the kernel itself is instantiated. We need to run the // ItaniumMangler to mark the names required to name this kernel. @@ -792,6 +815,12 @@ void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs, *AMDGPUFlatWorkGroupSize, New); } + if (const auto *AMDGPUMaxNumWorkGroups = + dyn_cast<AMDGPUMaxNumWorkGroupsAttr>(TmplAttr)) { + instantiateDependentAMDGPUMaxNumWorkGroupsAttr( + *this, TemplateArgs, *AMDGPUMaxNumWorkGroups, New); + } + if (const auto *ParamAttr = dyn_cast<HLSLParamModifierAttr>(TmplAttr)) { instantiateDependentHLSLParamModifierAttr(*this, TemplateArgs, ParamAttr, New); @@ -1698,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..d7521a5363a3d2c57f4b3dfa313d099973376e44 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -1018,6 +1018,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 +3504,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 +3530,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()); } @@ -6423,9 +6434,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); @@ -6494,6 +6508,9 @@ namespace { void VisitAttributedTypeLoc(AttributedTypeLoc TL) { fillAttributedTypeLoc(TL, State); } + void VisitCountAttributedTypeLoc(CountAttributedTypeLoc TL) { + // nothing + } void VisitBTFTagAttributedTypeLoc(BTFTagAttributedTypeLoc TL) { // nothing } @@ -9745,6 +9762,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..80a10647ca5d331a1fdd70edf2802eb73bbc7f15 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -7269,6 +7269,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 +13742,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..28e8d27fef08c6f955e622c488cc7ae0fba29749 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -6995,6 +6995,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 +9120,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/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index 3653d94c6e073964eac259647f47059a90c0751c..221409d011a38cc32f553411dda43ca11cb53e7e 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -514,6 +514,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. } 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/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/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/StreamChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp index 10972158f3986232db1dd2d9c0a5a0415a6b9e97..902c42a2799be46da90a4d179743cea8d5c5d5b1 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)); } 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/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/CoreEngine.cpp b/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp index 141d0cb320bffab360efd622b44ceb9229a94013..8605fa149e4f52c4a3f47bf56ec7c5af50698ee9 100644 --- a/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp +++ b/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp @@ -625,8 +625,8 @@ ExplodedNode* NodeBuilder::generateNodeImpl(const ProgramPoint &Loc, bool MarkAsSink) { HasGeneratedNodes = true; bool IsNew; - ExplodedNode *N = C.Eng.G.getNode(Loc, State, MarkAsSink, &IsNew); - N->addPredecessor(FromN, C.Eng.G); + ExplodedNode *N = C.getEngine().G.getNode(Loc, State, MarkAsSink, &IsNew); + N->addPredecessor(FromN, C.getEngine().G); Frontier.erase(FromN); if (!IsNew) @@ -655,7 +655,7 @@ ExplodedNode *BranchNodeBuilder::generateNode(ProgramStateRef State, if (!isFeasible(branch)) return nullptr; - ProgramPoint Loc = BlockEdge(C.Block, branch ? DstT:DstF, + ProgramPoint Loc = BlockEdge(C.getBlock(), branch ? DstT : DstF, NodePred->getLocationContext()); ExplodedNode *Succ = generateNodeImpl(Loc, State, NodePred); return Succ; 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..a8e573f7982b12a1eaf336d9fbca06d844d4bfde 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(); } 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/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 2b882f8a5e0793da3aba44ae0bcea4080e4fd9c3..33b43417a6613d8dda6a65d1924960abd86bca11 100644 --- a/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp +++ b/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp @@ -296,7 +296,7 @@ public: DisableFree(DisableFree), ModuleName(ModuleName) {} bool runInvocation(std::shared_ptr<CompilerInvocation> Invocation, - FileManager *FileMgr, + FileManager *DriverFileMgr, std::shared_ptr<PCHContainerOperations> PCHContainerOps, DiagnosticConsumer *DiagConsumer) override { // Make a deep copy of the original Clang invocation. @@ -342,12 +342,13 @@ public: ScanInstance.getHeaderSearchOpts().ModulesIncludeVFSUsage = any(OptimizeArgs & ScanningOptimizations::VFS); - ScanInstance.setFileManager(FileMgr); // Support for virtual file system overlays. - FileMgr->setVirtualFileSystem(createVFSFromCompilerInvocation( + auto FS = createVFSFromCompilerInvocation( ScanInstance.getInvocation(), ScanInstance.getDiagnostics(), - FileMgr->getVirtualFileSystemPtr())); + DriverFileMgr->getVirtualFileSystemPtr()); + // Create a new FileManager to match the invocation's FileSystemOptions. + auto *FileMgr = ScanInstance.createFileManager(FS); ScanInstance.createSourceManager(*FileMgr); // Store the list of prebuilt module files into header search options. This @@ -371,7 +372,8 @@ public: -> std::optional<ArrayRef<dependency_directives_scan::Directive>> { if (llvm::ErrorOr<EntryRef> Entry = LocalDepFS->getOrCreateFileSystemEntry(File.getName())) - return Entry->getDirectiveTokens(); + if (LocalDepFS->ensureDirectiveTokensArePopulated(*Entry)) + return Entry->getDirectiveTokens(); return std::nullopt; }; } @@ -624,9 +626,8 @@ bool DependencyScanningWorker::computeDependencies( ModifiedCommandLine ? *ModifiedCommandLine : CommandLine; auto &FinalFS = ModifiedFS ? ModifiedFS : BaseFS; - FileSystemOptions FSOpts; - FSOpts.WorkingDir = WorkingDirectory.str(); - auto FileMgr = llvm::makeIntrusiveRefCnt<FileManager>(FSOpts, FinalFS); + auto FileMgr = + llvm::makeIntrusiveRefCnt<FileManager>(FileSystemOptions{}, FinalFS); std::vector<const char *> FinalCCommandLine(FinalCommandLine.size(), nullptr); llvm::transform(FinalCommandLine, FinalCCommandLine.begin(), 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/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/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.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/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/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/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/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/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/working-directory-option.c b/clang/test/ClangScanDeps/working-directory-option.c new file mode 100644 index 0000000000000000000000000000000000000000..d57497d405d30f242c5e40000183d1a9d6c139ae --- /dev/null +++ b/clang/test/ClangScanDeps/working-directory-option.c @@ -0,0 +1,30 @@ +// Test that -working-directory works even when it differs from the working +// directory of the filesystem. + +// RUN: rm -rf %t +// RUN: mkdir -p %t/other +// RUN: split-file %s %t +// RUN: sed -e "s|DIR|%/t|g" %t/cdb.json.template > %t/cdb.json + +// RUN: clang-scan-deps -compilation-database %t/cdb.json -format experimental-full \ +// RUN: > %t/deps.json + +// RUN: cat %t/deps.json | sed 's:\\\\\?:/:g' | FileCheck %s -DPREFIX=%/t + +// CHECK: "file-deps": [ +// CHECK-NEXT: "[[PREFIX]]/cwd/t.c" +// CHECK-NEXT: "[[PREFIX]]/cwd/relative/h1.h" +// CHECK-NEXT: ] +// CHECK-NEXT: "input-file": "[[PREFIX]]/cwd/t.c" + +//--- cdb.json.template +[{ + "directory": "DIR/other", + "command": "clang -c t.c -I relative -working-directory DIR/cwd", + "file": "DIR/cwd/t.c" +}] + +//--- cwd/relative/h1.h + +//--- cwd/t.c +#include "h1.h" diff --git a/clang/test/CodeCompletion/ordinary-name.c b/clang/test/CodeCompletion/ordinary-name.c index c8181a248daa2fae964aca9ae337c731392deb0b..9398561920617308f921c61f2abb5a0910f8abc8 100644 --- a/clang/test/CodeCompletion/ordinary-name.c +++ b/clang/test/CodeCompletion/ordinary-name.c @@ -5,6 +5,7 @@ typedef struct t _TYPEDEF; void foo() { int y; // RUN: %clang_cc1 -isystem %S/Inputs -fsyntax-only -code-completion-at=%s:%(line-1):9 %s -o - | FileCheck -check-prefix=CHECK-CC1 %s + // CHECK-CC1-NOT: __builtin_va_list // CHECK-CC1-NOT: __INTEGER_TYPE // CHECK-CC1: _Imaginary // CHECK-CC1: _MyPrivateType @@ -15,4 +16,8 @@ void foo() { // CHECK-CC1: y // PR8744 - // RUN: %clang_cc1 -isystem %S/Inputs -fsyntax-only -code-completion-at=%s:%(line-17):11 %s + // RUN: %clang_cc1 -isystem %S/Inputs -fsyntax-only -code-completion-at=%s:%(line-18):11 %s + + // RUN: %clang_cc1 -isystem %S/Inputs -fsyntax-only -fdebugger-support -code-completion-at=%s:%(line-15):9 %s -o - | FileCheck -check-prefix=CHECK-DBG %s + // CHECK-DBG: __builtin_va_list + // CHECK-DBG: __INTEGER_TYPE 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/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/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/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/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/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-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/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..94095f9aa3e1f4e6f1f9d217e4d7ae3930c8f670 100644 --- a/clang/test/CodeGen/attr-target-clones-aarch64.c +++ b/clang/test/CodeGen/attr-target-clones-aarch64.c @@ -23,8 +23,6 @@ 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 @@ -177,15 +175,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 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/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/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/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/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/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/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/CodeGenCUDA/amdgpu-kernel-attrs.cu b/clang/test/CodeGenCUDA/amdgpu-kernel-attrs.cu index a1642421af2c8c096cbeb15354d3d46bf42bc859..11a133fd1351d2ba76180947ac2010b42df28cb8 100644 --- a/clang/test/CodeGenCUDA/amdgpu-kernel-attrs.cu +++ b/clang/test/CodeGenCUDA/amdgpu-kernel-attrs.cu @@ -40,12 +40,45 @@ __attribute__((amdgpu_num_vgpr(64))) // expected-no-diagnostics __global__ void num_vgpr_64() { // CHECK: define{{.*}} amdgpu_kernel void @_Z11num_vgpr_64v() [[NUM_VGPR_64:#[0-9]+]] } +__attribute__((amdgpu_max_num_work_groups(32, 4, 2))) // expected-no-diagnostics +__global__ void max_num_work_groups_32_4_2() { +// CHECK: define{{.*}} amdgpu_kernel void @_Z26max_num_work_groups_32_4_2v() [[MAX_NUM_WORK_GROUPS_32_4_2:#[0-9]+]] +} +__attribute__((amdgpu_max_num_work_groups(32))) // expected-no-diagnostics +__global__ void max_num_work_groups_32() { +// CHECK: define{{.*}} amdgpu_kernel void @_Z22max_num_work_groups_32v() [[MAX_NUM_WORK_GROUPS_32_1_1:#[0-9]+]] +} +__attribute__((amdgpu_max_num_work_groups(32,1))) // expected-no-diagnostics +__global__ void max_num_work_groups_32_1() { +// CHECK: define{{.*}} amdgpu_kernel void @_Z24max_num_work_groups_32_1v() [[MAX_NUM_WORK_GROUPS_32_1_1:#[0-9]+]] +} + + + +template<unsigned a> +__attribute__((amdgpu_max_num_work_groups(a, 4, 2))) +__global__ void template_a_4_2_max_num_work_groups() {} +template __global__ void template_a_4_2_max_num_work_groups<32>(); +// CHECK: define{{.*}} amdgpu_kernel void @_Z34template_a_4_2_max_num_work_groupsILj32EEvv() [[MAX_NUM_WORK_GROUPS_32_4_2:#[0-9]+]] + +template<unsigned a> +__attribute__((amdgpu_max_num_work_groups(32, a, 2))) +__global__ void template_32_a_2_max_num_work_groups() {} +template __global__ void template_32_a_2_max_num_work_groups<4>(); +// CHECK: define{{.*}} amdgpu_kernel void @_Z35template_32_a_2_max_num_work_groupsILj4EEvv() [[MAX_NUM_WORK_GROUPS_32_4_2:#[0-9]+]] + +template<unsigned a> +__attribute__((amdgpu_max_num_work_groups(32, 4, a))) +__global__ void template_32_4_a_max_num_work_groups() {} +template __global__ void template_32_4_a_max_num_work_groups<2>(); +// CHECK: define{{.*}} amdgpu_kernel void @_Z35template_32_4_a_max_num_work_groupsILj2EEvv() [[MAX_NUM_WORK_GROUPS_32_4_2:#[0-9]+]] // Make sure this is silently accepted on other targets. // NAMD-NOT: "amdgpu-flat-work-group-size" // NAMD-NOT: "amdgpu-waves-per-eu" // NAMD-NOT: "amdgpu-num-vgpr" // NAMD-NOT: "amdgpu-num-sgpr" +// NAMD-NOT: "amdgpu-max-num-work-groups" // DEFAULT-DAG: attributes [[FLAT_WORK_GROUP_SIZE_DEFAULT]] = {{.*}}"amdgpu-flat-work-group-size"="1,1024"{{.*}}"uniform-work-group-size"="true" // MAX1024-DAG: attributes [[FLAT_WORK_GROUP_SIZE_DEFAULT]] = {{.*}}"amdgpu-flat-work-group-size"="1,1024" @@ -53,5 +86,7 @@ __global__ void num_vgpr_64() { // CHECK-DAG: attributes [[WAVES_PER_EU_2]] = {{.*}}"amdgpu-waves-per-eu"="2" // CHECK-DAG: attributes [[NUM_SGPR_32]] = {{.*}}"amdgpu-num-sgpr"="32" // CHECK-DAG: attributes [[NUM_VGPR_64]] = {{.*}}"amdgpu-num-vgpr"="64" +// CHECK-DAG: attributes [[MAX_NUM_WORK_GROUPS_32_4_2]] = {{.*}}"amdgpu-max-num-workgroups"="32,4,2" +// CHECK-DAG: attributes [[MAX_NUM_WORK_GROUPS_32_1_1]] = {{.*}}"amdgpu-max-num-workgroups"="32,1,1" // NOUB-NOT: "uniform-work-group-size"="true" 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-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/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/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..f0177906a09a810c8fa9a226dc14f076b62248db --- /dev/null +++ b/clang/test/CodeGenCXX/x86_64-vaarg.cpp @@ -0,0 +1,23 @@ +// 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 +// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -x c -o - %s | FileCheck %s + +typedef struct { struct {} a; } empty; + +// CHECK-LABEL: @{{.*}}empty_record_test +// 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(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 {{.*}}, 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); +} 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/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..0f993193c00cce41d45a369118b4bb326f304164 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); } 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/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/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-attrs.cl b/clang/test/CodeGenOpenCL/amdgpu-attrs.cl index b0dfc97b53b2c5345773e8205bb87fcdf3685bf7..5648bc13458e1a09bfde3ba77a490e6e000ad037 100644 --- a/clang/test/CodeGenOpenCL/amdgpu-attrs.cl +++ b/clang/test/CodeGenOpenCL/amdgpu-attrs.cl @@ -139,6 +139,46 @@ kernel void reqd_work_group_size_32_2_1_flat_work_group_size_16_128() { // CHECK: define{{.*}} amdgpu_kernel void @reqd_work_group_size_32_2_1_flat_work_group_size_16_128() [[FLAT_WORK_GROUP_SIZE_16_128:#[0-9]+]] } +__attribute__((amdgpu_max_num_work_groups(1, 1, 1))) // expected-no-diagnostics +kernel void max_num_work_groups_1_1_1() { +// CHECK: define{{.*}} amdgpu_kernel void @max_num_work_groups_1_1_1() [[MAX_NUM_WORK_GROUPS_1_1_1:#[0-9]+]] +} + +__attribute__((amdgpu_max_num_work_groups(32, 1, 1))) // expected-no-diagnostics +kernel void max_num_work_groups_32_1_1() { +// CHECK: define{{.*}} amdgpu_kernel void @max_num_work_groups_32_1_1() [[MAX_NUM_WORK_GROUPS_32_1_1:#[0-9]+]] +} + +__attribute__((amdgpu_max_num_work_groups(32, 8, 1))) // expected-no-diagnostics +kernel void max_num_work_groups_32_8_1() { +// CHECK: define{{.*}} amdgpu_kernel void @max_num_work_groups_32_8_1() [[MAX_NUM_WORK_GROUPS_32_8_1:#[0-9]+]] +} + +__attribute__((amdgpu_max_num_work_groups(1, 1, 32))) // expected-no-diagnostics +kernel void max_num_work_groups_1_1_32() { +// CHECK: define{{.*}} amdgpu_kernel void @max_num_work_groups_1_1_32() [[MAX_NUM_WORK_GROUPS_1_1_32:#[0-9]+]] +} + +__attribute__((amdgpu_max_num_work_groups(1, 8, 32))) // expected-no-diagnostics +kernel void max_num_work_groups_1_8_32() { +// CHECK: define{{.*}} amdgpu_kernel void @max_num_work_groups_1_8_32() [[MAX_NUM_WORK_GROUPS_1_8_32:#[0-9]+]] +} + +__attribute__((amdgpu_max_num_work_groups(4, 8, 32))) // expected-no-diagnostics +kernel void max_num_work_groups_4_8_32() { +// CHECK: define{{.*}} amdgpu_kernel void @max_num_work_groups_4_8_32() [[MAX_NUM_WORK_GROUPS_4_8_32:#[0-9]+]] +} + +__attribute__((amdgpu_max_num_work_groups(32))) // expected-no-diagnostics +kernel void max_num_work_groups_32() { +// CHECK: define{{.*}} amdgpu_kernel void @max_num_work_groups_32() [[MAX_NUM_WORK_GROUPS_32_1_1:#[0-9]+]] +} + +__attribute__((amdgpu_max_num_work_groups(32,1))) // expected-no-diagnostics +kernel void max_num_work_groups_32_1() { +// CHECK: define{{.*}} amdgpu_kernel void @max_num_work_groups_32_1() [[MAX_NUM_WORK_GROUPS_32_1_1:#[0-9]+]] +} + void a_function() { // CHECK: define{{.*}} void @a_function() [[A_FUNCTION:#[0-9]+]] } @@ -189,5 +229,12 @@ kernel void default_kernel() { // CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_WAVES_PER_EU_2_NUM_SGPR_32_NUM_VGPR_64]] = {{.*}} "amdgpu-flat-work-group-size"="32,64" "amdgpu-num-sgpr"="32" "amdgpu-num-vgpr"="64" "amdgpu-waves-per-eu"="2" // CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_WAVES_PER_EU_2_4_NUM_SGPR_32_NUM_VGPR_64]] = {{.*}} "amdgpu-flat-work-group-size"="32,64" "amdgpu-num-sgpr"="32" "amdgpu-num-vgpr"="64" "amdgpu-waves-per-eu"="2,4" +// CHECK-DAG: attributes [[MAX_NUM_WORK_GROUPS_1_1_1]] = {{.*}} "amdgpu-max-num-workgroups"="1,1,1" +// CHECK-DAG: attributes [[MAX_NUM_WORK_GROUPS_32_1_1]] = {{.*}} "amdgpu-max-num-workgroups"="32,1,1" +// CHECK-DAG: attributes [[MAX_NUM_WORK_GROUPS_32_8_1]] = {{.*}} "amdgpu-max-num-workgroups"="32,8,1" +// CHECK-DAG: attributes [[MAX_NUM_WORK_GROUPS_1_1_32]] = {{.*}} "amdgpu-max-num-workgroups"="1,1,32" +// CHECK-DAG: attributes [[MAX_NUM_WORK_GROUPS_1_8_32]] = {{.*}} "amdgpu-max-num-workgroups"="1,8,32" +// CHECK-DAG: attributes [[MAX_NUM_WORK_GROUPS_4_8_32]] = {{.*}} "amdgpu-max-num-workgroups"="4,8,32" + // CHECK-DAG: attributes [[A_FUNCTION]] = {{.*}} // CHECK-DAG: attributes [[DEFAULT_KERNEL_ATTRS]] = {{.*}} "amdgpu-flat-work-group-size"="1,256" 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..4363769b864571bded723c97ea7ea95d56b0b8f8 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 @@ -6,21 +6,22 @@ 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 __bf16 v8bf16 __attribute__((ext_vector_type(8))); typedef half v4h __attribute__((ext_vector_type(4))); typedef short v4s __attribute__((ext_vector_type(4))); +typedef __bf16 v4bf16 __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 v8h* v8h_inptr, global v8bf16* v8bf16_inptr, + global int* int_inptr, global v4s* v4s_inptr, global v4h* v4h_inptr, global v4bf16* v4bf16_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}} - - 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}} + 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}} + v8h out_3 = __builtin_amdgcn_global_load_tr_b128_v8f16(v8h_inptr); // expected-error{{'__builtin_amdgcn_global_load_tr_b128_v8f16' needs target feature gfx12-insts,wavefrontsize32}} + v8bf16 o4 = __builtin_amdgcn_global_load_tr_b128_v8bf16(v8bf16_inptr); // expected-error{{'__builtin_amdgcn_global_load_tr_b128_v8bf16' needs target feature gfx12-insts,wavefrontsize32}} + + int out_5 = __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_6 = __builtin_amdgcn_global_load_tr_b128_v4i16(v4s_inptr); // expected-error{{'__builtin_amdgcn_global_load_tr_b128_v4i16' needs target feature gfx12-insts,wavefrontsize64}} + v4h out_7 = __builtin_amdgcn_global_load_tr_b128_v4f16(v4h_inptr); // expected-error{{'__builtin_amdgcn_global_load_tr_b128_v4f16' needs target feature gfx12-insts,wavefrontsize64}} + v4bf16 o8 = __builtin_amdgcn_global_load_tr_b128_v4bf16(v4bf16_inptr); // expected-error{{'__builtin_amdgcn_global_load_tr_b128_v4bf16' 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..208f92fc5d44f3ffcd4d25dc063c8b9c3bc2c55f 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 @@ -5,11 +5,12 @@ typedef half v4h __attribute__((ext_vector_type(4))); typedef short v4s __attribute__((ext_vector_type(4))); +typedef __bf16 v4bf16 __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, global v4h* v4h_inptr, global v4bf16* v4bf16_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}} + v4h out_3 = __builtin_amdgcn_global_load_tr_b128_v4f16(v4h_inptr); // expected-error{{'__builtin_amdgcn_global_load_tr_b128_v4f16' needs target feature gfx12-insts,wavefrontsize64}} + v4bf16 o4 = __builtin_amdgcn_global_load_tr_b128_v4bf16(v4bf16_inptr); // expected-error{{'__builtin_amdgcn_global_load_tr_b128_v4bf16' 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..199146a9715da6c03057a349472dc31c08803fa5 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 @@ -6,11 +6,12 @@ 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 __bf16 v8bf16 __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, global v8h* v8h_inptr, global v8bf16* v8bf16_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}} + v8h out_3 = __builtin_amdgcn_global_load_tr_b128_v8f16(v8h_inptr); // expected-error{{'__builtin_amdgcn_global_load_tr_b128_v8f16' needs target feature gfx12-insts,wavefrontsize32}} + v8bf16 o4 = __builtin_amdgcn_global_load_tr_b128_v8bf16(v8bf16_inptr); // expected-error{{'__builtin_amdgcn_global_load_tr_b128_v8bf16' 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..0035b16b902b68d4fc09bdc600cfd1711b684466 100644 --- a/clang/test/CodeGenOpenCL/builtins-amdgcn-global-load-tr-w32.cl +++ b/clang/test/CodeGenOpenCL/builtins-amdgcn-global-load-tr-w32.cl @@ -5,44 +5,44 @@ 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 __bf16 v8bf16 __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: 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: 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-LABEL: @test_amdgcn_global_load_tr_b128_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) +v8h test_amdgcn_global_load_tr_b128_v8f16(global v8h* inptr) { - return __builtin_amdgcn_global_load_tr_v8f16(inptr); + return __builtin_amdgcn_global_load_tr_b128_v8f16(inptr); } +// CHECK-GFX1200-LABEL: @test_amdgcn_global_load_tr_b128_v8bf16( +// CHECK-GFX1200-NEXT: entry: +// CHECK-GFX1200-NEXT: [[TMP0:%.*]] = tail call <8 x bfloat> @llvm.amdgcn.global.load.tr.v8bf16(ptr addrspace(1) [[INPTR:%.*]]) +// CHECK-GFX1200-NEXT: ret <8 x bfloat> [[TMP0]] +// +v8bf16 test_amdgcn_global_load_tr_b128_v8bf16(global v8bf16* inptr) +{ + return __builtin_amdgcn_global_load_tr_b128_v8bf16(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..6c025bb5a55a360f71afe530897eaa5ec92402ca 100644 --- a/clang/test/CodeGenOpenCL/builtins-amdgcn-global-load-tr-w64.cl +++ b/clang/test/CodeGenOpenCL/builtins-amdgcn-global-load-tr-w64.cl @@ -4,44 +4,44 @@ typedef half v4h __attribute__((ext_vector_type(4))); typedef short v4s __attribute__((ext_vector_type(4))); +typedef __bf16 v4bf16 __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: 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: 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-LABEL: @test_amdgcn_global_load_tr_b128_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) +v4h test_amdgcn_global_load_tr_b128_v4f16(global v4h* inptr) { - return __builtin_amdgcn_global_load_tr_v4f16(inptr); + return __builtin_amdgcn_global_load_tr_b128_v4f16(inptr); } +// CHECK-GFX1200-LABEL: @test_amdgcn_global_load_tr_b128_v4bf16( +// CHECK-GFX1200-NEXT: entry: +// CHECK-GFX1200-NEXT: [[TMP0:%.*]] = tail call <4 x bfloat> @llvm.amdgcn.global.load.tr.v4bf16(ptr addrspace(1) [[INPTR:%.*]]) +// CHECK-GFX1200-NEXT: ret <4 x bfloat> [[TMP0]] +// +v4bf16 test_amdgcn_global_load_tr_b128_v4bf16(global v4bf16* inptr) +{ + return __builtin_amdgcn_global_load_tr_b128_v4bf16(inptr); +} 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-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/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/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/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/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/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/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/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/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/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/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..052956dfa2dcea5d9e5e8e7a5f275aaadf3fa553 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,8 +35,6 @@ // 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 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/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..80d92ee1a90b4bcb29312613b20601e019ff229a --- /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=g2,g1" + +// 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/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/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/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/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/pragma-attribute-supported-attributes-list.test b/clang/test/Misc/pragma-attribute-supported-attributes-list.test index ec84ebdc6abe7b494931e6f6bf6031170a52cd83..318bfb2df2a7aaf0838579cbdc91d438dc87b03e 100644 --- a/clang/test/Misc/pragma-attribute-supported-attributes-list.test +++ b/clang/test/Misc/pragma-attribute-supported-attributes-list.test @@ -4,6 +4,7 @@ // CHECK: #pragma clang attribute supports the following attributes: // CHECK-NEXT: AMDGPUFlatWorkGroupSize (SubjectMatchRule_function) +// CHECK-NEXT: AMDGPUMaxNumWorkGroups (SubjectMatchRule_function) // CHECK-NEXT: AMDGPUNumSGPR (SubjectMatchRule_function) // CHECK-NEXT: AMDGPUNumVGPR (SubjectMatchRule_function) // CHECK-NEXT: AMDGPUWavesPerEU (SubjectMatchRule_function) 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/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-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/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/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..9f8a8bdeeb9cb047d2bec0b1f6c346ad5ffe4ed1 100644 --- a/clang/test/Preprocessor/aarch64-target-features.c +++ b/clang/test/Preprocessor/aarch64-target-features.c @@ -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 ff4d00ac3bcfcc1d4c36571e559199a661588f92..246cbfa2d6ab7db1d52c925e69c72c9e2aac0ba3 100644 --- a/clang/test/Preprocessor/bpf-predefined-macros.c +++ b/clang/test/Preprocessor/bpf-predefined-macros.c @@ -61,6 +61,9 @@ int r; #ifdef __BPF_FEATURE_ST int s; #endif +#ifdef __BPF_FEATURE_ADDR_SPACE_CAST +int t; +#endif // CHECK: int b; // CHECK: int c; @@ -90,6 +93,11 @@ int s; // CPU_V4: int r; // CPU_V4: int s; +// CPU_V1: int t; +// CPU_V2: int t; +// CPU_V3: int t; +// CPU_V4: int t; + // CPU_GENERIC: int g; // CPU_PROBE: int f; 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/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-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/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/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/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/SemaCUDA/amdgpu-attrs.cu b/clang/test/SemaCUDA/amdgpu-attrs.cu index 4811ef796c66b39a7ccebd30508310be53bd8aa4..e04b32d121bc8cd959ded0abfaf061238762c742 100644 --- a/clang/test/SemaCUDA/amdgpu-attrs.cu +++ b/clang/test/SemaCUDA/amdgpu-attrs.cu @@ -63,6 +63,16 @@ __global__ void flat_work_group_size_32_64_waves_per_eu_2_num_sgpr_32_num_vgpr_6 __attribute__((amdgpu_flat_work_group_size(32, 64), amdgpu_waves_per_eu(2, 4), amdgpu_num_sgpr(32), amdgpu_num_vgpr(64))) __global__ void flat_work_group_size_32_64_waves_per_eu_2_4_num_sgpr_32_num_vgpr_64() {} +__attribute__((amdgpu_max_num_work_groups(32, 1, 1))) +__global__ void max_num_work_groups_32_1_1() {} + +__attribute__((amdgpu_max_num_work_groups(32, 1, 1), amdgpu_flat_work_group_size(32, 64))) +__global__ void max_num_work_groups_32_1_1_flat_work_group_size_32_64() {} + +__attribute__((amdgpu_max_num_work_groups(32, 1, 1), amdgpu_flat_work_group_size(32, 64), amdgpu_waves_per_eu(2, 4), amdgpu_num_sgpr(32), amdgpu_num_vgpr(64))) +__global__ void max_num_work_groups_32_1_1_flat_work_group_size_32_64_waves_per_eu_2_4_num_sgpr_32_num_vgpr_64() {} + + // expected-error@+2{{attribute 'reqd_work_group_size' can only be applied to an OpenCL kernel function}} __attribute__((reqd_work_group_size(32, 64, 64))) __global__ void reqd_work_group_size_32_64_64() {} @@ -194,3 +204,125 @@ __global__ void non_cexpr_waves_per_eu_2() {} // expected-error@+1{{'amdgpu_waves_per_eu' attribute requires parameter 1 to be an integer constant}} __attribute__((amdgpu_waves_per_eu(2, ipow2(2)))) __global__ void non_cexpr_waves_per_eu_2_4() {} + +__attribute__((amdgpu_max_num_work_groups(32))) +__global__ void max_num_work_groups_32() {} + +__attribute__((amdgpu_max_num_work_groups(32, 1))) +__global__ void max_num_work_groups_32_1() {} + +// expected-error@+1{{'amdgpu_max_num_work_groups' attribute takes no more than 3 arguments}} +__attribute__((amdgpu_max_num_work_groups(32, 1, 1, 1))) +__global__ void max_num_work_groups_32_1_1_1() {} + +// expected-error@+1{{'amdgpu_max_num_work_groups' attribute takes at least 1 argument}} +__attribute__((amdgpu_max_num_work_groups())) +__global__ void max_num_work_groups_no_arg() {} + +// expected-error@+1{{expected expression}} +__attribute__((amdgpu_max_num_work_groups(,1,1))) +__global__ void max_num_work_groups_empty_1_1() {} + +// expected-error@+1{{expected expression}} +__attribute__((amdgpu_max_num_work_groups(32,,1))) +__global__ void max_num_work_groups_32_empty_1() {} + +// expected-error@+1{{'amdgpu_max_num_work_groups' attribute requires parameter 0 to be an integer constant}} +__attribute__((amdgpu_max_num_work_groups(ipow2(5), 1, 1))) +__global__ void max_num_work_groups_32_1_1_non_int_arg0() {} + +// expected-error@+1{{'amdgpu_max_num_work_groups' attribute requires parameter 1 to be an integer constant}} +__attribute__((amdgpu_max_num_work_groups(32, "1", 1))) +__global__ void max_num_work_groups_32_1_1_non_int_arg1() {} + +// expected-error@+1{{'amdgpu_max_num_work_groups' attribute requires a non-negative integral compile time constant expression}} +__attribute__((amdgpu_max_num_work_groups(-32, 1, 1))) +__global__ void max_num_work_groups_32_1_1_neg_int_arg0() {} + +// expected-error@+1{{'amdgpu_max_num_work_groups' attribute requires a non-negative integral compile time constant expression}} +__attribute__((amdgpu_max_num_work_groups(32, -1, 1))) +__global__ void max_num_work_groups_32_1_1_neg_int_arg1() {} + +// expected-error@+1{{'amdgpu_max_num_work_groups' attribute requires a non-negative integral compile time constant expression}} +__attribute__((amdgpu_max_num_work_groups(32, 1, -1))) +__global__ void max_num_work_groups_32_1_1_neg_int_arg2() {} + +// expected-error@+1{{'amdgpu_max_num_work_groups' attribute must be greater than 0}} +__attribute__((amdgpu_max_num_work_groups(0, 1, 1))) +__global__ void max_num_work_groups_0_1_1() {} + +// expected-error@+1{{'amdgpu_max_num_work_groups' attribute must be greater than 0}} +__attribute__((amdgpu_max_num_work_groups(32, 0, 1))) +__global__ void max_num_work_groups_32_0_1() {} + +// expected-error@+1{{'amdgpu_max_num_work_groups' attribute must be greater than 0}} +__attribute__((amdgpu_max_num_work_groups(32, 1, 0))) +__global__ void max_num_work_groups_32_1_0() {} + +__attribute__((amdgpu_max_num_work_groups(4294967295))) +__global__ void max_num_work_groups_max_unsigned_int() {} + +// expected-error@+1{{integer constant expression evaluates to value 4294967296 that cannot be represented in a 32-bit unsigned integer type}} +__attribute__((amdgpu_max_num_work_groups(4294967296))) +__global__ void max_num_work_groups_max_unsigned_int_plus1() {} + +// expected-error@+1{{integer constant expression evaluates to value 10000000000 that cannot be represented in a 32-bit unsigned integer type}} +__attribute__((amdgpu_max_num_work_groups(10000000000))) +__global__ void max_num_work_groups_too_large() {} + +int num_wg_x = 32; +int num_wg_y = 1; +int num_wg_z = 1; +// expected-error@+1{{'amdgpu_max_num_work_groups' attribute requires parameter 0 to be an integer constant}} +__attribute__((amdgpu_max_num_work_groups(num_wg_x, 1, 1))) +__global__ void max_num_work_groups_32_1_1_non_const_arg0() {} + +// expected-error@+1{{'amdgpu_max_num_work_groups' attribute requires parameter 1 to be an integer constant}} +__attribute__((amdgpu_max_num_work_groups(32, num_wg_y, 1))) +__global__ void max_num_work_groups_32_1_1_non_const_arg1() {} + +// expected-error@+1{{'amdgpu_max_num_work_groups' attribute requires parameter 2 to be an integer constant}} +__attribute__((amdgpu_max_num_work_groups(32, 1, num_wg_z))) +__global__ void max_num_work_groups_32_1_1_non_const_arg2() {} + +const int c_num_wg_x = 32; +__attribute__((amdgpu_max_num_work_groups(c_num_wg_x, 1, 1))) +__global__ void max_num_work_groups_32_1_1_const_arg0() {} + +template<unsigned a> +__attribute__((amdgpu_max_num_work_groups(a, 1, 1))) +__global__ void template_a_1_1_max_num_work_groups() {} +template __global__ void template_a_1_1_max_num_work_groups<32>(); + +template<unsigned a> +__attribute__((amdgpu_max_num_work_groups(32, a, 1))) +__global__ void template_32_a_1_max_num_work_groups() {} +template __global__ void template_32_a_1_max_num_work_groups<1>(); + +template<unsigned a> +__attribute__((amdgpu_max_num_work_groups(32, 1, a))) +__global__ void template_32_1_a_max_num_work_groups() {} +template __global__ void template_32_1_a_max_num_work_groups<1>(); + +// expected-error@+3{{'amdgpu_max_num_work_groups' attribute must be greater than 0}} +// expected-note@+4{{in instantiation of}} +template<unsigned b> +__attribute__((amdgpu_max_num_work_groups(b, 1, 1))) +__global__ void template_b_1_1_max_num_work_groups() {} +template __global__ void template_b_1_1_max_num_work_groups<0>(); + +// expected-error@+3{{'amdgpu_max_num_work_groups' attribute must be greater than 0}} +// expected-note@+4{{in instantiation of}} +template<unsigned b> +__attribute__((amdgpu_max_num_work_groups(32, b, 1))) +__global__ void template_32_b_1_max_num_work_groups() {} +template __global__ void template_32_b_1_max_num_work_groups<0>(); + +// expected-error@+3{{'amdgpu_max_num_work_groups' attribute must be greater than 0}} +// expected-note@+4{{in instantiation of}} +template<unsigned b> +__attribute__((amdgpu_max_num_work_groups(32, 1, b))) +__global__ void template_32_1_b_max_num_work_groups() {} +template __global__ void template_32_1_b_max_num_work_groups<0>(); + + 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..3ce26c8fcd984ec8cd5407d08b6b55b7cd7380c9 100644 --- a/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp +++ b/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp @@ -230,3 +230,20 @@ 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 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/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/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/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/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/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/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/SemaTemplate/PR25708.cpp b/clang/test/SemaTemplate/PR25708.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6a214fc6b43bc1d285c453b2b5cfb793983b98d0 --- /dev/null +++ b/clang/test/SemaTemplate/PR25708.cpp @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -std=c++11 -verify %s +// expected-no-diagnostics + +struct FooAccessor +{ + template <typename T> + using Foo = typename T::Foo; +}; + +class Type +{ + friend struct FooAccessor; + + using Foo = int; +}; + +int main() +{ + FooAccessor::Foo<Type> t; +} diff --git a/clang/test/SemaTemplate/concepts.cpp b/clang/test/SemaTemplate/concepts.cpp index bac209a28da912e1e14f29f9313710cf1f749c87..b7ea0d003a52d74a3baf53292fbb505c1d63097c 100644 --- a/clang/test/SemaTemplate/concepts.cpp +++ b/clang/test/SemaTemplate/concepts.cpp @@ -1085,3 +1085,32 @@ 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 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-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 c6da1c80a673f91b6ee9a18d6241da328e3bae28..13061cfa36eeb0a7ea8b2ed992965500cdcb4309 100644 --- a/clang/tools/clang-installapi/ClangInstallAPI.cpp +++ b/clang/tools/clang-installapi/ClangInstallAPI.cpp @@ -14,11 +14,13 @@ #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" #include "llvm/Option/Option.h" @@ -29,8 +31,6 @@ #include "llvm/Support/Process.h" #include "llvm/Support/Signals.h" #include "llvm/TargetParser/Host.h" -#include "llvm/TextAPI/RecordVisitor.h" -#include "llvm/TextAPI/TextAPIWriter.h" #include <memory> using namespace clang; @@ -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. - llvm::MachO::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..87f4c3327e8409bd2771ca79802efa36b59039e0 --- /dev/null +++ b/clang/tools/clang-installapi/InstallAPIOpts.td @@ -0,0 +1,31 @@ +//===--- 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">; diff --git a/clang/tools/clang-installapi/Options.cpp b/clang/tools/clang-installapi/Options.cpp index 701ab81c57c3d0e1b6249aaea043bc2771e9cd9a..b8696bb7896d8662fec1782fcdb5ba42b1f87407 100644 --- a/clang/tools/clang-installapi/Options.cpp +++ b/clang/tools/clang-installapi/Options.cpp @@ -10,35 +10,85 @@ #include "clang/Driver/Driver.h" #include "clang/Frontend/FrontendDiagnostic.h" #include "clang/InstallAPI/FileList.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 +96,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 +105,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 +119,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.IsDylib = Args.hasArg(drv::OPT_dynamiclib); - LinkerOpts.AppExtensionSafe = - Args.hasFlag(OPT_fapplication_extension, OPT_fno_application_extension, - /*Default=*/LinkerOpts.AppExtensionSafe); + 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 +157,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 +171,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 +181,77 @@ bool Options::processFrontendOptions(InputArgList &Args) { 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(); + + /// 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 +261,16 @@ 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"); } InstallAPIContext Options::createContext() { @@ -159,6 +283,7 @@ 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; @@ -168,16 +293,40 @@ InstallAPIContext Options::createContext() { 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; } } + // 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); return Ctx; } diff --git a/clang/tools/clang-installapi/Options.h b/clang/tools/clang-installapi/Options.h index 9d4d841284fd11c18e6a780606929654bfd6c430..2beeafc86bb086ef888990dee6373d17ae13b409 100644 --- a/clang/tools/clang-installapi/Options.h +++ b/clang/tools/clang-installapi/Options.h @@ -11,25 +11,21 @@ #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" #include "llvm/Support/Program.h" #include "llvm/TargetParser/Triple.h" -#include "llvm/TextAPI/Architecture.h" -#include "llvm/TextAPI/InterfaceFile.h" -#include "llvm/TextAPI/PackedVersion.h" -#include "llvm/TextAPI/Platform.h" -#include "llvm/TextAPI/Target.h" -#include "llvm/TextAPI/Utils.h" #include <set> #include <string> #include <vector> namespace clang { namespace installapi { -using Macro = std::pair<std::string, bool /*isUndef*/>; struct DriverOptions { /// \brief Path to input file lists (JSON). @@ -38,11 +34,20 @@ struct DriverOptions { /// \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 File encoding to print. - llvm::MachO::FileType OutFT = llvm::MachO::FileType::TBD_V5; + 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; @@ -53,7 +58,10 @@ struct LinkerOptions { std::string InstallName; /// \brief The current version to use for the dynamic library. - llvm::MachO::PackedVersion CurrentVersion; + PackedVersion CurrentVersion; + + /// \brief The compatibility version to use for the dynamic library. + PackedVersion CompatVersion; /// \brief Is application extension safe. bool AppExtensionSafe = false; @@ -72,6 +80,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. @@ -86,7 +96,7 @@ 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. @@ -98,6 +108,16 @@ private: 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..454ee1e42aed1d79814934468981784cc46ecfeb 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()); } diff --git a/clang/unittests/AST/DeclPrinterTest.cpp b/clang/unittests/AST/DeclPrinterTest.cpp index 0e09ab2a7bba88be1a3288dadf3ccc1219d87667..e024c41e03b48433e64501597ec4efdf10a1c02a 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();", 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/ASTMatchers/ASTMatchersTest.h b/clang/unittests/ASTMatchers/ASTMatchersTest.h index 1ed1b5958a8b3a10810fa59a2269fd9c75012f06..e98129953157418fb636d370a029f8295a052321 100644 --- a/clang/unittests/ASTMatchers/ASTMatchersTest.h +++ b/clang/unittests/ASTMatchers/ASTMatchersTest.h @@ -293,7 +293,8 @@ testing::AssertionResult notMatchesWithOpenMP51(const Twine &Code, template <typename T> testing::AssertionResult matchAndVerifyResultConditionally( const Twine &Code, const T &AMatcher, - std::unique_ptr<BoundNodesCallback> FindResultVerifier, bool ExpectResult) { + std::unique_ptr<BoundNodesCallback> FindResultVerifier, bool ExpectResult, + ArrayRef<std::string> Args = {}, StringRef Filename = "input.cc") { bool VerifiedResult = false; MatchFinder Finder; VerifyMatch VerifyVerifiedResult(std::move(FindResultVerifier), @@ -304,9 +305,13 @@ testing::AssertionResult matchAndVerifyResultConditionally( // Some tests use typeof, which is a gnu extension. Using an explicit // unknown-unknown triple is good for a large speedup, because it lets us // avoid constructing a full system triple. - std::vector<std::string> Args = {"-std=gnu++11", "-target", - "i386-unknown-unknown"}; - if (!runToolOnCodeWithArgs(Factory->create(), Code, Args)) { + std::vector<std::string> CompileArgs = {"-std=gnu++11", "-target", + "i386-unknown-unknown"}; + // Append additional arguments at the end to allow overriding the default + // choices that we made above. + llvm::copy(Args, std::back_inserter(CompileArgs)); + + if (!runToolOnCodeWithArgs(Factory->create(), Code, CompileArgs, Filename)) { return testing::AssertionFailure() << "Parsing error in \"" << Code << "\""; } if (!VerifiedResult && ExpectResult) { @@ -319,8 +324,8 @@ testing::AssertionResult matchAndVerifyResultConditionally( VerifiedResult = false; SmallString<256> Buffer; - std::unique_ptr<ASTUnit> AST( - buildASTFromCodeWithArgs(Code.toStringRef(Buffer), Args)); + std::unique_ptr<ASTUnit> AST(buildASTFromCodeWithArgs( + Code.toStringRef(Buffer), CompileArgs, Filename)); if (!AST.get()) return testing::AssertionFailure() << "Parsing error in \"" << Code << "\" while building AST"; @@ -339,19 +344,24 @@ testing::AssertionResult matchAndVerifyResultConditionally( // FIXME: Find better names for these functions (or document what they // do more precisely). template <typename T> -testing::AssertionResult matchAndVerifyResultTrue( - const Twine &Code, const T &AMatcher, - std::unique_ptr<BoundNodesCallback> FindResultVerifier) { - return matchAndVerifyResultConditionally(Code, AMatcher, - std::move(FindResultVerifier), true); +testing::AssertionResult +matchAndVerifyResultTrue(const Twine &Code, const T &AMatcher, + std::unique_ptr<BoundNodesCallback> FindResultVerifier, + ArrayRef<std::string> Args = {}, + StringRef Filename = "input.cc") { + return matchAndVerifyResultConditionally( + Code, AMatcher, std::move(FindResultVerifier), + /*ExpectResult=*/true, Args, Filename); } template <typename T> testing::AssertionResult matchAndVerifyResultFalse( const Twine &Code, const T &AMatcher, - std::unique_ptr<BoundNodesCallback> FindResultVerifier) { + std::unique_ptr<BoundNodesCallback> FindResultVerifier, + ArrayRef<std::string> Args = {}, StringRef Filename = "input.cc") { return matchAndVerifyResultConditionally( - Code, AMatcher, std::move(FindResultVerifier), false); + Code, AMatcher, std::move(FindResultVerifier), + /*ExpectResult=*/false, Args, Filename); } // Implements a run method that returns whether BoundNodes contains a diff --git a/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp index 6911d7600a718892cec5530b94b170fc2766cf7b..f198dc71eb8337ccba2e311a0809d2ff961fe14f 100644 --- a/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp +++ b/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp @@ -985,6 +985,38 @@ TEST(ForEachArgumentWithParam, HandlesBoundNodesForNonMatches) { std::make_unique<VerifyIdIsBoundTo<VarDecl>>("v", 4))); } +TEST_P(ASTMatchersTest, + ForEachArgumentWithParamMatchesExplicitObjectParamOnOperatorCalls) { + if (!GetParam().isCXX23OrLater()) { + return; + } + + auto DeclRef = declRefExpr(to(varDecl().bind("declOfArg"))).bind("arg"); + auto SelfParam = parmVarDecl().bind("param"); + StatementMatcher CallExpr = + callExpr(forEachArgumentWithParam(DeclRef, SelfParam)); + + StringRef S = R"cpp( + struct A { + int operator()(this const A &self); + }; + A obj; + int global = obj(); + )cpp"; + + auto Args = GetParam().getCommandLineArgs(); + auto Filename = getFilenameForTesting(GetParam().Language); + + EXPECT_TRUE(matchAndVerifyResultTrue( + S, CallExpr, + std::make_unique<VerifyIdIsBoundTo<ParmVarDecl>>("param", "self"), Args, + Filename)); + EXPECT_TRUE(matchAndVerifyResultTrue( + S, CallExpr, + std::make_unique<VerifyIdIsBoundTo<VarDecl>>("declOfArg", "obj"), Args, + Filename)); +} + TEST(ForEachArgumentWithParamType, ReportsNoFalsePositives) { StatementMatcher ArgumentY = declRefExpr(to(varDecl(hasName("y")))).bind("arg"); @@ -1168,6 +1200,37 @@ TEST(ForEachArgumentWithParamType, MatchesVariadicFunctionPtrCalls) { S, CallExpr, std::make_unique<VerifyIdIsBoundTo<DeclRefExpr>>("arg"))); } +TEST_P(ASTMatchersTest, + ForEachArgumentWithParamTypeMatchesExplicitObjectParamOnOperatorCalls) { + if (!GetParam().isCXX23OrLater()) { + return; + } + + auto DeclRef = declRefExpr(to(varDecl().bind("declOfArg"))).bind("arg"); + auto SelfTy = qualType(asString("const A &")).bind("selfType"); + StatementMatcher CallExpr = + callExpr(forEachArgumentWithParamType(DeclRef, SelfTy)); + + StringRef S = R"cpp( + struct A { + int operator()(this const A &self); + }; + A obj; + int global = obj(); + )cpp"; + + auto Args = GetParam().getCommandLineArgs(); + auto Filename = getFilenameForTesting(GetParam().Language); + + EXPECT_TRUE(matchAndVerifyResultTrue( + S, CallExpr, std::make_unique<VerifyIdIsBoundTo<QualType>>("selfType"), + Args, Filename)); + EXPECT_TRUE(matchAndVerifyResultTrue( + S, CallExpr, + std::make_unique<VerifyIdIsBoundTo<VarDecl>>("declOfArg", "obj"), Args, + Filename)); +} + TEST(QualType, hasCanonicalType) { EXPECT_TRUE(notMatches("typedef int &int_ref;" "int a;" 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..9430730004dbd2e1f3f8c5da33bcf8be81a0eb21 100644 --- a/clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp +++ b/clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp @@ -3383,6 +3383,66 @@ 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")); +} + // 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..03005384a6f667e10d0c2164abfe90d5994b1c5d 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) { @@ -11009,10 +11034,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 +11052,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 +11485,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( @@ -12356,7 +12396,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);"); @@ -19119,13 +19159,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 @@ -21060,7 +21100,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 +21360,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/InterpreterExtensionsTest.cpp b/clang/unittests/Interpreter/InterpreterExtensionsTest.cpp index f1c3d65ab0a95d049706b8ba4b4a6755fe5321e4..1ba865a79ed778cf161383e43a47112536a90ccd 100644 --- a/clang/unittests/Interpreter/InterpreterExtensionsTest.cpp +++ b/clang/unittests/Interpreter/InterpreterExtensionsTest.cpp @@ -17,32 +17,99 @@ #include "clang/Sema/Lookup.h" #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 { +static bool HostSupportsJit() { + auto J = llvm::orc::LLJITBuilder().create(); + if (J) + return true; + LLVMConsumeError(llvm::wrap(J.takeError())); + 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::InitializeAllTargets(); + llvm::InitializeAllTargetInfos(); + llvm::InitializeAllTargetMCs(); + llvm::InitializeAllAsmPrinters(); + } + ~LLVMInitRAII() { llvm::llvm_shutdown(); } +} LLVMInit; + class TestCreateResetExecutor : public Interpreter { public: TestCreateResetExecutor(std::unique_ptr<CompilerInstance> CI, 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(); + clang::IncrementalCompilerBuilder CB; 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()); @@ -100,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/StaticAnalyzer/CMakeLists.txt b/clang/unittests/StaticAnalyzer/CMakeLists.txt index db56e77331b821195cd366c2cfdabead09492256..ff34d5747cc81b31aa891576a523ea5edecfa21e 100644 --- a/clang/unittests/StaticAnalyzer/CMakeLists.txt +++ b/clang/unittests/StaticAnalyzer/CMakeLists.txt @@ -12,6 +12,7 @@ add_clang_unittest(StaticAnalysisTests 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 index 19c66cc6bee1eb227c6bc709c8b7057f8ca511e3..d6dfcaac6f3bdc41bd97f7f23af81a6f70bba45f 100644 --- a/clang/unittests/StaticAnalyzer/IsCLibraryFunctionTest.cpp +++ b/clang/unittests/StaticAnalyzer/IsCLibraryFunctionTest.cpp @@ -12,78 +12,73 @@ using namespace clang; using namespace ento; using namespace ast_matchers; -testing::AssertionResult extractFunctionDecl(StringRef Code, - const FunctionDecl *&Result) { - auto ASTUnit = tooling::buildASTFromCode(Code); - if (!ASTUnit) - return testing::AssertionFailure() << "AST construction failed"; - - ASTContext &Context = ASTUnit->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(); -} +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(IsCLibraryFunctionTest, AcceptsGlobal) { - const FunctionDecl *Result; - ASSERT_TRUE(extractFunctionDecl(R"cpp(void fun();)cpp", Result)); - EXPECT_TRUE(CheckerContext::isCLibraryFunction(Result)); +TEST_F(IsCLibraryFunctionTest, AcceptsGlobal) { + ASSERT_TRUE(buildAST(R"cpp(void fun();)cpp")); + EXPECT_TRUE(CheckerContext::isCLibraryFunction(getFunctionDecl())); } -TEST(IsCLibraryFunctionTest, AcceptsExternCGlobal) { - const FunctionDecl *Result; - ASSERT_TRUE( - extractFunctionDecl(R"cpp(extern "C" { void fun(); })cpp", Result)); - EXPECT_TRUE(CheckerContext::isCLibraryFunction(Result)); +TEST_F(IsCLibraryFunctionTest, AcceptsExternCGlobal) { + ASSERT_TRUE(buildAST(R"cpp(extern "C" { void fun(); })cpp")); + EXPECT_TRUE(CheckerContext::isCLibraryFunction(getFunctionDecl())); } -TEST(IsCLibraryFunctionTest, RejectsNoInlineNoExternalLinkage) { - // Functions that are neither inlined nor externally visible cannot be C library functions. - const FunctionDecl *Result; - ASSERT_TRUE(extractFunctionDecl(R"cpp(static void fun();)cpp", Result)); - EXPECT_FALSE(CheckerContext::isCLibraryFunction(Result)); +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(IsCLibraryFunctionTest, RejectsAnonymousNamespace) { - const FunctionDecl *Result; - ASSERT_TRUE( - extractFunctionDecl(R"cpp(namespace { void fun(); })cpp", Result)); - EXPECT_FALSE(CheckerContext::isCLibraryFunction(Result)); +TEST_F(IsCLibraryFunctionTest, RejectsAnonymousNamespace) { + ASSERT_TRUE(buildAST(R"cpp(namespace { void fun(); })cpp")); + EXPECT_FALSE(CheckerContext::isCLibraryFunction(getFunctionDecl())); } -TEST(IsCLibraryFunctionTest, AcceptsStdNamespace) { - const FunctionDecl *Result; - ASSERT_TRUE( - extractFunctionDecl(R"cpp(namespace std { void fun(); })cpp", Result)); - EXPECT_TRUE(CheckerContext::isCLibraryFunction(Result)); +TEST_F(IsCLibraryFunctionTest, AcceptsStdNamespace) { + ASSERT_TRUE(buildAST(R"cpp(namespace std { void fun(); })cpp")); + EXPECT_TRUE(CheckerContext::isCLibraryFunction(getFunctionDecl())); } -TEST(IsCLibraryFunctionTest, RejectsOtherNamespaces) { - const FunctionDecl *Result; - ASSERT_TRUE( - extractFunctionDecl(R"cpp(namespace stdx { void fun(); })cpp", Result)); - EXPECT_FALSE(CheckerContext::isCLibraryFunction(Result)); +TEST_F(IsCLibraryFunctionTest, RejectsOtherNamespaces) { + ASSERT_TRUE(buildAST(R"cpp(namespace stdx { void fun(); })cpp")); + EXPECT_FALSE(CheckerContext::isCLibraryFunction(getFunctionDecl())); } -TEST(IsCLibraryFunctionTest, RejectsClassStatic) { - const FunctionDecl *Result; - ASSERT_TRUE( - extractFunctionDecl(R"cpp(class A { static void fun(); };)cpp", Result)); - EXPECT_FALSE(CheckerContext::isCLibraryFunction(Result)); +TEST_F(IsCLibraryFunctionTest, RejectsClassStatic) { + ASSERT_TRUE(buildAST(R"cpp(class A { static void fun(); };)cpp")); + EXPECT_FALSE(CheckerContext::isCLibraryFunction(getFunctionDecl())); } -TEST(IsCLibraryFunctionTest, RejectsClassMember) { - const FunctionDecl *Result; - ASSERT_TRUE(extractFunctionDecl(R"cpp(class A { void fun(); };)cpp", Result)); - EXPECT_FALSE(CheckerContext::isCLibraryFunction(Result)); +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/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..60f48aba2788e0820fe5f5fa9d942324b85074ec 100644 --- a/clang/www/c_status.html +++ b/clang/www/c_status.html @@ -260,7 +260,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> @@ -315,7 +315,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 +336,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> @@ -369,7 +375,7 @@ conformance.</p> <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 +407,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 +417,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 +477,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> 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/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..da47317c0e57641fc9cca7a93ea6d847d5a80db9 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); @@ -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_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..d519ac3a459b67b1b7e2900eacd5a6bc1329e042 100644 --- a/compiler-rt/lib/hwasan/hwasan_interceptors.cpp +++ b/compiler-rt/lib/hwasan/hwasan_interceptors.cpp @@ -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..a04175ba1e4b56939122785fd3169764c2c46e66 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]; 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..6e0b2bf2ef5b6fb62a4aa9a44785329a3a72a09e 100644 --- a/compiler-rt/lib/msan/msan_interceptors.cpp +++ b/compiler-rt/lib/msan/msan_interceptors.cpp @@ -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..cd2d9f5c720c57523e6f013bb64bab841abfcabd 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(__msan_get_track_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(__msan_get_track_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_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_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_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/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..f4dd90aac6655526fea4b9bdc2bf68e37d0525bb 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" @@ -47,11 +48,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 +76,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 +103,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 +164,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); @@ -274,7 +279,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 +291,7 @@ public: } ALWAYS_INLINE uptr addHeaderTag(uptr Ptr) { - if (!allocatorSupportsMemoryTagging<Config>()) + if (!allocatorSupportsMemoryTagging<AllocatorConfig>()) return Ptr; return addFixedTag(Ptr, 2); } @@ -419,7 +424,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 +506,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 +666,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 +769,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 +792,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 +893,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 +903,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); } @@ -983,7 +989,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 +1038,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(), ""); @@ -1142,7 +1148,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 +1168,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 +1190,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 +1207,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); 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/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..f5e4ab57b4dfd5e526d3d81a36c60a9a1f26d12e 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); @@ -400,9 +399,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 +515,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/secondary.h b/compiler-rt/lib/scudo/standalone/secondary.h index 732fd307ed2f434f02cc4bb17c2334b3ae8a8779..202c55cc1a92b2962643114afe6f8ed43a7851a5 100644 --- a/compiler-rt/lib/scudo/standalone/secondary.h +++ b/compiler-rt/lib/scudo/standalone/secondary.h @@ -173,8 +173,6 @@ public: template <typename Config> class MapAllocatorCache { public: - using CacheConfig = typename Config::Secondary::Cache; - void getStats(ScopedString *Str) { ScopedLock L(Mutex); uptr Integral; @@ -199,16 +197,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 +251,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 +380,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 +404,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 +429,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 +466,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 +483,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 +553,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/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..6a311adc55e4bd3e0d67c3c18fcdfdab7978f5b5 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 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/tsan/rtl/tsan_interceptors_posix.cpp b/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp index 24309ab66b2e671ad3917b168055d411a1e79330..8ffc703b05eace1672bd0de5cf0f6fb750d89b9f 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp +++ b/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp @@ -2861,6 +2861,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 diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl_mutex.cpp b/compiler-rt/lib/tsan/rtl/tsan_rtl_mutex.cpp index 2e978852ea7d379c4ec408f00cdfeb177144bbae..2a8aa1915c9aeb385b5679ebc6f7c431f07c70dc 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_rtl_mutex.cpp +++ b/compiler-rt/lib/tsan/rtl/tsan_rtl_mutex.cpp @@ -446,9 +446,9 @@ void Acquire(ThreadState *thr, uptr pc, uptr addr) { if (!s) return; SlotLocker locker(thr); + ReadLock lock(&s->mtx); if (!s->clock) return; - ReadLock lock(&s->mtx); thr->clock.Acquire(s->clock); } 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/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/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/compare_exchange_acquire_fence.cpp b/compiler-rt/test/tsan/compare_exchange_acquire_fence.cpp new file mode 100644 index 0000000000000000000000000000000000000000..404fd2fbb3c2266a9caa83a1bc8a5fac6e6604da --- /dev/null +++ b/compiler-rt/test/tsan/compare_exchange_acquire_fence.cpp @@ -0,0 +1,43 @@ +// RUN: %clangxx_tsan -O1 %s %link_libcxx_tsan -o %t && %run %t 2>&1 +// This is a correct program and tsan should not report a race. +// +// Verify that there is a happens-before relationship between a +// memory_order_release store that happens as part of a successful +// compare_exchange_strong(), and an atomic_thread_fence(memory_order_acquire) +// that happens after a relaxed load. + +#include <atomic> +#include <sanitizer/tsan_interface.h> +#include <stdbool.h> +#include <stdio.h> +#include <thread> + +std::atomic<bool> a; +unsigned int b; +constexpr int loops = 100000; + +void Thread1() { + for (int i = 0; i < loops; ++i) { + while (a.load(std::memory_order_acquire)) { + } + b = i; + bool expected = false; + a.compare_exchange_strong(expected, true, std::memory_order_acq_rel); + } +} + +int main() { + std::thread t(Thread1); + unsigned int sum = 0; + for (int i = 0; i < loops; ++i) { + while (!a.load(std::memory_order_relaxed)) { + } + std::atomic_thread_fence(std::memory_order_acquire); + __tsan_acquire(&a); + sum += b; + a.store(false, std::memory_order_release); + } + t.join(); + fprintf(stderr, "DONE: %u\n", sum); + return 0; +} 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/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 132420009bd1df2f21be80d8cf81f87b32e6ecb2..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,14 +1,14 @@ // 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 // struct if there aren't any methods - even though it's tagged // as a class. -// CHECK: type = {{struct|class}} A { -// CHECK-NEXT: {{(public:){0,1}}} -// CHECK-NEXT: int MyData; +// CHECK: {{struct|class}} A { +// CHECK: int MyData; // CHECK-NEXT: } class A; class B { diff --git a/cross-project-tests/debuginfo-tests/llgdb-tests/static-member-2.cpp b/cross-project-tests/debuginfo-tests/llgdb-tests/static-member-2.cpp index 3f11ae018fc858c1f001afc732a40d14e2496004..c9b416dace925cc263ba4cc5e1578719896f8d5c 100644 --- a/cross-project-tests/debuginfo-tests/llgdb-tests/static-member-2.cpp +++ b/cross-project-tests/debuginfo-tests/llgdb-tests/static-member-2.cpp @@ -2,22 +2,21 @@ // RUN: %clangxx %target_itanium_abi_host_triple %t -o %t.out // RUN: %test_debuginfo %s %t.out // XFAIL: gdb-clang-incompatibility -// XFAIL: system-darwin // DEBUGGER: delete breakpoints -// DEBUGGER: break static-member.cpp:33 +// DEBUGGER: break static-member-2.cpp:36 // DEBUGGER: r // DEBUGGER: ptype C // CHECK: {{struct|class}} C { -// CHECK: static const int a; +// CHECK: static const int a // CHECK-NEXT: static int b; // CHECK-NEXT: static int c; -// CHECK-NEXT: int d; +// CHECK: int d; // CHECK-NEXT: } // DEBUGGER: p C::a -// CHECK: ${{[0-9]}} = 4 +// CHECK: 4 // DEBUGGER: p C::c -// CHECK: ${{[0-9]}} = 15 +// CHECK: 15 // PR14471, PR14734 diff --git a/cross-project-tests/debuginfo-tests/llgdb-tests/static-member.cpp b/cross-project-tests/debuginfo-tests/llgdb-tests/static-member.cpp index 57316dfd64040452eb81a3aeb03068922cd56e74..492e0ca084209f168bf9fea34901cda369e3d561 100644 --- a/cross-project-tests/debuginfo-tests/llgdb-tests/static-member.cpp +++ b/cross-project-tests/debuginfo-tests/llgdb-tests/static-member.cpp @@ -2,16 +2,15 @@ // RUN: %clangxx %target_itanium_abi_host_triple %t -o %t.out // RUN: %test_debuginfo %s %t.out // XFAIL: !system-darwin && gdb-clang-incompatibility -// XFAIL: system-darwin // DEBUGGER: delete breakpoints -// DEBUGGER: break static-member.cpp:33 +// DEBUGGER: break static-member.cpp:35 // DEBUGGER: r // DEBUGGER: ptype MyClass // CHECK: {{struct|class}} MyClass { -// CHECK: static const int a; +// CHECK: static const int a // CHECK-NEXT: static int b; // CHECK-NEXT: static int c; -// CHECK-NEXT: int d; +// CHECK: int d; // CHECK-NEXT: } // DEBUGGER: p MyClass::a // CHECK: ${{[0-9]}} = 4 diff --git a/cross-project-tests/debuginfo-tests/llgdb-tests/test_debuginfo.pl b/cross-project-tests/debuginfo-tests/llgdb-tests/test_debuginfo.pl index 6dbc3b9b8632e5337f5676a07948bac3321e1be8..fa52a5037c2196ff16237d5679c9ba28f61e2835 100755 --- a/cross-project-tests/debuginfo-tests/llgdb-tests/test_debuginfo.pl +++ b/cross-project-tests/debuginfo-tests/llgdb-tests/test_debuginfo.pl @@ -56,7 +56,7 @@ my $my_debugger = $ENV{'DEBUGGER'}; if (!$my_debugger) { if ($use_lldb) { my $path = dirname(Cwd::abs_path($0)); - $my_debugger = "/usr/bin/env python3 $path/llgdb.py"; + $my_debugger = "/usr/bin/xcrun python3 $path/llgdb.py"; } else { $my_debugger = "gdb"; } @@ -66,12 +66,18 @@ if (!$my_debugger) { my $debugger_options = "-q -batch -n -x"; # run debugger and capture output. +print("Running debugger\n"); system("$my_debugger $debugger_options $debugger_script_file $executable_file > $output_file 2>&1"); - +if ($?) { + print("Debugger output was:\n"); + system("cat", "$output_file"); + exit 1; +} # validate output. +print("Running FileCheck\n"); system("FileCheck", "-input-file", "$output_file", "$testcase_file"); -if ($?>>8 == 1) { - print "Debugger output was:\n"; +if ($?) { + print("Debugger output was:\n"); system("cat", "$output_file"); exit 1; } 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/Common/optional.h b/flang/include/flang/Common/optional.h new file mode 100644 index 0000000000000000000000000000000000000000..b5623b84dbd36987c57d4d69c7ea8a1d585cf723 --- /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/Runtime/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/reference-wrapper.h b/flang/include/flang/Common/reference-wrapper.h new file mode 100644 index 0000000000000000000000000000000000000000..66f924662d96122c28d1198f7f50b9c3d46e8ee4 --- /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/Runtime/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/visit.h b/flang/include/flang/Common/visit.h index d3136be3f6a1f0f8e6ccd7c8212b59945651e8d1..f733b726189c8807f6f33b7c5529518a7d25f36f 100644 --- a/flang/include/flang/Common/visit.h +++ b/flang/include/flang/Common/visit.h @@ -17,27 +17,6 @@ // // 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_ @@ -52,7 +31,22 @@ template <std::size_t LOW, std::size_t HIGH, typename RESULT, typename VISITOR, typename... VARIANT> inline 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}; 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/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/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/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..b2c3d92909375c74321d14b3f4f18f03533dea4e 100644 --- a/flang/include/flang/Parser/dump-parse-tree.h +++ b/flang/include/flang/Parser/dump-parse-tree.h @@ -233,6 +233,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.h b/flang/include/flang/Parser/parse-tree.h index f7b72c3af091647507defd51624aaa403584c4c4..c96abfba491d4bbd18302755613e6f40c422f80f 100644 --- a/flang/include/flang/Parser/parse-tree.h +++ b/flang/include/flang/Parser/parse-tree.h @@ -4297,16 +4297,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/Runtime/api-attrs.h b/flang/include/flang/Runtime/api-attrs.h index 9c8a67ffc34a82fb08a837b5d04e8f148c715517..fc3eb42e1b73f53c024f846564649d4c0c45d1ab 100644 --- a/flang/include/flang/Runtime/api-attrs.h +++ b/flang/include/flang/Runtime/api-attrs.h @@ -109,6 +109,18 @@ #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/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/type-code.h b/flang/include/flang/Runtime/type-code.h index 3757840cfdef963c337b9ab3a5b68d9f10a9ba9e..f7419249c2ba9cf3b923f9ef3698dcb1785e80f2 100644 --- a/flang/include/flang/Runtime/type-code.h +++ b/flang/include/flang/Runtime/type-code.h @@ -10,6 +10,7 @@ #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> @@ -54,7 +55,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..66774b51316cbf5bcda0c10ac0578562c350bf2e 100644 --- a/flang/include/flang/Semantics/tools.h +++ b/flang/include/flang/Semantics/tools.h @@ -180,7 +180,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 +282,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/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..48830dc55578c2f16f823623e9fed64b993913b4 100644 --- a/flang/lib/Lower/Bridge.cpp +++ b/flang/lib/Lower/Bridge.cpp @@ -748,7 +748,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 +1010,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 {}; } @@ -1060,15 +1058,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 +1081,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 +1111,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 +2522,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( @@ -3660,11 +3706,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 +3796,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 +4023,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); 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..c65becc497459c9fe554d69823536369bdb4930f 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(); @@ -975,12 +1050,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 +1456,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, 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..fe5ce4b17b25877b008a5fdc30d529861159c36c 100644 --- a/flang/lib/Lower/ConvertExprToHLFIR.cpp +++ b/flang/lib/Lower/ConvertExprToHLFIR.cpp @@ -284,7 +284,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 +306,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())) 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..7b7e4a875cd8e8254f3ab3a37543e4d98145e217 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)) diff --git a/flang/lib/Lower/OpenMP/ClauseProcessor.cpp b/flang/lib/Lower/OpenMP/ClauseProcessor.cpp index a41f8312a28c9e850de221bca393dcaf0d46d41c..52c3479b1ea95d30fc3d2345399706f96464d1ab 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,64 +31,55 @@ 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::ModType &m) { + switch (m) { + case omp::clause::Schedule::ModType::Monotonic: return mlir::omp::ScheduleModifier::monotonic; - case Fortran::parser::OmpScheduleModifierType::ModType::Nonmonotonic: + case omp::clause::Schedule::ModType::Nonmonotonic: return mlir::omp::ScheduleModifier::nonmonotonic; - case Fortran::parser::OmpScheduleModifierType::ModType::Simd: + case omp::clause::Schedule::ModType::Simd: return mlir::omp::ScheduleModifier::simd; } return mlir::omp::ScheduleModifier::none; } static mlir::omp::ScheduleModifier -getScheduleModifier(const Fortran::parser::OmpScheduleClause &x) { - const auto &modifier = - std::get<std::optional<Fortran::parser::OmpScheduleModifier>>(x.t); +getScheduleModifier(const omp::clause::Schedule &clause) { + using ScheduleModifier = omp::clause::Schedule::ScheduleModifier; + const auto &modifier = std::get<std::optional<ScheduleModifier>>(clause.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); - + using ModType = omp::clause::Schedule::ModType; + const auto &modType1 = std::get<ModType>(modifier->t); + if (modType1 == ModType::Simd) { + const auto &modType2 = std::get<std::optional<ModType>>(modifier->t); + if (modType2 && *modType2 != ModType::Simd) + return translateScheduleModifier(*modType2); return mlir::omp::ScheduleModifier::none; } - return translateScheduleModifier(modType1.v); + return translateScheduleModifier(modType1); } return mlir::omp::ScheduleModifier::none; } static mlir::omp::ScheduleModifier -getSimdModifier(const Fortran::parser::OmpScheduleClause &x) { - const auto &modifier = - std::get<std::optional<Fortran::parser::OmpScheduleModifier>>(x.t); +getSimdModifier(const omp::clause::Schedule &clause) { + using ScheduleModifier = omp::clause::Schedule::ScheduleModifier; + const auto &modifier = std::get<std::optional<ScheduleModifier>>(clause.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) + using ModType = omp::clause::Schedule::ModType; + const auto &modType1 = std::get<ModType>(modifier->t); + if (modType1 == 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) + const auto &modType2 = std::get<std::optional<ModType>>(modifier->t); + if (modType2 && *modType2 == ModType::Simd) return mlir::omp::ScheduleModifier::simd; } return mlir::omp::ScheduleModifier::none; @@ -95,29 +87,25 @@ getSimdModifier(const Fortran::parser::OmpScheduleClause &x) { 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); + const omp::ObjectList &objectList = std::get<omp::ObjectList>(clause.t); + const auto &modifier = + std::get<std::optional<omp::clause::Allocate::Modifier>>(clause.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); + modifier && + std::holds_alternative<omp::clause::Allocate::Modifier::Allocator>( + modifier->u); - if (allocateModifier && !onlyAllocator) { + if (modifier && !onlyAllocator) { TODO(currentLocation, "OmpAllocateClause ALIGN modifier"); } @@ -125,37 +113,34 @@ genAllocateClause(Fortran::lower::AbstractConverter &converter, // 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); + const auto &value = + std::get<omp::clause::Allocate::Modifier::Allocator>(modifier->u); + mlir::Value operand = + fir::getBase(converter.genExprValue(value.v, stmtCtx)); + allocatorOperands.append(objectList.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(objectList.size(), operand); } - genObjectList(ompObjectList, converter, allocateOperands); + genObjectList(objectList, 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::Type::Master: procBindKind = mlir::omp::ClauseProcBindKind::Master; break; - case Fortran::parser::OmpProcBindClause::Type::Close: + case omp::clause::ProcBind::Type::Close: procBindKind = mlir::omp::ClauseProcBindKind::Close; break; - case Fortran::parser::OmpProcBindClause::Type::Spread: + case omp::clause::ProcBind::Type::Spread: procBindKind = mlir::omp::ClauseProcBindKind::Spread; break; - case Fortran::parser::OmpProcBindClause::Type::Primary: + case omp::clause::ProcBind::Type::Primary: procBindKind = mlir::omp::ClauseProcBindKind::Primary; break; } @@ -165,20 +150,17 @@ static mlir::omp::ClauseProcBindKindAttr genProcBindKindAttr( static mlir::omp::ClauseTaskDependAttr genDependKindAttr(fir::FirOpBuilder &firOpBuilder, - const Fortran::parser::OmpClause::Depend *dependClause) { + const omp::clause::Depend &clause) { 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: + const auto &inOut = std::get<omp::clause::Depend::InOut>(clause.u); + switch (std::get<omp::clause::Depend::Type>(inOut.t)) { + case omp::clause::Depend::Type::In: pbKind = mlir::omp::ClauseTaskDepend::taskdependin; break; - case Fortran::parser::OmpDependenceType::Type::Out: + case omp::clause::Depend::Type::Out: pbKind = mlir::omp::ClauseTaskDepend::taskdependout; break; - case Fortran::parser::OmpDependenceType::Type::Inout: + case omp::clause::Depend::Type::Inout: pbKind = mlir::omp::ClauseTaskDepend::taskdependinout; break; default: @@ -189,44 +171,59 @@ genDependKindAttr(fir::FirOpBuilder &firOpBuilder, 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 +236,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 +249,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 +285,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::Type::Shared: + case omp::clause::Default::Type::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::Type::Private: // TODO Support default(private) break; - case Fortran::parser::OmpDefaultClause::Type::Firstprivate: + case omp::clause::Default::Type::Firstprivate: // TODO Support default(firstprivate) break; } @@ -318,20 +316,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 +334,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::Type::Nohost: result = mlir::omp::DeclareTargetDeviceType::nohost; break; - case Fortran::parser::OmpDeviceTypeClause::Type::Host: + case omp::clause::DeviceType::Type::Host: result = mlir::omp::DeclareTargetDeviceType::host; break; - case Fortran::parser::OmpDeviceTypeClause::Type::Any: + case omp::clause::DeviceType::Type::Any: result = mlir::omp::DeclareTargetDeviceType::any; break; } @@ -360,12 +355,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 +369,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 +379,19 @@ 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>()) { + result = fir::getBase(converter.genExprValue(clause->v, stmtCtx)); return true; } return false; @@ -406,23 +399,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 +421,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 +430,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 +453,38 @@ 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::ScheduleType>(clause->t); mlir::omp::ClauseScheduleKind scheduleKind; - switch (scheduleClauseKind) { - case Fortran::parser::OmpScheduleClause::ScheduleType::Static: + switch (scheduleType) { + case omp::clause::Schedule::ScheduleType::Static: scheduleKind = mlir::omp::ClauseScheduleKind::Static; break; - case Fortran::parser::OmpScheduleClause::ScheduleType::Dynamic: + case omp::clause::Schedule::ScheduleType::Dynamic: scheduleKind = mlir::omp::ClauseScheduleKind::Dynamic; break; - case Fortran::parser::OmpScheduleClause::ScheduleType::Guided: + case omp::clause::Schedule::ScheduleType::Guided: scheduleKind = mlir::omp::ClauseScheduleKind::Guided; break; - case Fortran::parser::OmpScheduleClause::ScheduleType::Auto: + case omp::clause::Schedule::ScheduleType::Auto: scheduleKind = mlir::omp::ClauseScheduleKind::Auto; break; - case Fortran::parser::OmpScheduleClause::ScheduleType::Runtime: + case omp::clause::Schedule::ScheduleType::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 +495,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 +516,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 +534,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 +554,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 +598,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 +723,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 +746,30 @@ 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); + assert(std::holds_alternative<omp::clause::Depend::InOut>(clause.u) && + "Only InOut is handled at the moment"); + const auto &inOut = std::get<omp::clause::Depend::InOut>(clause.u); + const auto &objects = std::get<omp::ObjectList>(inOut.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, clause); + 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 +777,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 +798,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 +839,61 @@ 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 &oMapType = 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); + const Map::MapType::Type &mapType = + std::get<Map::MapType::Type>(oMapType->t); switch (mapType) { - case Fortran::parser::OmpMapType::Type::To: + case Map::MapType::Type::To: mapTypeBits |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO; break; - case Fortran::parser::OmpMapType::Type::From: + case Map::MapType::Type::From: mapTypeBits |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_FROM; break; - case Fortran::parser::OmpMapType::Type::Tofrom: + case Map::MapType::Type::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::Type::Alloc: + case Map::MapType::Type::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::Type::Delete: mapTypeBits |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_DELETE; } - if (std::get<std::optional<Fortran::parser::OmpMapType::Always>>( - oMapType->t)) + if (std::get<std::optional<Map::MapType::Always>>(oMapType->t)) 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 +916,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(clause.v, 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 +994,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 +1008,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..8582716e6b9a775ced678dbc4d8f1e1c1ad90957 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(makeList(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,30 @@ 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) { + for (const omp::Object &object : clause.v) { 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 +234,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 +261,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 +272,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/ClauseT.h b/flang/lib/Lower/OpenMP/ClauseT.h new file mode 100644 index 0000000000000000000000000000000000000000..2aae29af29214afa5077ce2e5946ca20bc57e220 --- /dev/null +++ b/flang/lib/Lower/OpenMP/ClauseT.h @@ -0,0 +1,714 @@ +//===- ClauseT -- 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 +// +//===----------------------------------------------------------------------===// +#ifndef FORTRAN_LOWER_OPENMP_CLAUSET_H +#define FORTRAN_LOWER_OPENMP_CLAUSET_H + +#include "flang/Parser/parse-tree.h" // For enum reuse + +#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/Support/raw_ostream.h" + +#include <algorithm> +#include <iterator> +#include <optional> +#include <tuple> +#include <type_traits> +#include <utility> +#include <variant> + +#include "llvm/Frontend/OpenMP/OMP.h.inc" + +namespace tomp { + +template <typename T> +using ListT = llvm::SmallVector<T, 0>; + +// A specialization of ObjectT<Id, Expr> must provide the following definitions: +// { +// using IdType = Id; +// using ExprType = Expr; +// +// auto id() const -> Id { +// return the identifier of the object (for use in tests for +// presence/absence of the object) +// } +// +// auto ref() const -> const Expr& { +// 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]`. +template <typename Id, typename Expr> +struct ObjectT; + +template <typename I, typename E> +using ObjectListT = ListT<ObjectT<I, E>>; + +namespace clause { +// Helper objects + +template <typename I, typename E> +struct DefinedOperatorT { + struct DefinedOpName { + using WrapperTrait = std::true_type; + ObjectT<I, E> v; + }; + using IntrinsicOperator = Fortran::parser::DefinedOperator::IntrinsicOperator; + using UnionTrait = std::true_type; + std::variant<DefinedOpName, IntrinsicOperator> u; +}; + +template <typename I, typename E> +struct ProcedureDesignatorT { + using WrapperTrait = std::true_type; + ObjectT<I, E> v; +}; + +template <typename I, typename E> +struct ReductionOperatorT { + using UnionTrait = std::true_type; + std::variant<DefinedOperatorT<I, E>, ProcedureDesignatorT<I, E>> u; +}; + +template <typename I, typename E> +struct AcqRelT { + using EmptyTrait = std::true_type; +}; +template <typename I, typename E> +struct AcquireT { + using EmptyTrait = std::true_type; +}; +template <typename I, typename E> +struct AdjustArgsT { + using EmptyTrait = std::true_type; +}; +template <typename I, typename E> +struct AffinityT { + using EmptyTrait = std::true_type; +}; +template <typename I, typename E> +struct AlignT { + using EmptyTrait = std::true_type; +}; +template <typename I, typename E> +struct AppendArgsT { + using EmptyTrait = std::true_type; +}; +template <typename I, typename E> +struct AtT { + using EmptyTrait = std::true_type; +}; +template <typename I, typename E> +struct BindT { + using EmptyTrait = std::true_type; +}; +template <typename I, typename E> +struct CancellationConstructTypeT { + using EmptyTrait = std::true_type; +}; +template <typename I, typename E> +struct CaptureT { + using EmptyTrait = std::true_type; +}; +template <typename I, typename E> +struct CompareT { + using EmptyTrait = std::true_type; +}; +template <typename I, typename E> +struct DepobjT { + using EmptyTrait = std::true_type; +}; +template <typename I, typename E> +struct DestroyT { + using EmptyTrait = std::true_type; +}; +template <typename I, typename E> +struct DetachT { + using EmptyTrait = std::true_type; +}; +template <typename I, typename E> +struct DoacrossT { + using EmptyTrait = std::true_type; +}; +template <typename I, typename E> +struct DynamicAllocatorsT { + using EmptyTrait = std::true_type; +}; +template <typename I, typename E> +struct ExclusiveT { + using EmptyTrait = std::true_type; +}; +template <typename I, typename E> +struct FailT { + using EmptyTrait = std::true_type; +}; +template <typename I, typename E> +struct FlushT { + using EmptyTrait = std::true_type; +}; +template <typename I, typename E> +struct FullT { + using EmptyTrait = std::true_type; +}; +template <typename I, typename E> +struct InbranchT { + using EmptyTrait = std::true_type; +}; +template <typename I, typename E> +struct InclusiveT { + using EmptyTrait = std::true_type; +}; +template <typename I, typename E> +struct IndirectT { + using EmptyTrait = std::true_type; +}; +template <typename I, typename E> +struct InitT { + using EmptyTrait = std::true_type; +}; +template <typename I, typename E> +struct MatchT { + using EmptyTrait = std::true_type; +}; +template <typename I, typename E> +struct MemoryOrderT { + using EmptyTrait = std::true_type; +}; +template <typename I, typename E> +struct MergeableT { + using EmptyTrait = std::true_type; +}; +template <typename I, typename E> +struct MessageT { + using EmptyTrait = std::true_type; +}; +template <typename I, typename E> +struct NogroupT { + using EmptyTrait = std::true_type; +}; +template <typename I, typename E> +struct NotinbranchT { + using EmptyTrait = std::true_type; +}; +template <typename I, typename E> +struct NowaitT { + using EmptyTrait = std::true_type; +}; +template <typename I, typename E> +struct OmpxAttributeT { + using EmptyTrait = std::true_type; +}; +template <typename I, typename E> +struct OmpxBareT { + using EmptyTrait = std::true_type; +}; +template <typename I, typename E> +struct ReadT { + using EmptyTrait = std::true_type; +}; +template <typename I, typename E> +struct RelaxedT { + using EmptyTrait = std::true_type; +}; +template <typename I, typename E> +struct ReleaseT { + using EmptyTrait = std::true_type; +}; +template <typename I, typename E> +struct ReverseOffloadT { + using EmptyTrait = std::true_type; +}; +template <typename I, typename E> +struct SeqCstT { + using EmptyTrait = std::true_type; +}; +template <typename I, typename E> +struct SeverityT { + using EmptyTrait = std::true_type; +}; +template <typename I, typename E> +struct SimdT { + using EmptyTrait = std::true_type; +}; +template <typename I, typename E> +struct ThreadprivateT { + using EmptyTrait = std::true_type; +}; +template <typename I, typename E> +struct ThreadsT { + using EmptyTrait = std::true_type; +}; +template <typename I, typename E> +struct UnifiedAddressT { + using EmptyTrait = std::true_type; +}; +template <typename I, typename E> +struct UnifiedSharedMemoryT { + using EmptyTrait = std::true_type; +}; +template <typename I, typename E> +struct UnknownT { + using EmptyTrait = std::true_type; +}; +template <typename I, typename E> +struct UntiedT { + using EmptyTrait = std::true_type; +}; +template <typename I, typename E> +struct UpdateT { + using EmptyTrait = std::true_type; +}; +template <typename I, typename E> +struct UseT { + using EmptyTrait = std::true_type; +}; +template <typename I, typename E> +struct UsesAllocatorsT { + using EmptyTrait = std::true_type; +}; +template <typename I, typename E> +struct WeakT { + using EmptyTrait = std::true_type; +}; +template <typename I, typename E> +struct WhenT { + using EmptyTrait = std::true_type; +}; +template <typename I, typename E> +struct WriteT { + using EmptyTrait = std::true_type; +}; + +template <typename I, typename E> +struct AlignedT { + using TupleTrait = std::true_type; + std::tuple<ObjectListT<I, E>, std::optional<E>> t; +}; + +template <typename I, typename E> +struct AllocateT { + struct Modifier { + struct Allocator { + using WrapperTrait = std::true_type; + E v; + }; + struct Align { + using WrapperTrait = std::true_type; + E v; + }; + struct ComplexModifier { + using TupleTrait = std::true_type; + std::tuple<Allocator, Align> t; + }; + using UnionTrait = std::true_type; + std::variant<Allocator, ComplexModifier, Align> u; + }; + using TupleTrait = std::true_type; + std::tuple<std::optional<Modifier>, ObjectListT<I, E>> t; +}; + +template <typename I, typename E> +struct AllocatorT { + using WrapperTrait = std::true_type; + E v; +}; + +template <typename I, typename E> +struct AtomicDefaultMemOrderT { + using WrapperTrait = std::true_type; + using OmpAtomicDefaultMemOrderType = + Fortran::common::OmpAtomicDefaultMemOrderType; + OmpAtomicDefaultMemOrderType v; +}; + +template <typename I, typename E> +struct CollapseT { + using WrapperTrait = std::true_type; + E v; +}; + +template <typename I, typename E> +struct CopyinT { + using WrapperTrait = std::true_type; + ObjectListT<I, E> v; +}; + +template <typename I, typename E> +struct CopyprivateT { + using WrapperTrait = std::true_type; + ObjectListT<I, E> v; +}; + +template <typename I, typename E> +struct DefaultmapT { + using ImplicitBehavior = + Fortran::parser::OmpDefaultmapClause::ImplicitBehavior; + using VariableCategory = + Fortran::parser::OmpDefaultmapClause::VariableCategory; + using TupleTrait = std::true_type; + std::tuple<ImplicitBehavior, std::optional<VariableCategory>> t; +}; + +template <typename I, typename E> +struct DefaultT { + using Type = Fortran::parser::OmpDefaultClause::Type; + using WrapperTrait = std::true_type; + Type v; +}; + +template <typename I, typename E> +struct DependT { + struct Source { + using EmptyTrait = std::true_type; + }; + struct Sink { + using Length = std::tuple<DefinedOperatorT<I, E>, E>; + using Vec = std::tuple<ObjectT<I, E>, std::optional<Length>>; + using WrapperTrait = std::true_type; + ListT<Vec> v; + }; + using Type = Fortran::parser::OmpDependenceType::Type; + struct InOut { + using TupleTrait = std::true_type; + std::tuple<Type, ObjectListT<I, E>> t; + }; + using UnionTrait = std::true_type; + std::variant<Source, Sink, InOut> u; +}; + +template <typename I, typename E> +struct DeviceT { + using DeviceModifier = Fortran::parser::OmpDeviceClause::DeviceModifier; + using TupleTrait = std::true_type; + std::tuple<std::optional<DeviceModifier>, E> t; +}; + +template <typename I, typename E> +struct DeviceTypeT { + using Type = Fortran::parser::OmpDeviceTypeClause::Type; + using WrapperTrait = std::true_type; + Type v; +}; + +template <typename I, typename E> +struct DistScheduleT { + using WrapperTrait = std::true_type; + std::optional<E> v; +}; + +template <typename I, typename E> +struct EnterT { + using WrapperTrait = std::true_type; + ObjectListT<I, E> v; +}; + +template <typename I, typename E> +struct FilterT { + using WrapperTrait = std::true_type; + E v; +}; + +template <typename I, typename E> +struct FinalT { + using WrapperTrait = std::true_type; + E v; +}; + +template <typename I, typename E> +struct FirstprivateT { + using WrapperTrait = std::true_type; + ObjectListT<I, E> v; +}; + +template <typename I, typename E> +struct FromT { + using WrapperTrait = std::true_type; + ObjectListT<I, E> v; +}; + +template <typename I, typename E> +struct GrainsizeT { + using WrapperTrait = std::true_type; + E v; +}; + +template <typename I, typename E> +struct HasDeviceAddrT { + using WrapperTrait = std::true_type; + ObjectListT<I, E> v; +}; + +template <typename I, typename E> +struct HintT { + using WrapperTrait = std::true_type; + E v; +}; + +template <typename I, typename E> +struct IfT { + using DirectiveNameModifier = + Fortran::parser::OmpIfClause::DirectiveNameModifier; + using TupleTrait = std::true_type; + std::tuple<std::optional<DirectiveNameModifier>, E> t; +}; + +template <typename I, typename E> +struct InReductionT { + using TupleTrait = std::true_type; + std::tuple<ReductionOperatorT<I, E>, ObjectListT<I, E>> t; +}; + +template <typename I, typename E> +struct IsDevicePtrT { + using WrapperTrait = std::true_type; + ObjectListT<I, E> v; +}; + +template <typename I, typename E> +struct LastprivateT { + using WrapperTrait = std::true_type; + ObjectListT<I, E> v; +}; + +template <typename I, typename E> +struct LinearT { + struct Modifier { + using Type = Fortran::parser::OmpLinearModifier::Type; + using WrapperTrait = std::true_type; + Type v; + }; + using TupleTrait = std::true_type; + std::tuple<std::optional<Modifier>, ObjectListT<I, E>, std::optional<E>> t; +}; + +template <typename I, typename E> +struct LinkT { + using WrapperTrait = std::true_type; + ObjectListT<I, E> v; +}; + +template <typename I, typename E> +struct MapT { + struct MapType { + struct Always { + using EmptyTrait = std::true_type; + }; + using Type = Fortran::parser::OmpMapType::Type; + using TupleTrait = std::true_type; + std::tuple<std::optional<Always>, Type> t; + }; + using TupleTrait = std::true_type; + std::tuple<std::optional<MapType>, ObjectListT<I, E>> t; +}; + +template <typename I, typename E> +struct NocontextT { + using WrapperTrait = std::true_type; + E v; +}; + +template <typename I, typename E> +struct NontemporalT { + using WrapperTrait = std::true_type; + ObjectListT<I, E> v; +}; + +template <typename I, typename E> +struct NovariantsT { + using WrapperTrait = std::true_type; + E v; +}; + +template <typename I, typename E> +struct NumTasksT { + using WrapperTrait = std::true_type; + E v; +}; + +template <typename I, typename E> +struct NumTeamsT { + using WrapperTrait = std::true_type; + E v; +}; + +template <typename I, typename E> +struct NumThreadsT { + using WrapperTrait = std::true_type; + E v; +}; + +template <typename I, typename E> +struct OmpxDynCgroupMemT { + using WrapperTrait = std::true_type; + E v; +}; + +template <typename I, typename E> +struct OrderedT { + using WrapperTrait = std::true_type; + std::optional<E> v; +}; + +template <typename I, typename E> +struct OrderT { + using Kind = Fortran::parser::OmpOrderModifier::Kind; + using Type = Fortran::parser::OmpOrderClause::Type; + using TupleTrait = std::true_type; + std::tuple<std::optional<Kind>, Type> t; +}; + +template <typename I, typename E> +struct PartialT { + using WrapperTrait = std::true_type; + std::optional<E> v; +}; + +template <typename I, typename E> +struct PriorityT { + using WrapperTrait = std::true_type; + E v; +}; + +template <typename I, typename E> +struct PrivateT { + using WrapperTrait = std::true_type; + ObjectListT<I, E> v; +}; + +template <typename I, typename E> +struct ProcBindT { + using Type = Fortran::parser::OmpProcBindClause::Type; + using WrapperTrait = std::true_type; + Type v; +}; + +template <typename I, typename E> +struct ReductionT { + using TupleTrait = std::true_type; + std::tuple<ReductionOperatorT<I, E>, ObjectListT<I, E>> t; +}; + +template <typename I, typename E> +struct SafelenT { + using WrapperTrait = std::true_type; + E v; +}; + +template <typename I, typename E> +struct ScheduleT { + using ModType = Fortran::parser::OmpScheduleModifierType::ModType; + struct ScheduleModifier { + using TupleTrait = std::true_type; + std::tuple<ModType, std::optional<ModType>> t; + }; + using ScheduleType = Fortran::parser::OmpScheduleClause::ScheduleType; + using TupleTrait = std::true_type; + std::tuple<std::optional<ScheduleModifier>, ScheduleType, std::optional<E>> t; +}; + +template <typename I, typename E> +struct SharedT { + using WrapperTrait = std::true_type; + ObjectListT<I, E> v; +}; + +template <typename I, typename E> +struct SimdlenT { + using WrapperTrait = std::true_type; + E v; +}; + +template <typename I, typename E> +struct SizesT { + using WrapperTrait = std::true_type; + ListT<E> v; +}; + +template <typename I, typename E> +struct TaskReductionT { + using TupleTrait = std::true_type; + std::tuple<ReductionOperatorT<I, E>, ObjectListT<I, E>> t; +}; + +template <typename I, typename E> +struct ThreadLimitT { + using WrapperTrait = std::true_type; + E v; +}; + +template <typename I, typename E> +struct ToT { + using WrapperTrait = std::true_type; + ObjectListT<I, E> v; +}; + +template <typename I, typename E> +struct UniformT { + using WrapperTrait = std::true_type; + ObjectListT<I, E> v; +}; + +template <typename I, typename E> +struct UseDeviceAddrT { + using WrapperTrait = std::true_type; + ObjectListT<I, E> v; +}; + +template <typename I, typename E> +struct UseDevicePtrT { + using WrapperTrait = std::true_type; + ObjectListT<I, E> v; +}; + +template <typename I, typename E> +using UnionOfAllClausesT = std::variant< + AcqRelT<I, E>, AcquireT<I, E>, AdjustArgsT<I, E>, AffinityT<I, E>, + AlignT<I, E>, AlignedT<I, E>, AllocateT<I, E>, AllocatorT<I, E>, + AppendArgsT<I, E>, AtT<I, E>, AtomicDefaultMemOrderT<I, E>, BindT<I, E>, + CancellationConstructTypeT<I, E>, CaptureT<I, E>, CollapseT<I, E>, + CompareT<I, E>, CopyprivateT<I, E>, CopyinT<I, E>, DefaultT<I, E>, + DefaultmapT<I, E>, DependT<I, E>, DepobjT<I, E>, DestroyT<I, E>, + DetachT<I, E>, DeviceT<I, E>, DeviceTypeT<I, E>, DistScheduleT<I, E>, + DoacrossT<I, E>, DynamicAllocatorsT<I, E>, EnterT<I, E>, ExclusiveT<I, E>, + FailT<I, E>, FilterT<I, E>, FinalT<I, E>, FirstprivateT<I, E>, FlushT<I, E>, + FromT<I, E>, FullT<I, E>, GrainsizeT<I, E>, HasDeviceAddrT<I, E>, + HintT<I, E>, IfT<I, E>, InReductionT<I, E>, InbranchT<I, E>, + InclusiveT<I, E>, IndirectT<I, E>, InitT<I, E>, IsDevicePtrT<I, E>, + LastprivateT<I, E>, LinearT<I, E>, LinkT<I, E>, MapT<I, E>, MatchT<I, E>, + MemoryOrderT<I, E>, MergeableT<I, E>, MessageT<I, E>, NogroupT<I, E>, + NowaitT<I, E>, NocontextT<I, E>, NontemporalT<I, E>, NotinbranchT<I, E>, + NovariantsT<I, E>, NumTasksT<I, E>, NumTeamsT<I, E>, NumThreadsT<I, E>, + OmpxAttributeT<I, E>, OmpxDynCgroupMemT<I, E>, OmpxBareT<I, E>, + OrderT<I, E>, OrderedT<I, E>, PartialT<I, E>, PriorityT<I, E>, + PrivateT<I, E>, ProcBindT<I, E>, ReadT<I, E>, ReductionT<I, E>, + RelaxedT<I, E>, ReleaseT<I, E>, ReverseOffloadT<I, E>, SafelenT<I, E>, + ScheduleT<I, E>, SeqCstT<I, E>, SeverityT<I, E>, SharedT<I, E>, SimdT<I, E>, + SimdlenT<I, E>, SizesT<I, E>, TaskReductionT<I, E>, ThreadLimitT<I, E>, + ThreadprivateT<I, E>, ThreadsT<I, E>, ToT<I, E>, UnifiedAddressT<I, E>, + UnifiedSharedMemoryT<I, E>, UniformT<I, E>, UnknownT<I, E>, UntiedT<I, E>, + UpdateT<I, E>, UseT<I, E>, UseDeviceAddrT<I, E>, UseDevicePtrT<I, E>, + UsesAllocatorsT<I, E>, WeakT<I, E>, WhenT<I, E>, WriteT<I, E>>; +} // namespace clause + +template <typename Id, typename Expr> +struct ClauseT { + llvm::omp::Clause id; // The numeric id of the clause + using UnionTrait = std::true_type; + clause::UnionOfAllClausesT<Id, Expr> u; +}; + +} // namespace tomp + +#endif // FORTRAN_LOWER_OPENMP_CLAUSET_H diff --git a/flang/lib/Lower/OpenMP/Clauses.cpp b/flang/lib/Lower/OpenMP/Clauses.cpp new file mode 100644 index 0000000000000000000000000000000000000000..70f232a4858e1b5ecf0b3796bab8823c9fbb5819 --- /dev/null +++ b/flang/lib/Lower/OpenMP/Clauses.cpp @@ -0,0 +1,728 @@ +//===-- 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; +} + +namespace clause { +// Helper objects +#ifdef EMPTY_CLASS +#undef EMPTY_CLASS +#endif +#define EMPTY_CLASS(cls) \ + cls make(const parser::OmpClause::cls &, semantics::SemanticsContext &) { \ + return cls{}; \ + } \ + [[maybe_unused]] extern int xyzzy_semicolon_absorber + +#ifdef WRAPPER_CLASS +#undef WRAPPER_CLASS +#endif +#define WRAPPER_CLASS(cls, content) \ + [[maybe_unused]] extern int xyzzy_semicolon_absorber +#define GEN_FLANG_CLAUSE_PARSER_CLASSES +#include "llvm/Frontend/OpenMP/OMP.inc" +#undef EMPTY_CLASS +#undef WRAPPER_CLASS + +DefinedOperator makeDefinedOperator(const parser::DefinedOperator &inp, + semantics::SemanticsContext &semaCtx) { + return std::visit( + common::visitors{ + [&](const parser::DefinedOpName &s) { + return DefinedOperator{ + DefinedOperator::DefinedOpName{makeObject(s.v, semaCtx)}}; + }, + [&](const parser::DefinedOperator::IntrinsicOperator &s) { + return DefinedOperator{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 OmpClause::T exists) has its "make". +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{{ + makeList(t0, semaCtx), + maybeApply(makeExprFn(semaCtx), t1), + }}; +} + +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); + + auto convert = [&](auto &&s) -> Allocate::Modifier { + using Modifier = Allocate::Modifier; + using Allocator = Modifier::Allocator; + using Align = Modifier::Align; + using ComplexModifier = Modifier::ComplexModifier; + + return std::visit( + common::visitors{ + [&](const wrapped::AllocateModifier::Allocator &v) { + return Modifier{Allocator{makeExpr(v.v, semaCtx)}}; + }, + [&](const wrapped::AllocateModifier::ComplexModifier &v) { + auto &s0 = std::get<wrapped::AllocateModifier::Allocator>(v.t); + auto &s1 = std::get<wrapped::AllocateModifier::Align>(v.t); + return Modifier{ComplexModifier{{ + Allocator{makeExpr(s0.v, semaCtx)}, + Align{makeExpr(s1.v, semaCtx)}, + }}}; + }, + [&](const wrapped::AllocateModifier::Align &v) { + return Modifier{Align{makeExpr(v.v, semaCtx)}}; + }, + }, + s.u); + }; + + return Allocate{{maybeApply(convert, t0), makeList(t1, semaCtx)}}; +} + +Allocator make(const parser::OmpClause::Allocator &inp, + semantics::SemanticsContext &semaCtx) { + // inp.v -> parser::ScalarIntExpr + return Allocator{makeExpr(inp.v, semaCtx)}; +} + +// 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 + return AtomicDefaultMemOrder{inp.v.v}; +} + +Collapse make(const parser::OmpClause::Collapse &inp, + semantics::SemanticsContext &semaCtx) { + // inp.v -> parser::ScalarIntConstantExpr + return Collapse{makeExpr(inp.v, semaCtx)}; +} + +Copyin make(const parser::OmpClause::Copyin &inp, + semantics::SemanticsContext &semaCtx) { + // inp.v -> parser::OmpObjectList + return Copyin{makeList(inp.v, semaCtx)}; +} + +Copyprivate make(const parser::OmpClause::Copyprivate &inp, + semantics::SemanticsContext &semaCtx) { + // inp.v -> parser::OmpObjectList + return Copyprivate{makeList(inp.v, semaCtx)}; +} + +Defaultmap make(const parser::OmpClause::Defaultmap &inp, + semantics::SemanticsContext &semaCtx) { + // inp.v -> parser::OmpDefaultmapClause + using wrapped = parser::OmpDefaultmapClause; + + auto &t0 = std::get<wrapped::ImplicitBehavior>(inp.v.t); + auto &t1 = std::get<std::optional<wrapped::VariableCategory>>(inp.v.t); + return Defaultmap{{t0, t1}}; +} + +Default make(const parser::OmpClause::Default &inp, + semantics::SemanticsContext &semaCtx) { + // inp.v -> parser::OmpDefaultClause + return Default{inp.v.v}; +} + +Depend make(const parser::OmpClause::Depend &inp, + semantics::SemanticsContext &semaCtx) { + // inp.v -> parser::OmpDependClause + using wrapped = parser::OmpDependClause; + + return std::visit( + common::visitors{ + [&](const wrapped::Source &s) { return Depend{Depend::Source{}}; }, + [&](const wrapped::Sink &s) { + auto convert = [&](const parser::OmpDependSinkVec &v) { + auto &t0 = std::get<parser::Name>(v.t); + auto &t1 = + std::get<std::optional<parser::OmpDependSinkVecLength>>(v.t); + auto convert1 = [&](const parser::OmpDependSinkVecLength &u) { + auto &s0 = std::get<parser::DefinedOperator>(u.t); + auto &s1 = std::get<parser::ScalarIntConstantExpr>(u.t); + return Depend::Sink::Length{makeDefinedOperator(s0, semaCtx), + makeExpr(s1, semaCtx)}; + }; + return Depend::Sink::Vec{makeObject(t0, semaCtx), + maybeApply(convert1, t1)}; + }; + return Depend{Depend::Sink{makeList(s.v, convert)}}; + }, + [&](const wrapped::InOut &s) { + auto &t0 = std::get<parser::OmpDependenceType>(s.t); + auto &t1 = std::get<std::list<parser::Designator>>(s.t); + auto convert = [&](const parser::Designator &t) { + return makeObject(t, semaCtx); + }; + return Depend{Depend::InOut{{t0.v, makeList(t1, convert)}}}; + }, + }, + inp.v.u); +} + +Device make(const parser::OmpClause::Device &inp, + semantics::SemanticsContext &semaCtx) { + // inp.v -> parser::OmpDeviceClause + using wrapped = parser::OmpDeviceClause; + + auto &t0 = std::get<std::optional<wrapped::DeviceModifier>>(inp.v.t); + auto &t1 = std::get<parser::ScalarIntExpr>(inp.v.t); + return Device{{t0, makeExpr(t1, semaCtx)}}; +} + +DeviceType make(const parser::OmpClause::DeviceType &inp, + semantics::SemanticsContext &semaCtx) { + // inp.v -> parser::OmpDeviceTypeClause + return DeviceType{inp.v.v}; +} + +DistSchedule make(const parser::OmpClause::DistSchedule &inp, + semantics::SemanticsContext &semaCtx) { + // inp.v -> std::optional<parser::ScalarIntExpr> + return DistSchedule{maybeApply(makeExprFn(semaCtx), inp.v)}; +} + +Enter make(const parser::OmpClause::Enter &inp, + semantics::SemanticsContext &semaCtx) { + // inp.v -> parser::OmpObjectList + return Enter{makeList(inp.v, semaCtx)}; +} + +Filter make(const parser::OmpClause::Filter &inp, + semantics::SemanticsContext &semaCtx) { + // inp.v -> parser::ScalarIntExpr + return Filter{makeExpr(inp.v, semaCtx)}; +} + +Final make(const parser::OmpClause::Final &inp, + semantics::SemanticsContext &semaCtx) { + // inp.v -> parser::ScalarLogicalExpr + return Final{makeExpr(inp.v, semaCtx)}; +} + +Firstprivate make(const parser::OmpClause::Firstprivate &inp, + semantics::SemanticsContext &semaCtx) { + // inp.v -> parser::OmpObjectList + return Firstprivate{makeList(inp.v, semaCtx)}; +} + +From make(const parser::OmpClause::From &inp, + semantics::SemanticsContext &semaCtx) { + // inp.v -> parser::OmpObjectList + return From{makeList(inp.v, semaCtx)}; +} + +Grainsize make(const parser::OmpClause::Grainsize &inp, + semantics::SemanticsContext &semaCtx) { + // inp.v -> parser::ScalarIntExpr + return Grainsize{makeExpr(inp.v, semaCtx)}; +} + +HasDeviceAddr make(const parser::OmpClause::HasDeviceAddr &inp, + semantics::SemanticsContext &semaCtx) { + // inp.v -> parser::OmpObjectList + return HasDeviceAddr{makeList(inp.v, semaCtx)}; +} + +Hint make(const parser::OmpClause::Hint &inp, + semantics::SemanticsContext &semaCtx) { + // inp.v -> parser::ConstantExpr + return Hint{makeExpr(inp.v, semaCtx)}; +} + +If make(const parser::OmpClause::If &inp, + semantics::SemanticsContext &semaCtx) { + // inp.v -> parser::OmpIfClause + using wrapped = parser::OmpIfClause; + + auto &t0 = std::get<std::optional<wrapped::DirectiveNameModifier>>(inp.v.t); + auto &t1 = std::get<parser::ScalarLogicalExpr>(inp.v.t); + return If{{t0, makeExpr(t1, semaCtx)}}; +} + +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{ + {makeReductionOperator(t0, semaCtx), makeList(t1, semaCtx)}}; +} + +IsDevicePtr make(const parser::OmpClause::IsDevicePtr &inp, + semantics::SemanticsContext &semaCtx) { + // inp.v -> parser::OmpObjectList + return IsDevicePtr{makeList(inp.v, semaCtx)}; +} + +Lastprivate make(const parser::OmpClause::Lastprivate &inp, + semantics::SemanticsContext &semaCtx) { + // inp.v -> parser::OmpObjectList + return Lastprivate{makeList(inp.v, semaCtx)}; +} + +Linear make(const parser::OmpClause::Linear &inp, + semantics::SemanticsContext &semaCtx) { + // inp.v -> parser::OmpLinearClause + using wrapped = parser::OmpLinearClause; + + return std::visit( + common::visitors{ + [&](const wrapped::WithModifier &s) { + return Linear{{Linear::Modifier{s.modifier.v}, + makeList(s.names, makeObjectFn(semaCtx)), + maybeApply(makeExprFn(semaCtx), s.step)}}; + }, + [&](const wrapped::WithoutModifier &s) { + return Linear{{std::nullopt, + makeList(s.names, makeObjectFn(semaCtx)), + maybeApply(makeExprFn(semaCtx), s.step)}}; + }, + }, + inp.v.u); +} + +Link make(const parser::OmpClause::Link &inp, + semantics::SemanticsContext &semaCtx) { + // inp.v -> parser::OmpObjectList + return Link{makeList(inp.v, semaCtx)}; +} + +Map make(const parser::OmpClause::Map &inp, + semantics::SemanticsContext &semaCtx) { + // inp.v -> parser::OmpMapClause + auto &t0 = std::get<std::optional<parser::OmpMapType>>(inp.v.t); + auto &t1 = std::get<parser::OmpObjectList>(inp.v.t); + auto convert = [](const parser::OmpMapType &s) { + auto &s0 = std::get<std::optional<parser::OmpMapType::Always>>(s.t); + auto &s1 = std::get<parser::OmpMapType::Type>(s.t); + auto convertT = [](parser::OmpMapType::Always) { + return Map::MapType::Always{}; + }; + return Map::MapType{{maybeApply(convertT, s0), s1}}; + }; + return Map{{maybeApply(convert, t0), makeList(t1, semaCtx)}}; +} + +Nocontext make(const parser::OmpClause::Nocontext &inp, + semantics::SemanticsContext &semaCtx) { + // inp.v -> parser::ScalarLogicalExpr + return Nocontext{makeExpr(inp.v, semaCtx)}; +} + +Nontemporal make(const parser::OmpClause::Nontemporal &inp, + semantics::SemanticsContext &semaCtx) { + // inp.v -> std::list<parser::Name> + return Nontemporal{makeList(inp.v, makeObjectFn(semaCtx))}; +} + +Novariants make(const parser::OmpClause::Novariants &inp, + semantics::SemanticsContext &semaCtx) { + // inp.v -> parser::ScalarLogicalExpr + return Novariants{makeExpr(inp.v, semaCtx)}; +} + +NumTasks make(const parser::OmpClause::NumTasks &inp, + semantics::SemanticsContext &semaCtx) { + // inp.v -> parser::ScalarIntExpr + return NumTasks{makeExpr(inp.v, semaCtx)}; +} + +NumTeams make(const parser::OmpClause::NumTeams &inp, + semantics::SemanticsContext &semaCtx) { + // inp.v -> parser::ScalarIntExpr + return NumTeams{makeExpr(inp.v, semaCtx)}; +} + +NumThreads make(const parser::OmpClause::NumThreads &inp, + semantics::SemanticsContext &semaCtx) { + // inp.v -> parser::ScalarIntExpr + return NumThreads{makeExpr(inp.v, semaCtx)}; +} + +OmpxDynCgroupMem make(const parser::OmpClause::OmpxDynCgroupMem &inp, + semantics::SemanticsContext &semaCtx) { + // inp.v -> parser::ScalarIntExpr + return OmpxDynCgroupMem{makeExpr(inp.v, semaCtx)}; +} + +Ordered make(const parser::OmpClause::Ordered &inp, + semantics::SemanticsContext &semaCtx) { + // inp.v -> std::optional<parser::ScalarIntConstantExpr> + return Ordered{maybeApply(makeExprFn(semaCtx), inp.v)}; +} + +Order make(const parser::OmpClause::Order &inp, + semantics::SemanticsContext &semaCtx) { + // inp.v -> parser::OmpOrderClause + using wrapped = parser::OmpOrderClause; + auto &t0 = std::get<std::optional<parser::OmpOrderModifier>>(inp.v.t); + auto &t1 = std::get<wrapped::Type>(inp.v.t); + auto convert = [](const parser::OmpOrderModifier &s) -> Order::Kind { + return std::get<parser::OmpOrderModifier::Kind>(s.u); + }; + return Order{{maybeApply(convert, t0), t1}}; +} + +Partial make(const parser::OmpClause::Partial &inp, + semantics::SemanticsContext &semaCtx) { + // inp.v -> std::optional<parser::ScalarIntConstantExpr> + return Partial{maybeApply(makeExprFn(semaCtx), inp.v)}; +} + +Priority make(const parser::OmpClause::Priority &inp, + semantics::SemanticsContext &semaCtx) { + // inp.v -> parser::ScalarIntExpr + return Priority{makeExpr(inp.v, semaCtx)}; +} + +Private make(const parser::OmpClause::Private &inp, + semantics::SemanticsContext &semaCtx) { + // inp.v -> parser::OmpObjectList + return Private{makeList(inp.v, semaCtx)}; +} + +ProcBind make(const parser::OmpClause::ProcBind &inp, + semantics::SemanticsContext &semaCtx) { + // inp.v -> parser::OmpProcBindClause + return ProcBind{inp.v.v}; +} + +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{{makeReductionOperator(t0, semaCtx), makeList(t1, semaCtx)}}; +} + +Safelen make(const parser::OmpClause::Safelen &inp, + semantics::SemanticsContext &semaCtx) { + // inp.v -> parser::ScalarIntConstantExpr + return Safelen{makeExpr(inp.v, semaCtx)}; +} + +Schedule make(const parser::OmpClause::Schedule &inp, + semantics::SemanticsContext &semaCtx) { + // inp.v -> parser::OmpScheduleClause + using wrapped = parser::OmpScheduleClause; + + 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); + + auto convert = [](auto &&s) -> Schedule::ScheduleModifier { + auto &s0 = std::get<parser::OmpScheduleModifier::Modifier1>(s.t); + auto &s1 = + std::get<std::optional<parser::OmpScheduleModifier::Modifier2>>(s.t); + + auto convert1 = [](auto &&v) { // Modifier1 or Modifier2 + return v.v.v; + }; + return Schedule::ScheduleModifier{{s0.v.v, maybeApply(convert1, s1)}}; + }; + + return Schedule{ + {maybeApply(convert, t0), t1, maybeApply(makeExprFn(semaCtx), t2)}}; +} + +Shared make(const parser::OmpClause::Shared &inp, + semantics::SemanticsContext &semaCtx) { + // inp.v -> parser::OmpObjectList + return Shared{makeList(inp.v, semaCtx)}; +} + +Simdlen make(const parser::OmpClause::Simdlen &inp, + semantics::SemanticsContext &semaCtx) { + // inp.v -> parser::ScalarIntConstantExpr + return Simdlen{makeExpr(inp.v, semaCtx)}; +} + +Sizes make(const parser::OmpClause::Sizes &inp, + semantics::SemanticsContext &semaCtx) { + // inp.v -> std::list<parser::ScalarIntExpr> + return Sizes{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{ + {makeReductionOperator(t0, semaCtx), makeList(t1, semaCtx)}}; +} + +ThreadLimit make(const parser::OmpClause::ThreadLimit &inp, + semantics::SemanticsContext &semaCtx) { + // inp.v -> parser::ScalarIntExpr + return ThreadLimit{makeExpr(inp.v, semaCtx)}; +} + +To make(const parser::OmpClause::To &inp, + semantics::SemanticsContext &semaCtx) { + // inp.v -> parser::OmpObjectList + return To{makeList(inp.v, semaCtx)}; +} + +Uniform make(const parser::OmpClause::Uniform &inp, + semantics::SemanticsContext &semaCtx) { + // inp.v -> std::list<parser::Name> + return Uniform{makeList(inp.v, makeObjectFn(semaCtx))}; +} + +UseDeviceAddr make(const parser::OmpClause::UseDeviceAddr &inp, + semantics::SemanticsContext &semaCtx) { + // inp.v -> parser::OmpObjectList + return UseDeviceAddr{makeList(inp.v, semaCtx)}; +} + +UseDevicePtr make(const parser::OmpClause::UseDevicePtr &inp, + semantics::SemanticsContext &semaCtx) { + // inp.v -> parser::OmpObjectList + return UseDevicePtr{makeList(inp.v, semaCtx)}; +} +} // 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> makeList(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..3fba593b5349c18c96c4bbfe3983b0ededb7d9e1 --- /dev/null +++ b/flang/lib/Lower/OpenMP/Clauses.h @@ -0,0 +1,212 @@ +//===-- 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 "ClauseT.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 <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 SymIdent = semantics::Symbol *; +using SymReference = SomeExpr; + +template <typename T> +using List = tomp::ListT<T>; +} // namespace Fortran::lower::omp + +namespace tomp { +template <> +struct ObjectT<Fortran::lower::omp::SymIdent, + Fortran::lower::omp::SymReference> { + using IdType = Fortran::lower::omp::SymIdent; + using ExprType = Fortran::lower::omp::SymReference; + + const IdType &id() const { return symbol; } + const std::optional<ExprType> &ref() const { return designator; } + + IdType symbol; + std::optional<ExprType> designator; +}; +} // namespace tomp + +namespace Fortran::lower::omp { + +using Object = tomp::ObjectT<SymIdent, SymReference>; +using ObjectList = tomp::ObjectListT<SymIdent, SymReference>; + +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 makeList(const parser::OmpObjectList &objects, + semantics::SemanticsContext &semaCtx) { + return makeList(objects.v, makeObjectFn(semaCtx)); +} + +template <typename FuncTy, typename ElemTy, + typename ResultTy = std::invoke_result_t<FuncTy, ElemTy>> +std::optional<ResultTy> maybeApply(FuncTy &&func, + const std::optional<ElemTy> &inp) { + if (!inp) + return std::nullopt; + return std::move(func(*inp)); +} + +std::optional<Object> +getBaseObject(const Object &object, + Fortran::semantics::SemanticsContext &semaCtx); + +namespace clause { +using DefinedOperator = tomp::clause::DefinedOperatorT<SymIdent, SymReference>; +using ProcedureDesignator = + tomp::clause::ProcedureDesignatorT<SymIdent, SymReference>; +using ReductionOperator = + tomp::clause::ReductionOperatorT<SymIdent, SymReference>; + +#ifdef EMPTY_CLASS +#undef EMPTY_CLASS +#endif +#define EMPTY_CLASS(cls) \ + using cls = tomp::clause::cls##T<SymIdent, SymReference> + +#ifdef WRAPPER_CLASS +#undef WRAPPER_CLASS +#endif +#define WRAPPER_CLASS(cls, content) \ + [[maybe_unused]] extern int xyzzy_semicolon_absorber +#define GEN_FLANG_CLAUSE_PARSER_CLASSES +#include "llvm/Frontend/OpenMP/OMP.inc" +#undef EMPTY_CLASS +#undef WRAPPER_CLASS + +// "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 Aligned = tomp::clause::AlignedT<SymIdent, SymReference>; +using Allocate = tomp::clause::AllocateT<SymIdent, SymReference>; +using Allocator = tomp::clause::AllocatorT<SymIdent, SymReference>; +using AtomicDefaultMemOrder = + tomp::clause::AtomicDefaultMemOrderT<SymIdent, SymReference>; +using Collapse = tomp::clause::CollapseT<SymIdent, SymReference>; +using Copyin = tomp::clause::CopyinT<SymIdent, SymReference>; +using Copyprivate = tomp::clause::CopyprivateT<SymIdent, SymReference>; +using Defaultmap = tomp::clause::DefaultmapT<SymIdent, SymReference>; +using Default = tomp::clause::DefaultT<SymIdent, SymReference>; +using Depend = tomp::clause::DependT<SymIdent, SymReference>; +using Device = tomp::clause::DeviceT<SymIdent, SymReference>; +using DeviceType = tomp::clause::DeviceTypeT<SymIdent, SymReference>; +using DistSchedule = tomp::clause::DistScheduleT<SymIdent, SymReference>; +using Enter = tomp::clause::EnterT<SymIdent, SymReference>; +using Filter = tomp::clause::FilterT<SymIdent, SymReference>; +using Final = tomp::clause::FinalT<SymIdent, SymReference>; +using Firstprivate = tomp::clause::FirstprivateT<SymIdent, SymReference>; +using From = tomp::clause::FromT<SymIdent, SymReference>; +using Grainsize = tomp::clause::GrainsizeT<SymIdent, SymReference>; +using HasDeviceAddr = tomp::clause::HasDeviceAddrT<SymIdent, SymReference>; +using Hint = tomp::clause::HintT<SymIdent, SymReference>; +using If = tomp::clause::IfT<SymIdent, SymReference>; +using InReduction = tomp::clause::InReductionT<SymIdent, SymReference>; +using IsDevicePtr = tomp::clause::IsDevicePtrT<SymIdent, SymReference>; +using Lastprivate = tomp::clause::LastprivateT<SymIdent, SymReference>; +using Linear = tomp::clause::LinearT<SymIdent, SymReference>; +using Link = tomp::clause::LinkT<SymIdent, SymReference>; +using Map = tomp::clause::MapT<SymIdent, SymReference>; +using Nocontext = tomp::clause::NocontextT<SymIdent, SymReference>; +using Nontemporal = tomp::clause::NontemporalT<SymIdent, SymReference>; +using Novariants = tomp::clause::NovariantsT<SymIdent, SymReference>; +using NumTasks = tomp::clause::NumTasksT<SymIdent, SymReference>; +using NumTeams = tomp::clause::NumTeamsT<SymIdent, SymReference>; +using NumThreads = tomp::clause::NumThreadsT<SymIdent, SymReference>; +using OmpxDynCgroupMem = + tomp::clause::OmpxDynCgroupMemT<SymIdent, SymReference>; +using Ordered = tomp::clause::OrderedT<SymIdent, SymReference>; +using Order = tomp::clause::OrderT<SymIdent, SymReference>; +using Partial = tomp::clause::PartialT<SymIdent, SymReference>; +using Priority = tomp::clause::PriorityT<SymIdent, SymReference>; +using Private = tomp::clause::PrivateT<SymIdent, SymReference>; +using ProcBind = tomp::clause::ProcBindT<SymIdent, SymReference>; +using Reduction = tomp::clause::ReductionT<SymIdent, SymReference>; +using Safelen = tomp::clause::SafelenT<SymIdent, SymReference>; +using Schedule = tomp::clause::ScheduleT<SymIdent, SymReference>; +using Shared = tomp::clause::SharedT<SymIdent, SymReference>; +using Simdlen = tomp::clause::SimdlenT<SymIdent, SymReference>; +using Sizes = tomp::clause::SizesT<SymIdent, SymReference>; +using TaskReduction = tomp::clause::TaskReductionT<SymIdent, SymReference>; +using ThreadLimit = tomp::clause::ThreadLimitT<SymIdent, SymReference>; +using To = tomp::clause::ToT<SymIdent, SymReference>; +using Uniform = tomp::clause::UniformT<SymIdent, SymReference>; +using UseDeviceAddr = tomp::clause::UseDeviceAddrT<SymIdent, SymReference>; +using UseDevicePtr = tomp::clause::UseDevicePtrT<SymIdent, SymReference>; +} // namespace clause + +struct Clause : public tomp::ClauseT<SymIdent, SymReference> { + 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> makeList(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..e1aa7524e930d6c9d04be905ad050f055ead379e 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,26 @@ 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)) { + std::get_if<omp::clause::Lastprivate>(&clause.u)) { collectOmpObjectListSymbol(lastPrivateClause->v, 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 +134,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 +286,12 @@ 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) + for (const omp::Clause &clause : clauses) { + if (const auto *defaultClause = + std::get_if<omp::clause::Default>(&clause.u)) { + if (defaultClause->v == omp::clause::Default::Type::Private) collectSymbols(Fortran::semantics::Symbol::Flag::OmpPrivate); - else if (defaultClause->v.v == - Fortran::parser::OmpDefaultClause::Type::Firstprivate) + else if (defaultClause->v == omp::clause::Default::Type::Firstprivate) collectSymbols(Fortran::semantics::Symbol::Flag::OmpFirstPrivate); } } @@ -376,6 +368,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 +379,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 +397,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..226abe96705e35de7125def1a142aa71494cb8c8 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::makeList(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..02901ed070a76bdecc1c56fcbe1ebd370b948b87 100644 --- a/flang/lib/Lower/OpenMP/OpenMP.cpp +++ b/flang/lib/Lower/OpenMP/OpenMP.cpp @@ -214,24 +214,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, @@ -287,9 +269,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 +299,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 +347,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 +355,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 +447,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 +550,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(clause::If::DirectiveNameModifier::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 +576,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 +599,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 +663,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 +726,7 @@ genTaskOp(Fortran::lower::AbstractConverter &converter, dependOperands; ClauseProcessor cp(converter, semaCtx, clauseList); - cp.processIf(Fortran::parser::OmpIfClause::DirectiveNameModifier::Task, - ifClauseOperand); + cp.processIf(clause::If::DirectiveNameModifier::Task, ifClauseOperand); cp.processAllocate(allocatorOperands, allocateOperands); cp.processDefault(); cp.processFinal(stmtCtx, finalClauseOperand); @@ -755,9 +734,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 +751,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 +760,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 +770,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 +838,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(clause::If::DirectiveNameModifier::TargetData, 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 +871,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,20 +883,17 @@ genEnterExitUpdateDataOp(Fortran::lower::AbstractConverter &converter, llvm::SmallVector<mlir::Value> mapOperands, dependOperands; llvm::SmallVector<mlir::Attribute> dependTypeOperands; - Fortran::parser::OmpIfClause::DirectiveNameModifier directiveName; + clause::If::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>) { + directiveName = clause::If::DirectiveNameModifier::TargetEnterData; 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>) { + directiveName = clause::If::DirectiveNameModifier::TargetExitData; 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>) { + directiveName = clause::If::DirectiveNameModifier::TargetUpdate; directive = llvm::omp::Directive::OMPD_target_update; } else { return nullptr; @@ -865,12 +905,9 @@ genEnterExitUpdateDataOp(Fortran::lower::AbstractConverter &converter, 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 +923,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 +1092,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(clause::If::DirectiveNameModifier::Target, ifClauseOperand); cp.processDevice(stmtCtx, deviceOperand); cp.processThreadLimit(stmtCtx, threadLimitOperand); cp.processDepend(dependTypeOperands, dependOperands); @@ -1064,16 +1100,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 +1130,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 +1218,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(clause::If::DirectiveNameModifier::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 +1257,9 @@ static mlir::omp::DeclareTargetDeviceType getDeclareTargetInfo( if (const auto *objectList{ Fortran::parser::Unwrap<Fortran::parser::OmpObjectList>(spec.u)}) { + ObjectList objects{makeList(*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 +1276,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 +1359,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 +1367,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 +1396,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 +1406,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 +1430,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 +1482,7 @@ genLoopAndReductionVars( converter.bindSymbol(*arg, prv); } - return loopArgs; + return llvm::SmallVector<const Fortran::semantics::Symbol *>(loopArgs); } static void @@ -1511,7 +1493,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 +1501,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(clause::If::DirectiveNameModifier::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 +1537,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 +1545,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 +1553,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 +1581,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 +1609,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 +1622,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 +1640,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 Fortran::parser::OpenMPDeclareReductionConstruct + &declareReductionConstruct) { + TODO(converter.getCurrentLocation(), "OpenMPDeclareReductionConstruct"); +} - 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(); - }(); +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"); +} - 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::OpenMPDeclareTargetConstruct + &declareTargetConstruct) { + llvm::SmallVector<DeclareTargetCapturePair> symbolAndClause; + mlir::ModuleOp mod = converter.getFirOpBuilder().getModule(); + mlir::omp::DeclareTargetDeviceType deviceType = getDeclareTargetInfo( + converter, semaCtx, eval, declareTargetConstruct, symbolAndClause); - if (!validDirective) { - TODO(currentLocation, "Unhandled loop directive (" + - llvm::omp::getOpenMPDirectiveName(ompDirective) + - ")"); - } + for (const DeclareTargetCapturePair &symClause : symbolAndClause) { + mlir::Operation *op = mod.lookupSymbol(converter.mangleName( + std::get<const Fortran::semantics::Symbol &>(symClause))); - if (llvm::omp::allDoSimdSet.test(ompDirective)) { - // 2.9.3.2 Workshare SIMD construct - createSimdWsLoop(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; - } 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); + 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 +1891,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 +1999,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 +2165,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 +2194,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 +2205,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 @@ -2345,106 +2355,100 @@ void Fortran::lower::genOpenMPReduction( const Fortran::parser::OmpClauseList &clauseList) { fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); - for (const Fortran::parser::OmpClause &clause : clauseList.v) { + List<Clause> clauses{makeList(clauseList, semaCtx)}; + + for (const Clause &clause : clauses) { 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)}; + std::get_if<clause::Reduction>(&clause.u)) { + const auto &redOperator{ + std::get<clause::ReductionOperator>(reductionClause->t)}; + const auto &objects{std::get<ObjectList>(reductionClause->t)}; if (const auto *reductionOp = - std::get_if<Fortran::parser::DefinedOperator>(&redOperator.u)) { + std::get_if<clause::DefinedOperator>(&redOperator.u)) { const auto &intrinsicOp{ - std::get<Fortran::parser::DefinedOperator::IntrinsicOperator>( + std::get<clause::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: + 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 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); - } + 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<Fortran::parser::ProcedureDesignator>( - &redOperator.u)) { + std::get_if<clause::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); - } + 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); } } } diff --git a/flang/lib/Lower/OpenMP/ReductionProcessor.cpp b/flang/lib/Lower/OpenMP/ReductionProcessor.cpp index a8b98f3f567249a249ae8e0f6383392319d76745..2477f635792a25418b9c7acf1233b1481e96df42 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,96 @@ 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; + mlir::omp::DeclareReductionOp decl; const auto &redOperator{ - std::get<Fortran::parser::OmpReductionOperator>(reduction.t)}; - const auto &objectList{std::get<Fortran::parser::OmpObjectList>(reduction.t)}; + std::get<omp::clause::ReductionOperator>(reduction.t)}; + 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 +564,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..2bcd5e5914027d44a3e5fa6a1fe07e6f77473706 100644 --- a/flang/lib/Optimizer/Builder/FIRBuilder.cpp +++ b/flang/lib/Optimizer/Builder/FIRBuilder.cpp @@ -208,6 +208,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()); 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..ea1ef1f08aba2080e0aed202dc8313e9c381b02d 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", @@ -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}, @@ -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/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/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/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/unparse.cpp b/flang/lib/Parser/unparse.cpp index 600aa01999dab79e0bb49ee855e9f1a1887e2671..baba4863f5775fa22adcf420f8b42c9d2a5d8dc6 100644 --- a/flang/lib/Parser/unparse.cpp +++ b/flang/lib/Parser/unparse.cpp @@ -2729,6 +2729,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..d625f8c2f7fc118959362f5aea02b2ed53e7df29 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())}) { diff --git a/flang/lib/Semantics/check-declarations.cpp b/flang/lib/Semantics/check-declarations.cpp index 431cef207935085e79b73705c9ae696e49da190f..581371ff7a003143220856a67056e19626262bb0 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) { 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/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..f89323f3e54a627a97d501a63e59073dd6240a2d 100644 --- a/flang/lib/Semantics/resolve-names.cpp +++ b/flang/lib/Semantics/resolve-names.cpp @@ -3391,12 +3391,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 +4432,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>()) { 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..2230047abd722082cbd53015763edfb32ceef405 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()}; @@ -827,15 +839,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); + } } } } 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..02147487115497d22b06ec6ed9ea9fe9f6cea25d 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,6 +150,7 @@ set(sources numeric.cpp pointer.cpp product.cpp + pseudo-unit.cpp ragged.cpp random.cpp reduction.cpp 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/connection.h b/flang/runtime/connection.h index c9a7566f209881c0b8824143adc6336d030175c5..c41970d47e7b097bd15116c571e1337c78df0b8c 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,10 +26,10 @@ 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 { // Formatted stream files are viewed as having records, at least on input @@ -63,14 +63,14 @@ struct ConnectionState : public ConnectionAttributes { unterminatedRecord = false; } - std::optional<std::int64_t> EffectiveRecordLength() const { + 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 +86,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 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/descriptor-io.cpp b/flang/runtime/descriptor-io.cpp index 6041104773cc490e492b5c58fab019bff94a6e49..7c7323b719adf871c700f3e4af04cb9948a3dd86 100644 --- a/flang/runtime/descriptor-io.cpp +++ b/flang/runtime/descriptor-io.cpp @@ -12,11 +12,12 @@ namespace Fortran::runtime::io::descr { // 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)) { @@ -55,7 +56,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 +97,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; } } diff --git a/flang/runtime/descriptor-io.h b/flang/runtime/descriptor-io.h index 394578796faa7928b5bfd7b54fc74c3dd1586fd6..b6b0fefcff870b9ff2c5d63d708ee20206d8fd29 100644 --- a/flang/runtime/descriptor-io.h +++ b/flang/runtime/descriptor-io.h @@ -21,6 +21,7 @@ #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" @@ -321,9 +322,9 @@ static bool DefaultComponentwiseUnformattedIO(IoStatementState &io, return true; } -std::optional<bool> DefinedFormattedIo(IoStatementState &, const Descriptor &, - const typeInfo::DerivedType &, const typeInfo::SpecialBinding &, - const SubscriptValue[]); +Fortran::common::optional<bool> DefinedFormattedIo(IoStatementState &, + const Descriptor &, const typeInfo::DerivedType &, + const typeInfo::SpecialBinding &, const SubscriptValue[]); template <Direction DIR> static bool FormattedDerivedTypeIO(IoStatementState &io, @@ -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); } @@ -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; } diff --git a/flang/runtime/edit-input.cpp b/flang/runtime/edit-input.cpp index 85cce2f1a16623ccef09f88905b9ace1687775d6..fbeb1a595b327ef3f2d4a8a849ec99ade70f89b9 100644 --- a/flang/runtime/edit-input.cpp +++ b/flang/runtime/edit-input.cpp @@ -9,6 +9,7 @@ #include "edit-input.h" #include "namelist.h" #include "utf.h" +#include "flang/Common/optional.h" #include "flang/Common/real.h" #include "flang/Common/uint128.h" #include <algorithm> @@ -54,9 +55,9 @@ template <int LOG2_BASE> static 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; @@ -156,7 +157,8 @@ static inline char32_t GetRadixPointChar(const DataEdit &edit) { // 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) { + Fortran::common::optional<char32_t> &next, + Fortran::common::optional<int> &remaining) { remaining = io.CueUpInput(edit); next = io.NextInField(remaining, edit); char sign{'\0'}; @@ -198,8 +200,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}; @@ -279,10 +281,10 @@ struct ScannedRealInput { }; static 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; + Fortran::common::optional<int> radixPointOffset; auto Put{[&](char ch) -> void { if (got < bufferSize) { buffer[got] = ch; @@ -612,11 +614,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 +645,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 @@ -833,8 +848,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); } @@ -916,8 +931,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 ' ': diff --git a/flang/runtime/edit-output.cpp b/flang/runtime/edit-output.cpp index b474c8cd91bae4208747bf1434d22c5436db8302..7267540370fc0782edc2e7a1786a1662d7f2817f 100644 --- a/flang/runtime/edit-output.cpp +++ b/flang/runtime/edit-output.cpp @@ -9,6 +9,7 @@ #include "edit-output.h" #include "emit-encoded.h" #include "utf.h" +#include "flang/Common/real.h" #include "flang/Common/uint128.h" #include <algorithm> @@ -700,7 +701,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)}; 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..9bc1158509615ff9196967e13c35d216c443a761 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; @@ -29,10 +29,15 @@ constexpr bool isHostLittleEndian{true}; // 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 +53,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..9d650ceca4a8ccb5ec9506f652d45eb61cff16ee --- /dev/null +++ b/flang/runtime/external-unit.cpp @@ -0,0 +1,333 @@ +//===-- 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 "tools.h" + +#if !defined(RT_USE_PSEUDO_FILE_UNIT) + +#include "io-error.h" +#include "lock.h" +#include "unit-map.h" +#include "unit.h" +#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..6ca5776f812a04d2f7881f7d2a8435e66f2c41dc 100644 --- a/flang/runtime/file.cpp +++ b/flang/runtime/file.cpp @@ -60,7 +60,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 +322,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) { diff --git a/flang/runtime/file.h b/flang/runtime/file.h index a0712136a7f3dfde1988daf511800a80cd8164b6..17deeb0e2f827073513e967956000174554998d6 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 diff --git a/flang/runtime/format-implementation.h b/flang/runtime/format-implementation.h index 9c342db2e19a24601fde9a59323e3e4da0fcf5be..b84e3208271b7546539d2cf06d81f0be786df758 100644 --- a/flang/runtime/format-implementation.h +++ b/flang/runtime/format-implementation.h @@ -66,15 +66,6 @@ template <typename CONTEXT> 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 || @@ -233,7 +233,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 +246,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 +304,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,7 +419,7 @@ int FormatControl<CONTEXT>::CueUpNextDataEdit(Context &context, bool stop) { // Returns the next data edit descriptor template <typename CONTEXT> -std::optional<DataEdit> FormatControl<CONTEXT>::GetNextDataEdit( +Fortran::common::optional<DataEdit> FormatControl<CONTEXT>::GetNextDataEdit( Context &context, int maxRepeat) { int repeat{CueUpNextDataEdit(context)}; auto start{offset_}; @@ -444,7 +451,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 +460,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 +475,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 +486,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' diff --git a/flang/runtime/format.h b/flang/runtime/format.h index 1fe0802ac43c6959d141ba554465c1f8db84ba74..e7d945599640411e79121be3d6ed9a986fd78abc 100644 --- a/flang/runtime/format.h +++ b/flang/runtime/format.h @@ -14,9 +14,9 @@ #include "environment.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; @@ -64,9 +64,9 @@ struct DataEdit { 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}; @@ -102,7 +102,8 @@ 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); + 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. diff --git a/flang/runtime/freestanding-tools.h b/flang/runtime/freestanding-tools.h index bdc11ae93ac9097066f09f928c439c04bbe21169..682b4c9b89294bb36d49a79f0e071c6deb583870 100644 --- a/flang/runtime/freestanding-tools.h +++ b/flang/runtime/freestanding-tools.h @@ -42,6 +42,11 @@ #define STD_REALLOC_UNSUPPORTED 1 #endif +#if !defined(STD_MEMCHR_UNSUPPORTED) && \ + (defined(__CUDACC__) || defined(__CUDA__)) && defined(__CUDA_ARCH__) +#define STD_MEMCHR_UNSUPPORTED 1 +#endif + namespace Fortran::runtime { #if STD_FILL_N_UNSUPPORTED @@ -134,5 +139,23 @@ 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 + } // 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..66140e0058872314a4fc9df8248e325fc055b705 100644 --- a/flang/runtime/internal-unit.cpp +++ b/flang/runtime/internal-unit.cpp @@ -41,16 +41,6 @@ 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( const char *data, std::size_t bytes, IoErrorHandler &handler) { @@ -109,7 +99,11 @@ std::size_t InternalDescriptorUnit<DIR>::GetNextInputBytes( template <Direction DIR> 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) { diff --git a/flang/runtime/internal-unit.h b/flang/runtime/internal-unit.h index f0c50aac98878f9af3ea7dbbc32b345af9596155..b536ffb831d55040ebfb6e453ac89b45d90b51be 100644 --- a/flang/runtime/internal-unit.h +++ b/flang/runtime/internal-unit.h @@ -28,7 +28,6 @@ public: std::conditional_t<DIR == Direction::Input, const char *, char *>; InternalDescriptorUnit(Scalar, std::size_t chars, int kind); InternalDescriptorUnit(const Descriptor &, const Terminator &); - void EndIoStatement(); bool Emit(const char *, std::size_t, IoErrorHandler &); std::size_t GetNextInputBytes(const char *&, IoErrorHandler &); diff --git a/flang/runtime/io-api.cpp b/flang/runtime/io-api.cpp index 0ac20d3346dd5b3c65cf4e05f2e02526dd448a92..094db5572f15c2dcba7e7ca02e10827db4e450cb 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> @@ -168,7 +169,7 @@ static Cookie NoopUnit(const Terminator &terminator, int unitNumber, } static ExternalFileUnit *GetOrCreateUnit(int unitNumber, Direction direction, - std::optional<bool> isUnformatted, const Terminator &terminator, + Fortran::common::optional<bool> isUnformatted, const Terminator &terminator, Cookie &errorCookie) { if (ExternalFileUnit * unit{ExternalFileUnit::LookUpOrCreateAnonymous( @@ -472,8 +473,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 +493,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 +802,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: diff --git a/flang/runtime/io-stmt.cpp b/flang/runtime/io-stmt.cpp index 3ec01ffba9bf0658fafb29d213289dc9a1637052..e3f1214324d88704924dd522a68384048645474f 100644 --- a/flang/runtime/io-stmt.cpp +++ b/flang/runtime/io-stmt.cpp @@ -39,9 +39,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; + return Fortran::common::nullopt; } ExternalFileUnit *IoStatementBase::GetExternalFileUnit() const { @@ -119,9 +119,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); @@ -165,7 +162,8 @@ 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 +187,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 +227,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 +476,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 +551,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 +583,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 +600,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 +628,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 +637,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 +732,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 +749,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 +805,7 @@ ListDirectedStatementState<Direction::Input>::GetNextDataEdit( } eatComma_ = true; if (!ch) { - return std::nullopt; + return Fortran::common::nullopt; } if (*ch == '/') { hitSlash_ = true; diff --git a/flang/runtime/io-stmt.h b/flang/runtime/io-stmt.h index 0b6bcbd9af025ae6af2768a128d31a8770de6837..e00d54980aae594c84837eb44717721a9fd8407a 100644 --- a/flang/runtime/io-stmt.h +++ b/flang/runtime/io-stmt.h @@ -16,6 +16,8 @@ #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" @@ -94,7 +96,7 @@ public: 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); + Fortran::common::optional<DataEdit> GetNextDataEdit(int maxRepeat = 1); ExternalFileUnit *GetExternalFileUnit() const; // null if internal unit bool BeginReadingRecord(); void FinishReadingRecord(); @@ -122,7 +124,7 @@ public: } // Vacant after the end of the current record - std::optional<char32_t> GetCurrentChar(std::size_t &byteCount); + 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 +132,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; + 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 +150,8 @@ public: return remaining; } - std::optional<char32_t> SkipSpaces(std::optional<int> &remaining) { + 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,27 +170,27 @@ 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 &); + 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); // Skips spaces, advances records, and ignores NAMELIST comments - std::optional<char32_t> GetNextNonBlank(std::size_t &byteCount) { + 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); } @@ -208,39 +211,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_; }; @@ -262,7 +273,7 @@ public: void BackspaceRecord(); void HandleRelativePosition(std::int64_t); void HandleAbsolutePosition(std::int64_t); - std::optional<DataEdit> GetNextDataEdit( + Fortran::common::optional<DataEdit> GetNextDataEdit( IoStatementState &, int maxRepeat = 1); ExternalFileUnit *GetExternalFileUnit() const; bool BeginReadingRecord(); @@ -287,7 +298,7 @@ class ListDirectedStatementState<Direction::Output> public: bool EmitLeadingSpaceOrAdvance( IoStatementState &, std::size_t = 1, bool isCharacter = false); - std::optional<DataEdit> GetNextDataEdit( + Fortran::common::optional<DataEdit> GetNextDataEdit( IoStatementState &, int maxRepeat = 1); bool lastWasUndelimitedCharacter() const { return lastWasUndelimitedCharacter_; @@ -309,7 +320,7 @@ public: // Skips value separators, handles repetition and null values. // Vacant when '/' appears; present with descriptor == ListDirectedNullValue // when a null value appears. - std::optional<DataEdit> GetNextDataEdit( + Fortran::common::optional<DataEdit> GetNextDataEdit( IoStatementState &, int maxRepeat = 1); // Each NAMELIST input item is treated like a distinct list-directed @@ -328,7 +339,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}; @@ -380,7 +391,7 @@ public: IoStatementState &ioStatementState() { return ioStatementState_; } void CompleteOperation(); int EndIoStatement(); - std::optional<DataEdit> GetNextDataEdit( + Fortran::common::optional<DataEdit> GetNextDataEdit( IoStatementState &, int maxRepeat = 1) { return format_.GetNextDataEdit(*this, maxRepeat); } @@ -403,6 +414,7 @@ public: const Descriptor &, const char *sourceFile = nullptr, int sourceLine = 0); IoStatementState &ioStatementState() { return ioStatementState_; } using ListDirectedStatementState<DIR>::GetNextDataEdit; + void CompleteOperation(); int EndIoStatement(); private: @@ -464,7 +476,7 @@ public: const char *sourceFile = nullptr, int sourceLine = 0); void CompleteOperation(); int EndIoStatement(); - std::optional<DataEdit> GetNextDataEdit( + Fortran::common::optional<DataEdit> GetNextDataEdit( IoStatementState &, int maxRepeat = 1) { return format_.GetNextDataEdit(*this, maxRepeat); } @@ -522,7 +534,7 @@ public: void CompleteOperation(); int EndIoStatement(); bool AdvanceRecord(int = 1); - std::optional<DataEdit> GetNextDataEdit( + Fortran::common::optional<DataEdit> GetNextDataEdit( IoStatementState &, int maxRepeat = 1) { return format_.GetNextDataEdit(*this, maxRepeat); } @@ -570,14 +582,14 @@ public: 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 { diff --git a/flang/runtime/lock.h b/flang/runtime/lock.h index 5fdcf4745c21c2f73e2651b764f97d5078a0eac7..61b06a62ff7c882e2db26e1758d801ece879ba2c 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. + void Take() {} + bool Try() { return true; } + void Drop() {} + 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_; 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/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..ac9234f4af832b294053e71ed048c6cb0414622d 100644 --- a/flang/runtime/namelist.cpp +++ b/flang/runtime/namelist.cpp @@ -116,10 +116,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 +137,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 +159,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 +283,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; @@ -346,7 +347,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 +437,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)}; diff --git a/flang/runtime/numeric-templates.h b/flang/runtime/numeric-templates.h index ecc3b2654d9652ab46f52d2d98e2dd48a456d5c3..8ea3daaa57bcf8275f2ea5269bc9ebd426361f3b 100644 --- a/flang/runtime/numeric-templates.h +++ b/flang/runtime/numeric-templates.h @@ -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); } }; diff --git a/flang/runtime/pointer.cpp b/flang/runtime/pointer.cpp index fc9e0eeb7dac99e16f3ec8f5e0c7f832a3bafe37..b01735dc30e691c56e093a0b454ae0c1b82b82ff 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,18 +185,23 @@ 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 !defined(RT_DEVICE_COMPILATION) + 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); + } } +#endif return ReturnError(terminator, pointer.Destroy(/*finalize=*/true, /*destroyPointers=*/true, &terminator), errMsg, hasStat); diff --git a/flang/runtime/pseudo-unit.cpp b/flang/runtime/pseudo-unit.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8b5f36e2233a4702aaf45542724c991264b5a1ba --- /dev/null +++ b/flang/runtime/pseudo-unit.cpp @@ -0,0 +1,167 @@ +//===-- 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 "tools.h" + +#if defined(RT_USE_PSEUDO_FILE_UNIT) + +#include "io-error.h" +#include "unit.h" +#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/tools.cpp b/flang/runtime/tools.cpp index e653323ed1de0379a590d9e49ce3ec74c3d3df86..71022c7a8c179d6600bb5e48ba2c0b7f60410394 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'; diff --git a/flang/runtime/tools.h b/flang/runtime/tools.h index c1f89cadca06e79d0ebf6051a6212a6f73f25adb..c70a1b438e33295576e6544a43659b9dec5dc5c6 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; @@ -95,7 +117,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 +135,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 +356,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 +413,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 +451,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. 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..67f4775ae0a99b3939b437cdc769487020b9b8c5 100644 --- a/flang/runtime/unit.cpp +++ b/flang/runtime/unit.cpp @@ -5,291 +5,23 @@ // 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; - - 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); - } -} +ExternalFileUnit *defaultInput{nullptr}; // unit 5 +ExternalFileUnit *defaultOutput{nullptr}; // unit 6 +ExternalFileUnit *errorOutput{nullptr}; // unit 0 extension static inline void SwapEndianness( char *data, std::size_t bytes, std::size_t elementBytes) { @@ -997,39 +729,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)}; diff --git a/flang/runtime/unit.h b/flang/runtime/unit.h index e3c8757645bb9e50d3b366278782568d8899eba8..5f854abd42f64520ddc0dad730f0c79a3ca96f60 100644 --- a/flang/runtime/unit.h +++ b/flang/runtime/unit.h @@ -21,20 +21,77 @@ #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> namespace Fortran::runtime::io { class UnitMap; class ChildIo; +class ExternalFileUnit; + +// Predefined file units. +extern ExternalFileUnit *defaultInput; // unit 5 +extern ExternalFileUnit *defaultOutput; // unit 6 +extern ExternalFileUnit *errorOutput; // unit 0 extension + +#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; + + const char *path() const { return nullptr; } + std::size_t pathLength() const { return 0; } + void set_path(OwningPtr<char> &&, std::size_t bytes) {} + bool mayRead() const { return false; } + bool mayWrite() const { return true; } + bool mayPosition() const { return false; } + bool mayAsynchronous() const { return false; } + void set_mayAsynchronous(bool yes); + // Pretend to be a terminal to force the output + // at the end of IO statement. + bool isTerminal() const { return true; } + bool isWindowsTextFile() const { return false; } + Fortran::common::optional<FileOffset> knownSize() const; + bool IsConnected() const { return false; } + void Open(OpenStatus, Fortran::common::optional<Action>, Position, + IoErrorHandler &); + void Predefine(int fd) {} + void Close(CloseStatus, IoErrorHandler &); + std::size_t Read(FileOffset, char *, std::size_t minBytes, + std::size_t maxBytes, IoErrorHandler &); + std::size_t Write(FileOffset, const char *, std::size_t, IoErrorHandler &); + void Truncate(FileOffset, IoErrorHandler &); + int ReadAsynchronously(FileOffset, char *, std::size_t, IoErrorHandler &); + int WriteAsynchronously( + FileOffset, const char *, std::size_t, IoErrorHandler &); + void Wait(int id, IoErrorHandler &); + void WaitAll(IoErrorHandler &); + 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}; @@ -55,7 +112,7 @@ public: static ExternalFileUnit *LookUpOrCreate( int unit, const Terminator &, bool &wasExtant); static ExternalFileUnit *LookUpOrCreateAnonymous(int unit, Direction, - std::optional<bool> isUnformatted, const Terminator &); + Fortran::common::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); @@ -64,11 +121,11 @@ public: static 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 &); + bool OpenUnit(Fortran::common::optional<OpenStatus>, + Fortran::common::optional<Action>, Position, OwningPtr<char> &&path, + std::size_t pathLength, Convert, IoErrorHandler &); + void OpenAnonymousUnit(Fortran::common::optional<OpenStatus>, + Fortran::common::optional<Action>, Position, Convert, IoErrorHandler &); void CloseUnit(CloseStatus, IoErrorHandler &); void DestroyClosed(); @@ -169,7 +226,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. @@ -211,7 +268,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..e9ccc2c04b6b07afefa133d2bea36a7ec7997f04 100644 --- a/flang/runtime/utf.cpp +++ b/flang/runtime/utf.cpp @@ -40,7 +40,7 @@ const std::uint8_t UTF8FirstByteTable[256]{ // clang-format on // 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 +50,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 +58,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) { diff --git a/flang/runtime/utf.h b/flang/runtime/utf.h index 6d9943bb6b8a2f50af832c9a8df9c1e334feaf81..2b4e4f9a188758f00fa619e20801a1b6dbc15140 100644 --- a/flang/runtime/utf.h +++ b/flang/runtime/utf.h @@ -41,9 +41,9 @@ #ifndef FORTRAN_RUNTIME_UTF_H_ #define FORTRAN_RUNTIME_UTF_H_ +#include "flang/Common/optional.h" #include <cstddef> #include <cstdint> -#include <optional> namespace Fortran::runtime { @@ -58,7 +58,7 @@ 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 *); +Fortran::common::optional<char32_t> DecodeUTF8(const char *); // Ensure that at least maxUTF8Bytes remain in the output // buffer before calling. 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..f41c832ee5ec6af466ce0f8d67bef517644d25c8 --- /dev/null +++ b/flang/test/Lower/HLFIR/procedure-pointer-component-structure-constructor.f90 @@ -0,0 +1,48 @@ +! Test passing +! 1. NULL(), +! 2. procedure, +! 3. procedure pointer, (pending) +! 4. reference to a function that returns a procedure pointer (pending) +! 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 + v2 = DT(fun) + END + +! CDHECK-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/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/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/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/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/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/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/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/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/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..17ce56e228a6acb53a070176c7644fadf52b9b09 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 @@ -201,6 +245,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 +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/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..39756e1ee29f549230c7b9f90c53d461363437bd 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 @@ -212,6 +256,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/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..78da7f0b334b1fe377b15bf081979f025102c6b5 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 @@ -333,6 +366,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 +442,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 +490,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 +509,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 +583,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 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..6e63e270280e7a98020de3263b07a54a89164764 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 @@ -204,6 +234,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 +309,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..5aae4e246cfb3c2b9429783f0d58189902710737 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 @@ -341,6 +374,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 +450,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 +498,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 +517,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 +606,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 diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt index e0324061a9c78c05e947007523858ea751f20173..29080df5492274bf2b4180de22205850ab35af84 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 @@ -374,12 +385,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 +467,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,6 +505,12 @@ 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) @@ -470,8 +523,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 +544,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() diff --git a/libc/config/windows/entrypoints.txt b/libc/config/windows/entrypoints.txt index d6227a427afe2b86860e3f4f9bbfea177f390edc..f4456f561ec017519e547dfd77304f14bb84fe11 100644 --- a/libc/config/windows/entrypoints.txt +++ b/libc/config/windows/entrypoints.txt @@ -153,6 +153,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/c23.rst b/libc/docs/c23.rst index 24cef8539393df897d111ffe06b993df6bc11f05..3f64722bc8e64409e4c15ca4623b6d02baceb6e9 100644 --- a/libc/docs/c23.rst +++ b/libc/docs/c23.rst @@ -75,7 +75,7 @@ Additions: * dfmal * fsqrt* * dsqrtl -* stdbit.h (New header) +* stdbit.h (New header) |check| * stdckdint.h (New header) |check| * stddef.h diff --git a/libc/docs/dev/printf_behavior.rst b/libc/docs/dev/printf_behavior.rst index 00d6c83f4b0d3665cffe2ca1b113139106955edb..9548bfda57aa7de1271901de2746e31cbd8fb94f 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 ==================================== 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/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..fa604faaec2ff0697d2f6d9914d3c2a832b42df5 100644 --- a/libc/docs/math/index.rst +++ b/libc/docs/math/index.rst @@ -181,6 +181,22 @@ Basic Operations +--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ | 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| | | | @@ -259,6 +275,8 @@ Basic Operations +--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ | 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| | | | @@ -271,12 +289,30 @@ Basic Operations +--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ | 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| | | | @@ -319,6 +355,22 @@ Basic Operations +--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ | truncf128 | |check| | |check| | | |check| | | | | | | | | | +--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| ufromfp | |check| | | | | | | | | | | | | ++--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| ufromfpf | |check| | | | | | | | | | | | | ++--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| ufromfpl | |check| | | | | | | | | | | | | ++--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| ufromfpf128 | |check| | | | | | | | | | | | | ++--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| ufromfpx | |check| | | | | | | | | | | | | ++--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| ufromfpxf | |check| | | | | | | | | | | | | ++--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| ufromfpxl | |check| | | | | | | | | | | | | ++--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| ufromfpxf128 | |check| | | | | | | | | | | | | ++--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ Higher Math Functions diff --git a/libc/docs/stdbit.rst b/libc/docs/stdbit.rst index 9b4974cf1479b1682e3301c1a5ba30756ca1a304..d42f7938246293c2656ba3adcc7e814e28ea4efc 100644 --- a/libc/docs/stdbit.rst +++ b/libc/docs/stdbit.rst @@ -110,10 +110,10 @@ Macros ========================= ========= Macro Name Available ========================= ========= -__STDC_VERSION_STDBIT_H__ -__STDC_ENDIAN_LITTLE__ -__STDC_ENDIAN_BIG__ -__STDC_ENDIAN_NATIVE__ +__STDC_VERSION_STDBIT_H__ |check| +__STDC_ENDIAN_LITTLE__ |check| +__STDC_ENDIAN_BIG__ |check| +__STDC_ENDIAN_NATIVE__ |check| stdc_leading_zeros |check| stdc_leading_ones |check| stdc_trailing_zeros |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 e67fe4d11b4493cf13ce18bcf822cb6a8390d213..03c7a823e6e96b9df96b1df03af29402647f7db1 100644 --- a/libc/include/llvm-libc-macros/math-macros.h +++ b/libc/include/llvm-libc-macros/math-macros.h @@ -11,6 +11,18 @@ #include "limits-macros.h" +#define FP_NAN 0 +#define FP_INFINITE 1 +#define FP_ZERO 2 +#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 @@ -24,10 +36,6 @@ #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 __FAST_MATH__ #define math_errhandling 0 #elif defined(__NO_MATH_ERRNO__) @@ -38,4 +46,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/stdbit-macros.h b/libc/include/llvm-libc-macros/stdbit-macros.h index 10c0fac3c8dd8648eb959d2a49bdbb20f297fd43..c5b2f097783440d5c711986721240a2a28205e7d 100644 --- a/libc/include/llvm-libc-macros/stdbit-macros.h +++ b/libc/include/llvm-libc-macros/stdbit-macros.h @@ -9,6 +9,11 @@ #ifndef __LLVM_LIBC_MACROS_STDBIT_MACROS_H #define __LLVM_LIBC_MACROS_STDBIT_MACROS_H +#define __STDC_VERSION_STDBIT_H__ 202311L +#define __STDC_ENDIAN_LITTLE__ __ORDER_LITTLE_ENDIAN__ +#define __STDC_ENDIAN_BIG__ __ORDER_BIG_ENDIAN__ +#define __STDC_ENDIAN_NATIVE__ __BYTE_ORDER__ + // TODO(https://github.com/llvm/llvm-project/issues/80509): support _BitInt(). #ifdef __cplusplus inline unsigned stdc_leading_zeros(unsigned char x) { 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..8444a449ebe5be721c06cd66fe7013c1b223092d 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>] + >, ] >; @@ -881,6 +892,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 +1198,11 @@ def POSIX : StandardSpec<"POSIX"> { RetValSpec<IntType>, [ArgSpec<VoidType>] >, + FunctionSpec< + "fileno", + RetValSpec<IntType>, + [ArgSpec<FILEPtr>] + >, ] >; @@ -1493,6 +1534,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 1f14fe758130e8a99ee97e697d4d871f4da98aed..89b43f06778d95af2204b85991dae5193d55d030 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>]>, @@ -558,6 +635,7 @@ 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">, ] >; @@ -694,6 +772,11 @@ def StdC : StandardSpec<"stdc"> { RetValSpec<IntType>, [ArgSpec<ConstCharPtr>] >, + FunctionSpec< + "rename", + RetValSpec<IntType>, + [ArgSpec<ConstCharPtr>, ArgSpec<ConstCharPtr>] + >, FunctionSpec< "setbuf", RetValSpec<VoidType>, @@ -805,6 +888,10 @@ def StdC : StandardSpec<"stdc"> { HeaderSpec StdBit = HeaderSpec< "stdbit.h", [ + Macro<"__STDC_VERSION_STDBIT_H__">, + Macro<"__STDC_ENDIAN_LITTLE__">, + Macro<"__STDC_ENDIAN_BIG__">, + Macro<"__STDC_ENDIAN_NATIVE__">, Macro<"stdc_leading_zeros">, Macro<"stdc_leading_ones">, Macro<"stdc_trailing_zeros">, @@ -816,9 +903,9 @@ def StdC : StandardSpec<"stdc"> { Macro<"stdc_count_zeros">, Macro<"stdc_count_ones">, Macro<"stdc_has_single_bit">, - Macro<"std_bit_width">, - Macro<"std_bit_floor">, - Macro<"std_bit_ceil"> + Macro<"stdc_bit_width">, + Macro<"stdc_bit_floor">, + Macro<"stdc_bit_ceil"> ], // Macros [], // Types [], // Enumerations @@ -940,6 +1027,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>]>, @@ -1198,6 +1289,7 @@ def StdC : StandardSpec<"stdc"> { [ // Types ClockT, StructTmType, + StructTimeSpec, TimeTType, ], [], // Enumerations @@ -1278,12 +1370,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, @@ -1318,6 +1421,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 2e5a026bf423cd622c8c01e8268637068bd7d58a..7b1820d9bf3538575346ea6926fb401f6447b875 100644 --- a/libc/src/__support/CMakeLists.txt +++ b/libc/src/__support/CMakeLists.txt @@ -34,12 +34,21 @@ add_header_library( HDRS math_extras.h DEPENDS + libc.src.__support.CPP.bit libc.src.__support.CPP.limits libc.src.__support.CPP.type_traits libc.src.__support.macros.attributes 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..f76285be52194595cc29ca955b4687aa9d072df3 100644 --- a/libc/src/__support/CPP/CMakeLists.txt +++ b/libc/src/__support/CPP/CMakeLists.txt @@ -103,23 +103,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 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/bit.h b/libc/src/__support/CPP/bit.h index 1a05728b850653eea61971f1e0fdef0dcd9ac890..3f2fbec944054cdb8ae2e144ed7c6d784c4e2083 100644 --- a/libc/src/__support/CPP/bit.h +++ b/libc/src/__support/CPP/bit.h @@ -239,36 +239,6 @@ LIBC_INLINE constexpr To bit_or_static_cast(const From &from) { } } -// TODO: remove from 'bit.h' as it is not a standard function. -template <typename T> -[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_unsigned_v<T>, int> -first_leading_zero(T value) { - return value == cpp::numeric_limits<T>::max() ? 0 : countl_one(value) + 1; -} - -// TODO: remove from 'bit.h' as it is not a standard function. -template <typename T> -[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_unsigned_v<T>, int> -first_leading_one(T value) { - return first_leading_zero(static_cast<T>(~value)); -} - -// TODO: remove from 'bit.h' as it is not a standard function. -template <typename T> -[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_unsigned_v<T>, int> -first_trailing_zero(T value) { - return value == cpp::numeric_limits<T>::max() - ? 0 - : countr_zero(static_cast<T>(~value)) + 1; -} - -// TODO: remove from 'bit.h' as it is not a standard function. -template <typename T> -[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_unsigned_v<T>, int> -first_trailing_one(T value) { - return value == cpp::numeric_limits<T>::max() ? 0 : countr_zero(value) + 1; -} - /// Count number of 1's aka population count or Hamming weight. /// /// Only unsigned integral types are allowed. @@ -294,13 +264,6 @@ ADD_SPECIALIZATION(unsigned long long, __builtin_popcountll) // TODO: 128b specializations? #undef ADD_SPECIALIZATION -// TODO: remove from 'bit.h' as it is not a standard function. -template <typename T> -[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_unsigned_v<T>, int> -count_zeros(T value) { - return popcount<T>(static_cast<T>(~value)); -} - } // namespace LIBC_NAMESPACE::cpp #endif // LLVM_LIBC_SRC___SUPPORT_CPP_BIT_H 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/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/FPUtil/BasicOperations.h b/libc/src/__support/FPUtil/BasicOperations.h index a19d6d0bef08ff092cef38134727eb2c4f0f7bd9..b8cff982d3a6eaae83fe30fa4b991ce6d2d415f1 100644 --- a/libc/src/__support/FPUtil/BasicOperations.h +++ b/libc/src/__support/FPUtil/BasicOperations.h @@ -11,6 +11,7 @@ #include "FPBits.h" +#include "FEnvImpl.h" #include "src/__support/CPP/type_traits.h" #include "src/__support/common.h" @@ -58,6 +59,110 @@ LIBC_INLINE T fmax(T x, T 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); + 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> LIBC_INLINE T fdim(T x, T y) { FPBits<T> bitx(x), bity(y); diff --git a/libc/src/__support/FPUtil/CMakeLists.txt b/libc/src/__support/FPUtil/CMakeLists.txt index f1c6fba22856dd332896683777b24e610560f9e9..4ded70a675ea88350b2e016d4c73a20d741b8445 100644 --- a/libc/src/__support/FPUtil/CMakeLists.txt +++ b/libc/src/__support/FPUtil/CMakeLists.txt @@ -35,6 +35,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 ) diff --git a/libc/src/__support/FPUtil/FEnvImpl.h b/libc/src/__support/FPUtil/FEnvImpl.h index 6810659733de2c31b97e3061788ad1b634b76801..a6a533dcfdf4aabd57f973a7317b3857eefecd0d 100644 --- a/libc/src/__support/FPUtil/FEnvImpl.h +++ b/libc/src/__support/FPUtil/FEnvImpl.h @@ -9,13 +9,12 @@ #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..579584076b125891b67487bcf3289208fdfa3c5e 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,67 @@ 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) { + if (width == 0U) + 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; + if (rounded_value < -T(1U << (width - 1U))) + return FPBits<T>::quiet_nan().get_val(); + if (rounded_value > T((1U << (width - 1U)) - 1U)) + return FPBits<T>::quiet_nan().get_val(); + return rounded_value; + } + + if (rounded_value < T(0.0)) + 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 && rounded_value > T(1U << width) - 1U) + 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/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/amdgpu/utils.h b/libc/src/__support/GPU/amdgpu/utils.h index 75f0b5744ebd723cd8a0103c1a9c15900b387d41..9b520a6bcf38d40e14ee8e08fab39d1ed2624c7f 100644 --- a/libc/src/__support/GPU/amdgpu/utils.h +++ b/libc/src/__support/GPU/amdgpu/utils.h @@ -145,6 +145,12 @@ LIBC_INLINE uint32_t get_lane_size() { __builtin_amdgcn_wave_barrier(); } +/// Shuffles the the lanes inside the wavefront according to the given index. +[[clang::convergent]] LIBC_INLINE uint32_t shuffle(uint64_t, uint32_t idx, + uint32_t x) { + return __builtin_amdgcn_ds_bpermute(idx << 2, x); +} + /// Returns the current value of the GPU's processor clock. /// NOTE: The RDNA3 and RDNA2 architectures use a 20-bit cycle counter. LIBC_INLINE uint64_t processor_clock() { return __builtin_readcyclecounter(); } diff --git a/libc/src/__support/GPU/generic/utils.h b/libc/src/__support/GPU/generic/utils.h index c6c3c01cf7d5f0b88c2673eb774a46f4506c8619..b6df59f7aa9efcb37ff17d565da9faa540ceec12 100644 --- a/libc/src/__support/GPU/generic/utils.h +++ b/libc/src/__support/GPU/generic/utils.h @@ -67,6 +67,8 @@ LIBC_INLINE void sync_threads() {} LIBC_INLINE void sync_lane(uint64_t) {} +LIBC_INLINE uint32_t shuffle(uint64_t, uint32_t, uint32_t x) { return x; } + LIBC_INLINE uint64_t processor_clock() { return 0; } LIBC_INLINE uint64_t fixed_frequency_clock() { return 0; } diff --git a/libc/src/__support/GPU/nvptx/utils.h b/libc/src/__support/GPU/nvptx/utils.h index a92c8847b6ecdf4e5405941b0a408a5f00c8ba5c..3f19afb8364861a6724e4a92f5b710893dcc0489 100644 --- a/libc/src/__support/GPU/nvptx/utils.h +++ b/libc/src/__support/GPU/nvptx/utils.h @@ -97,7 +97,7 @@ LIBC_INLINE uint32_t get_lane_size() { return 32; } /// Returns the id of the thread inside of a CUDA warp executing together. [[clang::convergent]] LIBC_INLINE uint32_t get_lane_id() { - return get_thread_id() & (get_lane_size() - 1); + return __nvvm_read_ptx_sreg_laneid(); } /// Returns the bit-mask of active threads in the current warp. @@ -126,6 +126,14 @@ LIBC_INLINE uint32_t get_lane_size() { return 32; } __nvvm_bar_warp_sync(static_cast<uint32_t>(mask)); } +/// Shuffles the the lanes inside the warp according to the given index. +[[clang::convergent]] LIBC_INLINE uint32_t shuffle(uint64_t lane_mask, + uint32_t idx, uint32_t x) { + uint32_t mask = static_cast<uint32_t>(lane_mask); + uint32_t bitmask = (mask >> idx) & 1; + return -bitmask & __nvvm_shfl_sync_idx_i32(mask, x, idx, get_lane_size() - 1); +} + /// Returns the current value of the GPU's processor clock. LIBC_INLINE uint64_t processor_clock() { return __builtin_readcyclecounter(); } diff --git a/libc/src/__support/GPU/utils.h b/libc/src/__support/GPU/utils.h index 0f9167cdee0663b66895ff6d012adc56fca9dcf5..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. @@ -31,6 +31,25 @@ LIBC_INLINE bool is_first_lane(uint64_t lane_mask) { return gpu::get_lane_id() == get_first_lane_id(lane_mask); } +/// Gets the sum of all lanes inside the warp or wavefront. +LIBC_INLINE uint32_t reduce(uint64_t lane_mask, uint32_t x) { + for (uint32_t step = gpu::get_lane_size() / 2; step > 0; step /= 2) { + uint32_t index = step + gpu::get_lane_id(); + x += gpu::shuffle(lane_mask, index, x); + } + return gpu::broadcast_value(lane_mask, x); +} + +/// Gets the accumulator scan of the threads in the warp or wavefront. +LIBC_INLINE uint32_t scan(uint64_t lane_mask, uint32_t x) { + for (uint32_t step = 1; step < gpu::get_lane_size(); step *= 2) { + uint32_t index = gpu::get_lane_id() - step; + uint32_t bitmask = gpu::get_lane_id() >= step; + x += -bitmask & gpu::shuffle(lane_mask, index, x); + } + return x; +} + } // namespace gpu } // namespace LIBC_NAMESPACE diff --git a/libc/src/__support/UInt.h b/libc/src/__support/UInt.h index d92d61ed094ebe1a8eeca3a78b87df8211236d96..df01e081e3c19e61bccd169a48a5e34e4a05197b 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. 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/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/math_extras.h b/libc/src/__support/math_extras.h index c6b458ddecdabf42440eae72f7d15a24038e49cc..28ee1be8b99997b2b5dab712aa158669e8225569 100644 --- a/libc/src/__support/math_extras.h +++ b/libc/src/__support/math_extras.h @@ -10,7 +10,8 @@ #ifndef LLVM_LIBC_SRC___SUPPORT_MATH_EXTRAS_H #define LLVM_LIBC_SRC___SUPPORT_MATH_EXTRAS_H -#include "src/__support/CPP/limits.h" // CHAR_BIT +#include "src/__support/CPP/bit.h" // countl_one, countr_zero +#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 @@ -226,6 +227,40 @@ sub_with_borrow<unsigned long long>(unsigned long long a, unsigned long long b, #endif // LIBC_HAS_BUILTIN(__builtin_subc) +template <typename T> +[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_unsigned_v<T>, int> +first_leading_zero(T value) { + return value == cpp::numeric_limits<T>::max() ? 0 + : cpp::countl_one(value) + 1; +} + +template <typename T> +[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_unsigned_v<T>, int> +first_leading_one(T value) { + return first_leading_zero(static_cast<T>(~value)); +} + +template <typename T> +[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_unsigned_v<T>, int> +first_trailing_zero(T value) { + return value == cpp::numeric_limits<T>::max() + ? 0 + : cpp::countr_zero(static_cast<T>(~value)) + 1; +} + +template <typename T> +[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_unsigned_v<T>, int> +first_trailing_one(T value) { + return value == cpp::numeric_limits<T>::max() ? 0 + : cpp::countr_zero(value) + 1; +} + +template <typename T> +[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_unsigned_v<T>, int> +count_zeros(T value) { + return cpp::popcount<T>(static_cast<T>(~value)); +} + } // namespace LIBC_NAMESPACE #endif // LLVM_LIBC_SRC___SUPPORT_MATH_EXTRAS_H 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..61baa498321cb1b786c06d0c8096e898934f2cb1 100644 --- a/libc/src/math/CMakeLists.txt +++ b/libc/src/math/CMakeLists.txt @@ -117,6 +117,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 +167,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 +240,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 +249,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 +317,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/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/math/fmaximum_mag_num.h b/libc/src/math/fmaximum_mag_num.h new file mode 100644 index 0000000000000000000000000000000000000000..c4ff243846e037fbdc8ab5ba2efcfd3bdde751c2 --- /dev/null +++ b/libc/src/math/fmaximum_mag_num.h @@ -0,0 +1,18 @@ +//===-- 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. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIBC_SRC_MATH_FMAXIMUM_MAG_NUM_H +#define LLVM_LIBC_SRC_MATH_FMAXIMUM_MAG_NUM_H + +namespace LIBC_NAMESPACE { + +double fmaximum_mag_num(double x, double y); + +} // namespace LIBC_NAMESPACE + +#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..60d329f9adc6e3f70784e1e209bd64d6dcbaece1 100644 --- a/libc/src/math/generic/CMakeLists.txt +++ b/libc/src/math/generic/CMakeLists.txt @@ -1545,358 +1545,1073 @@ add_entrypoint_object( -O3 ) +add_entrypoint_object( + fmaximum + SRCS + fmaximum.cpp + HDRS + ../fmaximum.h + DEPENDS + libc.src.__support.FPUtil.basic_operations + COMPILE_OPTIONS + -O2 +) + +add_entrypoint_object( + fmaximumf + SRCS + fmaximumf.cpp + HDRS + ../fmaximumf.h + DEPENDS + libc.src.__support.FPUtil.basic_operations + COMPILE_OPTIONS + -O2 +) + +add_entrypoint_object( + fmaximuml + SRCS + fmaximuml.cpp + HDRS + ../fmaximuml.h + DEPENDS + libc.src.__support.FPUtil.basic_operations + COMPILE_OPTIONS + -O2 +) + +add_entrypoint_object( + fmaximumf128 + SRCS + fmaximumf128.cpp + HDRS + ../fmaximumf128.h + DEPENDS + libc.src.__support.macros.properties.types + libc.src.__support.FPUtil.basic_operations + COMPILE_OPTIONS + -O3 +) + +add_entrypoint_object( + fmaximum_num + SRCS + fmaximum_num.cpp + HDRS + ../fmaximum_num.h + DEPENDS + libc.src.__support.FPUtil.basic_operations + COMPILE_OPTIONS + -O2 +) + +add_entrypoint_object( + fmaximum_numf + SRCS + fmaximum_numf.cpp + HDRS + ../fmaximum_numf.h + DEPENDS + libc.src.__support.FPUtil.basic_operations + COMPILE_OPTIONS + -O2 +) + +add_entrypoint_object( + fmaximum_numl + SRCS + fmaximum_numl.cpp + HDRS + ../fmaximum_numl.h + DEPENDS + libc.src.__support.FPUtil.basic_operations + COMPILE_OPTIONS + -O2 +) + +add_entrypoint_object( + fmaximum_numf128 + SRCS + fmaximum_numf128.cpp + HDRS + ../fmaximum_numf128.h + DEPENDS + libc.src.__support.macros.properties.types + libc.src.__support.FPUtil.basic_operations + COMPILE_OPTIONS + -O3 +) + +add_entrypoint_object( + fmaximum_mag + SRCS + fmaximum_mag.cpp + HDRS + ../fmaximum_mag.h + DEPENDS + libc.src.__support.FPUtil.basic_operations + COMPILE_OPTIONS + -O2 +) + +add_entrypoint_object( + fmaximum_magf + SRCS + fmaximum_magf.cpp + HDRS + ../fmaximum_magf.h + DEPENDS + libc.src.__support.FPUtil.basic_operations + COMPILE_OPTIONS + -O2 +) + +add_entrypoint_object( + fmaximum_magl + SRCS + fmaximum_magl.cpp + HDRS + ../fmaximum_magl.h + DEPENDS + libc.src.__support.FPUtil.basic_operations + COMPILE_OPTIONS + -O2 +) + +add_entrypoint_object( + fmaximum_magf128 + SRCS + fmaximum_magf128.cpp + HDRS + ../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( + fmaximum_mag_numf + SRCS + fmaximum_mag_numf.cpp + HDRS + ../fmaximum_mag_numf.h + DEPENDS + libc.src.__support.FPUtil.basic_operations + COMPILE_OPTIONS + -O2 +) + +add_entrypoint_object( + fmaximum_mag_numl + SRCS + fmaximum_mag_numl.cpp + HDRS + ../fmaximum_mag_numl.h + DEPENDS + libc.src.__support.FPUtil.basic_operations + COMPILE_OPTIONS + -O2 +) + +add_entrypoint_object( + fmaximum_mag_numf128 + SRCS + fmaximum_mag_numf128.cpp + HDRS + ../fmaximum_mag_numf128.h + DEPENDS + libc.src.__support.macros.properties.types + libc.src.__support.FPUtil.basic_operations + COMPILE_OPTIONS + -O3 +) + +add_entrypoint_object( + fminimum + SRCS + fminimum.cpp + HDRS + ../fminimum.h + DEPENDS + libc.src.__support.FPUtil.basic_operations + COMPILE_OPTIONS + -O2 +) + +add_entrypoint_object( + fminimumf + SRCS + fminimumf.cpp + HDRS + ../fminimumf.h + DEPENDS + libc.src.__support.FPUtil.basic_operations + COMPILE_OPTIONS + -O2 +) + +add_entrypoint_object( + fminimuml + SRCS + fminimuml.cpp + HDRS + ../fminimuml.h + DEPENDS + libc.src.__support.FPUtil.basic_operations + COMPILE_OPTIONS + -O2 +) + +add_entrypoint_object( + fminimumf128 + SRCS + fminimumf128.cpp + HDRS + ../fminimumf128.h + DEPENDS + libc.src.__support.macros.properties.types + libc.src.__support.FPUtil.basic_operations + COMPILE_OPTIONS + -O3 +) + +add_entrypoint_object( + fminimum_num + SRCS + fminimum_num.cpp + HDRS + ../fminimum_num.h + DEPENDS + libc.src.__support.FPUtil.basic_operations + COMPILE_OPTIONS + -O2 +) + +add_entrypoint_object( + fminimum_numf + SRCS + fminimum_numf.cpp + HDRS + ../fminimum_numf.h + DEPENDS + libc.src.__support.FPUtil.basic_operations + COMPILE_OPTIONS + -O2 +) + +add_entrypoint_object( + fminimum_numl + SRCS + fminimum_numl.cpp + HDRS + ../fminimum_numl.h + DEPENDS + libc.src.__support.FPUtil.basic_operations + COMPILE_OPTIONS + -O2 +) + +add_entrypoint_object( + fminimum_numf128 + SRCS + fminimum_numf128.cpp + HDRS + ../fminimum_numf128.h + DEPENDS + libc.src.__support.macros.properties.types + libc.src.__support.FPUtil.basic_operations + COMPILE_OPTIONS + -O3 +) + +add_entrypoint_object( + fminimum_mag + SRCS + fminimum_mag.cpp + HDRS + ../fminimum_mag.h + DEPENDS + libc.src.__support.FPUtil.basic_operations + COMPILE_OPTIONS + -O2 +) + +add_entrypoint_object( + fminimum_magf + SRCS + fminimum_magf.cpp + HDRS + ../fminimum_magf.h + DEPENDS + libc.src.__support.FPUtil.basic_operations + COMPILE_OPTIONS + -O2 +) + +add_entrypoint_object( + fminimum_magl + SRCS + fminimum_magl.cpp + HDRS + ../fminimum_magl.h + DEPENDS + libc.src.__support.FPUtil.basic_operations + COMPILE_OPTIONS + -O2 +) + +add_entrypoint_object( + fminimum_magf128 + SRCS + fminimum_magf128.cpp + HDRS + ../fminimum_magf128.h + DEPENDS + libc.src.__support.macros.properties.types + libc.src.__support.FPUtil.basic_operations + COMPILE_OPTIONS + -O3 +) + + +add_entrypoint_object( + fminimum_mag_num + SRCS + fminimum_mag_num.cpp + HDRS + ../fminimum_mag_num.h + DEPENDS + libc.src.__support.FPUtil.basic_operations + COMPILE_OPTIONS + -O2 +) + +add_entrypoint_object( + fminimum_mag_numf + SRCS + fminimum_mag_numf.cpp + HDRS + ../fminimum_mag_numf.h + DEPENDS + libc.src.__support.FPUtil.basic_operations + COMPILE_OPTIONS + -O2 +) + +add_entrypoint_object( + fminimum_mag_numl + SRCS + fminimum_mag_numl.cpp + HDRS + ../fminimum_mag_numl.h + DEPENDS + libc.src.__support.FPUtil.basic_operations + COMPILE_OPTIONS + -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 + 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 - ../sqrt.h + ../nextafterl.h DEPENDS - libc.src.__support.FPUtil.sqrt + libc.src.__support.FPUtil.manipulation_functions COMPILE_OPTIONS -O3 ) add_entrypoint_object( - sqrtf + nextafterf128 SRCS - sqrtf.cpp + nextafterf128.cpp HDRS - ../sqrtf.h + ../nextafterf128.h DEPENDS - libc.src.__support.FPUtil.sqrt + libc.src.__support.macros.properties.types + libc.src.__support.FPUtil.manipulation_functions COMPILE_OPTIONS -O3 ) add_entrypoint_object( - sqrtl + nexttoward SRCS - sqrtl.cpp + nexttoward.cpp HDRS - ../sqrtl.h + ../nexttoward.h DEPENDS - libc.src.__support.FPUtil.sqrt + libc.src.__support.FPUtil.manipulation_functions COMPILE_OPTIONS -O3 ) add_entrypoint_object( - sqrtf128 + nexttowardf SRCS - sqrtf128.cpp + nexttowardf.cpp HDRS - ../sqrtf128.h + ../nexttowardf.h DEPENDS - libc.src.__support.macros.properties.types - libc.src.__support.FPUtil.sqrt + libc.src.__support.FPUtil.manipulation_functions COMPILE_OPTIONS -O3 - ) +) add_entrypoint_object( - remquof + nexttowardl SRCS - remquof.cpp + nexttowardl.cpp HDRS - ../remquof.h + ../nexttowardl.h DEPENDS - libc.src.__support.FPUtil.division_and_remainder_operations + libc.src.__support.FPUtil.manipulation_functions COMPILE_OPTIONS - -O2 + -O3 ) add_entrypoint_object( - remquo + nextdown SRCS - remquo.cpp + nextdown.cpp HDRS - ../remquo.h + ../nextdown.h DEPENDS - libc.src.__support.FPUtil.division_and_remainder_operations + libc.src.__support.FPUtil.manipulation_functions COMPILE_OPTIONS - -O2 + -O3 ) add_entrypoint_object( - remquol + nextdownl SRCS - remquol.cpp + nextdownl.cpp HDRS - ../remquol.h + ../nextdownl.h DEPENDS - libc.src.__support.FPUtil.division_and_remainder_operations + libc.src.__support.FPUtil.manipulation_functions COMPILE_OPTIONS - -O2 + -O3 ) add_entrypoint_object( - remainderf + nextdownf SRCS - remainderf.cpp + nextdownf.cpp HDRS - ../remainderf.h + ../nextdownf.h DEPENDS - libc.src.__support.FPUtil.division_and_remainder_operations + libc.src.__support.FPUtil.manipulation_functions COMPILE_OPTIONS - -O2 + -O3 ) add_entrypoint_object( - remainder + nextdownf128 SRCS - remainder.cpp + nextdownf128.cpp HDRS - ../remainder.h + ../nextdownf128.h DEPENDS - libc.src.__support.FPUtil.division_and_remainder_operations + libc.src.__support.macros.properties.types + libc.src.__support.FPUtil.manipulation_functions COMPILE_OPTIONS - -O2 + -O3 ) add_entrypoint_object( - remainderl + nextup SRCS - remainderl.cpp + nextup.cpp HDRS - ../remainderl.h + ../nextup.h DEPENDS - libc.src.__support.FPUtil.division_and_remainder_operations + libc.src.__support.FPUtil.manipulation_functions COMPILE_OPTIONS - -O2 + -O3 ) add_entrypoint_object( - hypotf + nextupl SRCS - hypotf.cpp + nextupl.cpp HDRS - ../hypotf.h + ../nextupl.h DEPENDS - libc.src.__support.FPUtil.basic_operations - libc.src.__support.FPUtil.fp_bits - libc.src.__support.FPUtil.sqrt + libc.src.__support.FPUtil.manipulation_functions COMPILE_OPTIONS -O3 ) add_entrypoint_object( - fdim + nextupf SRCS - fdim.cpp + nextupf.cpp HDRS - ../fdim.h + ../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.FPUtil.basic_operations + libc.src.__support.macros.properties.types + libc.src.__support.FPUtil.manipulation_functions + COMPILE_OPTIONS + -O3 ) add_entrypoint_object( - fdimf + fmod SRCS - fdimf.cpp + fmod.cpp HDRS - ../fdimf.h + ../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.basic_operations + libc.src.__support.FPUtil.generic.fmod + COMPILE_OPTIONS + -O3 ) add_entrypoint_object( - fdiml + fmodl SRCS - fdiml.cpp + fmodl.cpp HDRS - ../fdiml.h + ../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.FPUtil.basic_operations + libc.src.__support.macros.properties.types + libc.src.__support.FPUtil.generic.fmod + COMPILE_OPTIONS + -O3 ) add_entrypoint_object( - fdimf128 + fromfp SRCS - fdimf128.cpp + fromfp.cpp HDRS - ../fdimf128.h + ../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.macros.properties.types - libc.src.__support.FPUtil.basic_operations + libc.src.__support.FPUtil.nearest_integer + COMPILE_OPTIONS + -O3 ) add_entrypoint_object( - hypot + fromfpl SRCS - hypot.cpp + fromfpl.cpp HDRS - ../hypot.h + ../fromfpl.h DEPENDS - libc.src.__support.FPUtil.hypot + libc.src.__support.FPUtil.nearest_integer COMPILE_OPTIONS -O3 ) add_entrypoint_object( - nan + fromfpf128 SRCS - nan.cpp + fromfpf128.cpp HDRS - ../nan.h + ../fromfpf128.h DEPENDS - libc.src.__support.str_to_float - libc.src.errno.errno + libc.src.__support.macros.properties.types + libc.src.__support.FPUtil.nearest_integer COMPILE_OPTIONS -O3 ) add_entrypoint_object( - nanf + fromfpx SRCS - nanf.cpp + fromfpx.cpp HDRS - ../nanf.h + ../fromfpx.h DEPENDS - libc.src.__support.str_to_float - libc.src.errno.errno + libc.src.__support.FPUtil.nearest_integer COMPILE_OPTIONS -O3 ) add_entrypoint_object( - nanl + fromfpxf SRCS - nanl.cpp + fromfpxf.cpp HDRS - ../nanl.h + ../fromfpxf.h DEPENDS - libc.src.__support.str_to_float - libc.src.errno.errno + libc.src.__support.FPUtil.nearest_integer COMPILE_OPTIONS -O3 ) add_entrypoint_object( - nextafter + fromfpxl SRCS - nextafter.cpp + fromfpxl.cpp HDRS - ../nextafter.h + ../fromfpxl.h DEPENDS - libc.src.__support.FPUtil.manipulation_functions + libc.src.__support.FPUtil.nearest_integer COMPILE_OPTIONS - -O2 + -O3 ) add_entrypoint_object( - nextafterf + fromfpxf128 SRCS - nextafterf.cpp + fromfpxf128.cpp HDRS - ../nextafterf.h + ../fromfpxf128.h DEPENDS - libc.src.__support.FPUtil.manipulation_functions + libc.src.__support.macros.properties.types + libc.src.__support.FPUtil.nearest_integer COMPILE_OPTIONS - -O2 + -O3 ) add_entrypoint_object( - nextafterl + ufromfp SRCS - nextafterl.cpp + ufromfp.cpp HDRS - ../nextafterl.h + ../ufromfp.h DEPENDS - libc.src.__support.FPUtil.manipulation_functions + libc.src.__support.FPUtil.nearest_integer COMPILE_OPTIONS - -O2 + -O3 ) add_entrypoint_object( - nexttoward + ufromfpf SRCS - nexttoward.cpp + ufromfpf.cpp HDRS - ../nexttoward.h + ../ufromfpf.h DEPENDS - libc.src.__support.FPUtil.manipulation_functions + libc.src.__support.FPUtil.nearest_integer COMPILE_OPTIONS -O3 ) add_entrypoint_object( - nexttowardf + ufromfpl SRCS - nexttowardf.cpp + ufromfpl.cpp HDRS - ../nexttowardf.h + ../ufromfpl.h DEPENDS - libc.src.__support.FPUtil.manipulation_functions + libc.src.__support.FPUtil.nearest_integer COMPILE_OPTIONS -O3 ) add_entrypoint_object( - nexttowardl + ufromfpf128 SRCS - nexttowardl.cpp + ufromfpf128.cpp HDRS - ../nexttowardl.h + ../ufromfpf128.h DEPENDS - libc.src.__support.FPUtil.manipulation_functions + libc.src.__support.macros.properties.types + libc.src.__support.FPUtil.nearest_integer COMPILE_OPTIONS -O3 ) add_entrypoint_object( - fmod + ufromfpx SRCS - fmod.cpp + ufromfpx.cpp HDRS - ../fmod.h + ../ufromfpx.h DEPENDS - libc.src.__support.FPUtil.generic.fmod + libc.src.__support.FPUtil.nearest_integer COMPILE_OPTIONS -O3 ) add_entrypoint_object( - fmodf + ufromfpxf SRCS - fmodf.cpp + ufromfpxf.cpp HDRS - ../fmodf.h + ../ufromfpxf.h DEPENDS - libc.src.__support.FPUtil.generic.fmod + libc.src.__support.FPUtil.nearest_integer COMPILE_OPTIONS -O3 ) add_entrypoint_object( - fmodl + ufromfpxl SRCS - fmodl.cpp + ufromfpxl.cpp HDRS - ../fmodl.h + ../ufromfpxl.h DEPENDS - libc.src.__support.FPUtil.generic.fmod + libc.src.__support.FPUtil.nearest_integer COMPILE_OPTIONS -O3 ) add_entrypoint_object( - fmodf128 + ufromfpxf128 SRCS - fmodf128.cpp + ufromfpxf128.cpp HDRS - ../fmodf128.h + ../ufromfpxf128.h DEPENDS libc.src.__support.macros.properties.types - libc.src.__support.FPUtil.generic.fmod + libc.src.__support.FPUtil.nearest_integer COMPILE_OPTIONS -O3 ) @@ -2031,16 +2746,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,8 +2795,11 @@ 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 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/atanf.cpp b/libc/src/math/generic/atanf.cpp index e0f8a1bfc2ecc9d0bba73d167b0a26f211c71731..4adda429cc041c1cadff3644aae57569b610e612 100644 --- a/libc/src/math/generic/atanf.cpp +++ b/libc/src/math/generic/atanf.cpp @@ -7,60 +7,116 @@ //===----------------------------------------------------------------------===// #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). + double x2 = x_d * x_d; + double x4 = x2 * x2; + double c0 = fputil::multiply_add(x2, ATAN_COEFFS[0][1], ATAN_COEFFS[0][0]); + double c1 = fputil::multiply_add(x2, ATAN_COEFFS[0][3], ATAN_COEFFS[0][2]); + double c2 = fputil::multiply_add(x2, ATAN_COEFFS[0][5], ATAN_COEFFS[0][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) { + // Exceptional value: + if (LIBC_UNLIKELY(x_abs == 0x3ffe'2ec1U)) { // |x| = 0x1.fc5d82p+0 + return sign.is_pos() ? fputil::round_result_slightly_up(0x1.1ab2fp0f) + : fputil::round_result_slightly_down(-0x1.1ab2fp0f); } + // |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 == 0x3dbb'6ac7U)) { // |x| = 0x1.76d58ep-4 + return sign.is_pos() + ? fputil::round_result_slightly_up(0x1.75cb06p-4f) + : fputil::round_result_slightly_down(-0x1.75cb06p-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/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..93d5bcbf7b567df67e25c731da77b7d528a13023 100644 --- a/libc/src/math/generic/inv_trigf_utils.cpp +++ b/libc/src/math/generic/inv_trigf_utils.cpp @@ -10,19 +10,71 @@ 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), 7, [|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), "},"); +// }; +// For i = 0, ATAN_COEFFS[0][j] = (-1)^j * (1/(2*j + 1)) is the odd coefficients +// of the Taylor polynomial of atan(x). +double ATAN_COEFFS[17][8] = { + {0x1.0000000000000p+0, -0x1.5555555555555p-2, 0x1.999999999999ap-3, + -0x1.2492492492492p-3, 0x1.c71c71c71c71cp-4, -0x1.745d1745d1746p-4, + 0x1.3b13b13b13b14p-4, -0x1.1111111111111p-4}, + {0x1.ff55bb72cfdb1p-5, 0x1.fe01fe01fe1bp-1, -0x1.fc05f80821d1ap-5, + -0x1.4d6930419fc5fp-2, 0x1.f61b9f6d69313p-5, 0x1.8208a32f4346cp-3, + -0x1.ecb8fc53d04efp-5, -0x1.060710cb59cbcp-3}, + {0x1.fd5ba9aac2f3cp-4, 0x1.f81f81f81f96ap-1, -0x1.f05e09cf4c1b2p-4, + -0x1.368c3aac7543ep-2, 0x1.d9b14bddfac55p-4, 0x1.4048e55ec725ep-3, + -0x1.b98ca3c1594b5p-4, -0x1.664eabaabbc16p-4}, + {0x1.7b97b4bce5ae7p-3, 0x1.ee9c7f8458f06p-1, -0x1.665c226c8dc69p-3, + -0x1.1344bb77961b7p-2, 0x1.42ac97745d3ccp-3, 0x1.c32e142047ec1p-4, + -0x1.137ae41ab96cbp-3, -0x1.1a6ae8c09a4b6p-5}, + {0x1.f5b75f92c80c6p-3, 0x1.e1e1e1e1e1ed4p-1, -0x1.c5894d101ad4p-3, + -0x1.ce6de02b38c38p-3, 0x1.78a3920c336b9p-3, 0x1.dd5ff94a9d499p-5, + -0x1.1ac2d3f9d072ep-3, 0x1.0af9735dff373p-6}, + {0x1.362773707ebc5p-2, 0x1.d272ca3fc5b8bp-1, -0x1.0997e8ae90cb6p-2, + -0x1.6cf6667146798p-3, 0x1.8dd1dff17f3d3p-3, 0x1.24860eced656fp-7, + -0x1.f4220e8f18ed5p-4, 0x1.b700aed7cdc34p-5}, + {0x1.6f61941e4deeep-2, 0x1.c0e070381c115p-1, -0x1.2726dd1347c7ep-2, + -0x1.09f37b3ad010dp-3, 0x1.85eaca5196f5cp-3, -0x1.04d640117852ap-5, + -0x1.802c2956871c7p-4, 0x1.2992b45df0ee7p-4}, + {0x1.a64eec3cc23fep-2, 0x1.adbe87f94906bp-1, -0x1.3b9d8eab5eae5p-2, + -0x1.57c09646faabbp-4, 0x1.6795330e73aep-3, -0x1.f2d89a702a652p-5, + -0x1.f3afd90a9d4d7p-5, 0x1.3261723d3f153p-4}, + {0x1.dac670561bb53p-2, 0x1.999999999998fp-1, -0x1.47ae147afd8cap-2, + -0x1.5d867c3dfd72ap-5, 0x1.3a92a76cba833p-3, -0x1.3ec460286928ap-4, + -0x1.ed02ff86892acp-6, 0x1.0a674c8f05727p-4}, + {0x1.0657e94db30d2p-1, 0x1.84f00c27805ffp-1, -0x1.4c62cb564f677p-2, + -0x1.e6495b262dfe7p-8, 0x1.063c34eca262bp-3, -0x1.58b78dc79b5aep-4, + -0x1.4623815233be1p-8, 0x1.93afe94328089p-5}, + {0x1.1e00babdefeb6p-1, 0x1.702e05c0b8159p-1, -0x1.4af2b78236bd6p-2, + 0x1.5d0b7ea46ed08p-6, 0x1.a124870236935p-4, -0x1.519e1ec133a88p-4, + 0x1.a54632a3f48c7p-7, 0x1.099ca0945096dp-5}, + {0x1.345f01cce37bdp-1, 0x1.5babcc647fa7ep-1, -0x1.449db09443a67p-2, + 0x1.655caac78a0fcp-5, 0x1.3bbbdb0d09efap-4, -0x1.34a306c27e021p-4, + 0x1.83fe749c7966p-6, 0x1.2057cc96d9edcp-6}, + {0x1.4978fa3269ee2p-1, 0x1.47ae147ae146bp-1, -0x1.3a92a305652e1p-2, + 0x1.ec21b5172657fp-5, 0x1.c2f8c45d2f4eep-5, -0x1.0ba99c4aeb8acp-4, + 0x1.d716a4af4d1d6p-6, 0x1.97fba0a9696dep-8}, + {0x1.5d58987169b19p-1, 0x1.34679ace0133cp-1, -0x1.2ddfb03920e2fp-2, + 0x1.2491307c0fa0bp-4, 0x1.29c7eca0136fp-5, -0x1.bca792caa6f1cp-5, + 0x1.e5d92545576bcp-6, -0x1.8ca76fcf5ccd2p-10}, + {0x1.700a7c5784634p-1, 0x1.21fb78121fb71p-1, -0x1.1f6a8499ea541p-2, + 0x1.41b15e5e77bcfp-4, 0x1.59bc9bf54fb02p-6, -0x1.63b54ff058e0fp-5, + 0x1.c8da01221306fp-6, -0x1.906b2c274c39cp-8}, + {0x1.819d0b7158a4dp-1, 0x1.107fbbe01107cp-1, -0x1.0feeb40897d4ep-2, + 0x1.50e5afb95f5d6p-4, 0x1.2a7c2f0c7495dp-7, -0x1.12bd2bb5062cdp-5, + 0x1.93e8ceb89afebp-6, -0x1.10da9b8c6b731p-7}, + {0x1.921fb54442d18p-1, 0x1.fffffffffffebp-2, -0x1.fffffffffcbbcp-3, + 0x1.555555564e2fep-4, -0x1.20b17d5dd89dcp-30, -0x1.9999c5ad71711p-6, + 0x1.5558b76e7aaf9p-6, -0x1.236e803c6c1f6p-7}, +}; } // 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..c621f27e10146005355d37c31ddc4142fb066106 100644 --- a/libc/src/math/generic/inv_trigf_utils.h +++ b/libc/src/math/generic/inv_trigf_utils.h @@ -9,85 +9,32 @@ #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][8]; - 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 1 <= 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 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, ATAN_COEFFS[i][7], 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/stdbit/CMakeLists.txt b/libc/src/stdbit/CMakeLists.txt index 2aef2029f2df0bf2bd634ebcebd5197252a366c0..0c22b1d2617abb03dbcdb0dac79650424c5a33bb 100644 --- a/libc/src/stdbit/CMakeLists.txt +++ b/libc/src/stdbit/CMakeLists.txt @@ -1,30 +1,38 @@ +function(declare_dependencies prefixes dependencies) + set(suffixes c s i l ll) + foreach(prefix ${prefixes}) + foreach(suffix IN LISTS suffixes) + add_entrypoint_object( + stdc_${prefix}_u${suffix} + SRCS + stdc_${prefix}_u${suffix}.cpp + HDRS + stdc_${prefix}_u${suffix}.h + DEPENDS + ${dependencies} + ) + endforeach() + endforeach() +endfunction() + + set(prefixes leading_zeros leading_ones trailing_zeros trailing_ones - first_leading_zero - first_leading_one - first_trailing_zero - first_trailing_one - count_zeros count_ones has_single_bit bit_width bit_floor bit_ceil ) -set(suffixes c s i l ll) -foreach(prefix IN LISTS prefixes) - foreach(suffix IN LISTS suffixes) - add_entrypoint_object( - stdc_${prefix}_u${suffix} - SRCS - stdc_${prefix}_u${suffix}.cpp - HDRS - stdc_${prefix}_u${suffix}.h - DEPENDS - libc.src.__support.CPP.bit - ) - endforeach() -endforeach() +declare_dependencies("${prefixes}" libc.src.__support.CPP.bit) +set(prefixes + first_leading_zero + first_leading_one + first_trailing_zero + first_trailing_one + count_zeros +) +declare_dependencies("${prefixes}" libc.src.__support.math_extras) diff --git a/libc/src/stdbit/stdc_count_zeros_uc.cpp b/libc/src/stdbit/stdc_count_zeros_uc.cpp index 22c57bd60c3846001bd516abf385a712fbf91b93..309ebb55e0fac1de8ffe4ddef7edc8988ac4f8e6 100644 --- a/libc/src/stdbit/stdc_count_zeros_uc.cpp +++ b/libc/src/stdbit/stdc_count_zeros_uc.cpp @@ -8,13 +8,13 @@ #include "src/stdbit/stdc_count_zeros_uc.h" -#include "src/__support/CPP/bit.h" #include "src/__support/common.h" +#include "src/__support/math_extras.h" namespace LIBC_NAMESPACE { LLVM_LIBC_FUNCTION(unsigned, stdc_count_zeros_uc, (unsigned char value)) { - return static_cast<unsigned>(cpp::count_zeros(value)); + return static_cast<unsigned>(count_zeros(value)); } } // namespace LIBC_NAMESPACE diff --git a/libc/src/stdbit/stdc_count_zeros_ui.cpp b/libc/src/stdbit/stdc_count_zeros_ui.cpp index 6a1defd9d555b2051a68d882f09f93597e4983d2..31ea907b24de87a54e850b56b2b55509790371bd 100644 --- a/libc/src/stdbit/stdc_count_zeros_ui.cpp +++ b/libc/src/stdbit/stdc_count_zeros_ui.cpp @@ -8,13 +8,13 @@ #include "src/stdbit/stdc_count_zeros_ui.h" -#include "src/__support/CPP/bit.h" #include "src/__support/common.h" +#include "src/__support/math_extras.h" namespace LIBC_NAMESPACE { LLVM_LIBC_FUNCTION(unsigned, stdc_count_zeros_ui, (unsigned value)) { - return static_cast<unsigned>(cpp::count_zeros(value)); + return static_cast<unsigned>(count_zeros(value)); } } // namespace LIBC_NAMESPACE diff --git a/libc/src/stdbit/stdc_count_zeros_ul.cpp b/libc/src/stdbit/stdc_count_zeros_ul.cpp index ceab32ef9ac36dedeb0020dd86dac63574ad30e0..f5df5c49f131220c4f6e5c1c4b107b6d5d2c6ba8 100644 --- a/libc/src/stdbit/stdc_count_zeros_ul.cpp +++ b/libc/src/stdbit/stdc_count_zeros_ul.cpp @@ -8,13 +8,13 @@ #include "src/stdbit/stdc_count_zeros_ul.h" -#include "src/__support/CPP/bit.h" #include "src/__support/common.h" +#include "src/__support/math_extras.h" namespace LIBC_NAMESPACE { LLVM_LIBC_FUNCTION(unsigned, stdc_count_zeros_ul, (unsigned long value)) { - return static_cast<unsigned>(cpp::count_zeros(value)); + return static_cast<unsigned>(count_zeros(value)); } } // namespace LIBC_NAMESPACE diff --git a/libc/src/stdbit/stdc_count_zeros_ull.cpp b/libc/src/stdbit/stdc_count_zeros_ull.cpp index 2f57f727a6919c6e0ca5f55e5c727ac8fdb4951d..6a9c8f04a799fe4d1d426c46ce13d096541a792a 100644 --- a/libc/src/stdbit/stdc_count_zeros_ull.cpp +++ b/libc/src/stdbit/stdc_count_zeros_ull.cpp @@ -8,13 +8,13 @@ #include "src/stdbit/stdc_count_zeros_ull.h" -#include "src/__support/CPP/bit.h" #include "src/__support/common.h" +#include "src/__support/math_extras.h" namespace LIBC_NAMESPACE { LLVM_LIBC_FUNCTION(unsigned, stdc_count_zeros_ull, (unsigned long long value)) { - return static_cast<unsigned>(cpp::count_zeros(value)); + return static_cast<unsigned>(count_zeros(value)); } } // namespace LIBC_NAMESPACE diff --git a/libc/src/stdbit/stdc_count_zeros_us.cpp b/libc/src/stdbit/stdc_count_zeros_us.cpp index fc06836ee292a98e381de6279c56df2617ef67e7..c08186ec6e87cd4e7ca4bb4b9fd3e9f9c2e94d0f 100644 --- a/libc/src/stdbit/stdc_count_zeros_us.cpp +++ b/libc/src/stdbit/stdc_count_zeros_us.cpp @@ -8,13 +8,13 @@ #include "src/stdbit/stdc_count_zeros_us.h" -#include "src/__support/CPP/bit.h" #include "src/__support/common.h" +#include "src/__support/math_extras.h" namespace LIBC_NAMESPACE { LLVM_LIBC_FUNCTION(unsigned, stdc_count_zeros_us, (unsigned short value)) { - return static_cast<unsigned>(cpp::count_zeros(value)); + return static_cast<unsigned>(count_zeros(value)); } } // namespace LIBC_NAMESPACE diff --git a/libc/src/stdbit/stdc_first_leading_one_uc.cpp b/libc/src/stdbit/stdc_first_leading_one_uc.cpp index 02871595fdb6b89fc6b65e333ee1787989571612..2e28ed3bb6f82db0bab1e7f8e04d3124774c1dfe 100644 --- a/libc/src/stdbit/stdc_first_leading_one_uc.cpp +++ b/libc/src/stdbit/stdc_first_leading_one_uc.cpp @@ -8,13 +8,13 @@ #include "src/stdbit/stdc_first_leading_one_uc.h" -#include "src/__support/CPP/bit.h" #include "src/__support/common.h" +#include "src/__support/math_extras.h" namespace LIBC_NAMESPACE { LLVM_LIBC_FUNCTION(unsigned, stdc_first_leading_one_uc, (unsigned char value)) { - return static_cast<unsigned>(cpp::first_leading_one(value)); + return static_cast<unsigned>(first_leading_one(value)); } } // namespace LIBC_NAMESPACE diff --git a/libc/src/stdbit/stdc_first_leading_one_ui.cpp b/libc/src/stdbit/stdc_first_leading_one_ui.cpp index a6c7ef5a833914ce60ddf424c1690c504e8d237a..a07a39b09d9f44f856c59aabd008e88174934a7b 100644 --- a/libc/src/stdbit/stdc_first_leading_one_ui.cpp +++ b/libc/src/stdbit/stdc_first_leading_one_ui.cpp @@ -8,13 +8,13 @@ #include "src/stdbit/stdc_first_leading_one_ui.h" -#include "src/__support/CPP/bit.h" #include "src/__support/common.h" +#include "src/__support/math_extras.h" namespace LIBC_NAMESPACE { LLVM_LIBC_FUNCTION(unsigned, stdc_first_leading_one_ui, (unsigned value)) { - return static_cast<unsigned>(cpp::first_leading_one(value)); + return static_cast<unsigned>(first_leading_one(value)); } } // namespace LIBC_NAMESPACE diff --git a/libc/src/stdbit/stdc_first_leading_one_ul.cpp b/libc/src/stdbit/stdc_first_leading_one_ul.cpp index d1bcab5dda02a99d2975a2c1d1c1fe557e8b3806..4350fb7826b49cc63495890564d375d2b793b053 100644 --- a/libc/src/stdbit/stdc_first_leading_one_ul.cpp +++ b/libc/src/stdbit/stdc_first_leading_one_ul.cpp @@ -8,13 +8,13 @@ #include "src/stdbit/stdc_first_leading_one_ul.h" -#include "src/__support/CPP/bit.h" #include "src/__support/common.h" +#include "src/__support/math_extras.h" namespace LIBC_NAMESPACE { LLVM_LIBC_FUNCTION(unsigned, stdc_first_leading_one_ul, (unsigned long value)) { - return static_cast<unsigned>(cpp::first_leading_one(value)); + return static_cast<unsigned>(first_leading_one(value)); } } // namespace LIBC_NAMESPACE diff --git a/libc/src/stdbit/stdc_first_leading_one_ull.cpp b/libc/src/stdbit/stdc_first_leading_one_ull.cpp index 7be8f1051ec23132a867b1e989f1d7a0049ee5ca..57a5ae368e11ae99ce2c3b4c61ada51cb7a658a3 100644 --- a/libc/src/stdbit/stdc_first_leading_one_ull.cpp +++ b/libc/src/stdbit/stdc_first_leading_one_ull.cpp @@ -8,14 +8,14 @@ #include "src/stdbit/stdc_first_leading_one_ull.h" -#include "src/__support/CPP/bit.h" #include "src/__support/common.h" +#include "src/__support/math_extras.h" namespace LIBC_NAMESPACE { LLVM_LIBC_FUNCTION(unsigned, stdc_first_leading_one_ull, (unsigned long long value)) { - return static_cast<unsigned>(cpp::first_leading_one(value)); + return static_cast<unsigned>(first_leading_one(value)); } } // namespace LIBC_NAMESPACE diff --git a/libc/src/stdbit/stdc_first_leading_one_us.cpp b/libc/src/stdbit/stdc_first_leading_one_us.cpp index 7a4c7e673f367f0c0ba713dd6381729e03a8b35e..f14433b13f350032a1cef28f1bc0a5bc264d2e82 100644 --- a/libc/src/stdbit/stdc_first_leading_one_us.cpp +++ b/libc/src/stdbit/stdc_first_leading_one_us.cpp @@ -8,14 +8,14 @@ #include "src/stdbit/stdc_first_leading_one_us.h" -#include "src/__support/CPP/bit.h" #include "src/__support/common.h" +#include "src/__support/math_extras.h" namespace LIBC_NAMESPACE { LLVM_LIBC_FUNCTION(unsigned, stdc_first_leading_one_us, (unsigned short value)) { - return static_cast<unsigned>(cpp::first_leading_one(value)); + return static_cast<unsigned>(first_leading_one(value)); } } // namespace LIBC_NAMESPACE diff --git a/libc/src/stdbit/stdc_first_leading_zero_uc.cpp b/libc/src/stdbit/stdc_first_leading_zero_uc.cpp index ffc1d9247406a28bf2505936fa8b1023432d066c..6e2164256f17224009de54d5f80c51c3e384bcbc 100644 --- a/libc/src/stdbit/stdc_first_leading_zero_uc.cpp +++ b/libc/src/stdbit/stdc_first_leading_zero_uc.cpp @@ -8,14 +8,14 @@ #include "src/stdbit/stdc_first_leading_zero_uc.h" -#include "src/__support/CPP/bit.h" #include "src/__support/common.h" +#include "src/__support/math_extras.h" namespace LIBC_NAMESPACE { LLVM_LIBC_FUNCTION(unsigned, stdc_first_leading_zero_uc, (unsigned char value)) { - return static_cast<unsigned>(cpp::first_leading_zero(value)); + return static_cast<unsigned>(first_leading_zero(value)); } } // namespace LIBC_NAMESPACE diff --git a/libc/src/stdbit/stdc_first_leading_zero_ui.cpp b/libc/src/stdbit/stdc_first_leading_zero_ui.cpp index 1eeab2963e6aa7d1ea03b7ad51c811ee05e9af62..cb733a94c0d84dcc577f6be2926cad7dc217a4ad 100644 --- a/libc/src/stdbit/stdc_first_leading_zero_ui.cpp +++ b/libc/src/stdbit/stdc_first_leading_zero_ui.cpp @@ -8,13 +8,13 @@ #include "src/stdbit/stdc_first_leading_zero_ui.h" -#include "src/__support/CPP/bit.h" #include "src/__support/common.h" +#include "src/__support/math_extras.h" namespace LIBC_NAMESPACE { LLVM_LIBC_FUNCTION(unsigned, stdc_first_leading_zero_ui, (unsigned value)) { - return static_cast<unsigned>(cpp::first_leading_zero(value)); + return static_cast<unsigned>(first_leading_zero(value)); } } // namespace LIBC_NAMESPACE diff --git a/libc/src/stdbit/stdc_first_leading_zero_ul.cpp b/libc/src/stdbit/stdc_first_leading_zero_ul.cpp index 6743d3eda5168c7bad0ebb086bd779af695149d2..8a3930a271ed987f29ac3e1465c189ac7a0d6e2c 100644 --- a/libc/src/stdbit/stdc_first_leading_zero_ul.cpp +++ b/libc/src/stdbit/stdc_first_leading_zero_ul.cpp @@ -8,14 +8,14 @@ #include "src/stdbit/stdc_first_leading_zero_ul.h" -#include "src/__support/CPP/bit.h" #include "src/__support/common.h" +#include "src/__support/math_extras.h" namespace LIBC_NAMESPACE { LLVM_LIBC_FUNCTION(unsigned, stdc_first_leading_zero_ul, (unsigned long value)) { - return static_cast<unsigned>(cpp::first_leading_zero(value)); + return static_cast<unsigned>(first_leading_zero(value)); } } // namespace LIBC_NAMESPACE diff --git a/libc/src/stdbit/stdc_first_leading_zero_ull.cpp b/libc/src/stdbit/stdc_first_leading_zero_ull.cpp index 8128dd3d59a7bfa26f2114d2ddb1e7706d2fac92..5a69197a82996a84a641d423f5fbd76f9d2b4ca9 100644 --- a/libc/src/stdbit/stdc_first_leading_zero_ull.cpp +++ b/libc/src/stdbit/stdc_first_leading_zero_ull.cpp @@ -8,14 +8,14 @@ #include "src/stdbit/stdc_first_leading_zero_ull.h" -#include "src/__support/CPP/bit.h" #include "src/__support/common.h" +#include "src/__support/math_extras.h" namespace LIBC_NAMESPACE { LLVM_LIBC_FUNCTION(unsigned, stdc_first_leading_zero_ull, (unsigned long long value)) { - return static_cast<unsigned>(cpp::first_leading_zero(value)); + return static_cast<unsigned>(first_leading_zero(value)); } } // namespace LIBC_NAMESPACE diff --git a/libc/src/stdbit/stdc_first_leading_zero_us.cpp b/libc/src/stdbit/stdc_first_leading_zero_us.cpp index d931535e7690a6c787ecc96e4d516d4a4075a224..6482c8654db3b58cc7e45340d291fd8bef0e07b2 100644 --- a/libc/src/stdbit/stdc_first_leading_zero_us.cpp +++ b/libc/src/stdbit/stdc_first_leading_zero_us.cpp @@ -8,14 +8,14 @@ #include "src/stdbit/stdc_first_leading_zero_us.h" -#include "src/__support/CPP/bit.h" #include "src/__support/common.h" +#include "src/__support/math_extras.h" namespace LIBC_NAMESPACE { LLVM_LIBC_FUNCTION(unsigned, stdc_first_leading_zero_us, (unsigned short value)) { - return static_cast<unsigned>(cpp::first_leading_zero(value)); + return static_cast<unsigned>(first_leading_zero(value)); } } // namespace LIBC_NAMESPACE diff --git a/libc/src/stdbit/stdc_first_trailing_one_uc.cpp b/libc/src/stdbit/stdc_first_trailing_one_uc.cpp index 6ed35966be61a0304f2b0ef1845b27cdf48374f2..d3e8825eef00fc726d1b6198eb11237b6868b1ed 100644 --- a/libc/src/stdbit/stdc_first_trailing_one_uc.cpp +++ b/libc/src/stdbit/stdc_first_trailing_one_uc.cpp @@ -8,14 +8,14 @@ #include "src/stdbit/stdc_first_trailing_one_uc.h" -#include "src/__support/CPP/bit.h" #include "src/__support/common.h" +#include "src/__support/math_extras.h" namespace LIBC_NAMESPACE { LLVM_LIBC_FUNCTION(unsigned, stdc_first_trailing_one_uc, (unsigned char value)) { - return static_cast<unsigned>(cpp::first_trailing_one(value)); + return static_cast<unsigned>(first_trailing_one(value)); } } // namespace LIBC_NAMESPACE diff --git a/libc/src/stdbit/stdc_first_trailing_one_ui.cpp b/libc/src/stdbit/stdc_first_trailing_one_ui.cpp index a89083bd49507a8caad1ef378cffa3098e7d6bb6..842bd699505010f5d94a1b5955db867f9d48c69e 100644 --- a/libc/src/stdbit/stdc_first_trailing_one_ui.cpp +++ b/libc/src/stdbit/stdc_first_trailing_one_ui.cpp @@ -8,13 +8,13 @@ #include "src/stdbit/stdc_first_trailing_one_ui.h" -#include "src/__support/CPP/bit.h" #include "src/__support/common.h" +#include "src/__support/math_extras.h" namespace LIBC_NAMESPACE { LLVM_LIBC_FUNCTION(unsigned, stdc_first_trailing_one_ui, (unsigned value)) { - return static_cast<unsigned>(cpp::first_trailing_one(value)); + return static_cast<unsigned>(first_trailing_one(value)); } } // namespace LIBC_NAMESPACE diff --git a/libc/src/stdbit/stdc_first_trailing_one_ul.cpp b/libc/src/stdbit/stdc_first_trailing_one_ul.cpp index f30078d0f5ffaa3ac8184bc7767d35c564e233fa..0497d1d77811e4c6dcda208b8fd533a376a8eeb9 100644 --- a/libc/src/stdbit/stdc_first_trailing_one_ul.cpp +++ b/libc/src/stdbit/stdc_first_trailing_one_ul.cpp @@ -8,14 +8,14 @@ #include "src/stdbit/stdc_first_trailing_one_ul.h" -#include "src/__support/CPP/bit.h" #include "src/__support/common.h" +#include "src/__support/math_extras.h" namespace LIBC_NAMESPACE { LLVM_LIBC_FUNCTION(unsigned, stdc_first_trailing_one_ul, (unsigned long value)) { - return static_cast<unsigned>(cpp::first_trailing_one(value)); + return static_cast<unsigned>(first_trailing_one(value)); } } // namespace LIBC_NAMESPACE diff --git a/libc/src/stdbit/stdc_first_trailing_one_ull.cpp b/libc/src/stdbit/stdc_first_trailing_one_ull.cpp index 2e526a890cda9cda1d32f84c61cabefa2b79ff8c..6e062dd27cdd609e6614291527cdc66594057776 100644 --- a/libc/src/stdbit/stdc_first_trailing_one_ull.cpp +++ b/libc/src/stdbit/stdc_first_trailing_one_ull.cpp @@ -8,14 +8,14 @@ #include "src/stdbit/stdc_first_trailing_one_ull.h" -#include "src/__support/CPP/bit.h" #include "src/__support/common.h" +#include "src/__support/math_extras.h" namespace LIBC_NAMESPACE { LLVM_LIBC_FUNCTION(unsigned, stdc_first_trailing_one_ull, (unsigned long long value)) { - return static_cast<unsigned>(cpp::first_trailing_one(value)); + return static_cast<unsigned>(first_trailing_one(value)); } } // namespace LIBC_NAMESPACE diff --git a/libc/src/stdbit/stdc_first_trailing_one_us.cpp b/libc/src/stdbit/stdc_first_trailing_one_us.cpp index e4c88e0d7906b9ae038068d8cb542e6fd0a36fc1..e90158f10204955ff73075e7620089892853dd10 100644 --- a/libc/src/stdbit/stdc_first_trailing_one_us.cpp +++ b/libc/src/stdbit/stdc_first_trailing_one_us.cpp @@ -8,14 +8,14 @@ #include "src/stdbit/stdc_first_trailing_one_us.h" -#include "src/__support/CPP/bit.h" #include "src/__support/common.h" +#include "src/__support/math_extras.h" namespace LIBC_NAMESPACE { LLVM_LIBC_FUNCTION(unsigned, stdc_first_trailing_one_us, (unsigned short value)) { - return static_cast<unsigned>(cpp::first_trailing_one(value)); + return static_cast<unsigned>(first_trailing_one(value)); } } // namespace LIBC_NAMESPACE diff --git a/libc/src/stdbit/stdc_first_trailing_zero_uc.cpp b/libc/src/stdbit/stdc_first_trailing_zero_uc.cpp index 5825d5d441c591763ca4ae70f43ccbab73c2cb44..a6939f6286b34e6ad5184e507c3e2e709e07abba 100644 --- a/libc/src/stdbit/stdc_first_trailing_zero_uc.cpp +++ b/libc/src/stdbit/stdc_first_trailing_zero_uc.cpp @@ -8,14 +8,14 @@ #include "src/stdbit/stdc_first_trailing_zero_uc.h" -#include "src/__support/CPP/bit.h" #include "src/__support/common.h" +#include "src/__support/math_extras.h" namespace LIBC_NAMESPACE { LLVM_LIBC_FUNCTION(unsigned, stdc_first_trailing_zero_uc, (unsigned char value)) { - return static_cast<unsigned>(cpp::first_trailing_zero(value)); + return static_cast<unsigned>(first_trailing_zero(value)); } } // namespace LIBC_NAMESPACE diff --git a/libc/src/stdbit/stdc_first_trailing_zero_ui.cpp b/libc/src/stdbit/stdc_first_trailing_zero_ui.cpp index 3b51b5fa22c324ea7e0e7a91dc5939d68efab9af..7a50b696afff7e8384b8d936e609a4dcaff52a9b 100644 --- a/libc/src/stdbit/stdc_first_trailing_zero_ui.cpp +++ b/libc/src/stdbit/stdc_first_trailing_zero_ui.cpp @@ -8,13 +8,13 @@ #include "src/stdbit/stdc_first_trailing_zero_ui.h" -#include "src/__support/CPP/bit.h" #include "src/__support/common.h" +#include "src/__support/math_extras.h" namespace LIBC_NAMESPACE { LLVM_LIBC_FUNCTION(unsigned, stdc_first_trailing_zero_ui, (unsigned value)) { - return static_cast<unsigned>(cpp::first_trailing_zero(value)); + return static_cast<unsigned>(first_trailing_zero(value)); } } // namespace LIBC_NAMESPACE diff --git a/libc/src/stdbit/stdc_first_trailing_zero_ul.cpp b/libc/src/stdbit/stdc_first_trailing_zero_ul.cpp index abf122944a76a44f81b7b63df14f45d228442a20..88acbabdf2d9f1924f2d83635726cff8a7b01203 100644 --- a/libc/src/stdbit/stdc_first_trailing_zero_ul.cpp +++ b/libc/src/stdbit/stdc_first_trailing_zero_ul.cpp @@ -8,14 +8,14 @@ #include "src/stdbit/stdc_first_trailing_zero_ul.h" -#include "src/__support/CPP/bit.h" #include "src/__support/common.h" +#include "src/__support/math_extras.h" namespace LIBC_NAMESPACE { LLVM_LIBC_FUNCTION(unsigned, stdc_first_trailing_zero_ul, (unsigned long value)) { - return static_cast<unsigned>(cpp::first_trailing_zero(value)); + return static_cast<unsigned>(first_trailing_zero(value)); } } // namespace LIBC_NAMESPACE diff --git a/libc/src/stdbit/stdc_first_trailing_zero_ull.cpp b/libc/src/stdbit/stdc_first_trailing_zero_ull.cpp index 336e7d6e075ff2cd437b2df1b62c97e74300e39b..92df8f284e8b5f69d2d95c822f02ea79f824def0 100644 --- a/libc/src/stdbit/stdc_first_trailing_zero_ull.cpp +++ b/libc/src/stdbit/stdc_first_trailing_zero_ull.cpp @@ -8,14 +8,14 @@ #include "src/stdbit/stdc_first_trailing_zero_ull.h" -#include "src/__support/CPP/bit.h" #include "src/__support/common.h" +#include "src/__support/math_extras.h" namespace LIBC_NAMESPACE { LLVM_LIBC_FUNCTION(unsigned, stdc_first_trailing_zero_ull, (unsigned long long value)) { - return static_cast<unsigned>(cpp::first_trailing_zero(value)); + return static_cast<unsigned>(first_trailing_zero(value)); } } // namespace LIBC_NAMESPACE diff --git a/libc/src/stdbit/stdc_first_trailing_zero_us.cpp b/libc/src/stdbit/stdc_first_trailing_zero_us.cpp index b7d05047b2721a23943b335d708cc92802e3ea4c..86caa20dd3bd60c438ba4fd0f641d12878d39ba1 100644 --- a/libc/src/stdbit/stdc_first_trailing_zero_us.cpp +++ b/libc/src/stdbit/stdc_first_trailing_zero_us.cpp @@ -8,14 +8,14 @@ #include "src/stdbit/stdc_first_trailing_zero_us.h" -#include "src/__support/CPP/bit.h" #include "src/__support/common.h" +#include "src/__support/math_extras.h" namespace LIBC_NAMESPACE { LLVM_LIBC_FUNCTION(unsigned, stdc_first_trailing_zero_us, (unsigned short value)) { - return static_cast<unsigned>(cpp::first_trailing_zero(value)); + return static_cast<unsigned>(first_trailing_zero(value)); } } // namespace LIBC_NAMESPACE diff --git a/libc/src/stdio/CMakeLists.txt b/libc/src/stdio/CMakeLists.txt index bb8e41606c5dfbe5c019f7850120d6f543501851..11e15c91735188d6c32d73a598e4b522a79eee3c 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) 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/generic/CMakeLists.txt b/libc/src/stdio/generic/CMakeLists.txt index 4e4a709e94061b9b70ca9aee18c774f6e9f06084..0aa213caba7b8ae5d9c3b42dc54ceac499e33bca 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 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/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/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/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/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..a2b16e73f35321b6309327669158cca39f8a9021 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 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..e754b34e46985a5a3c6503e8284d14acc093979e 100644 --- a/libc/src/stdlib/exit.cpp +++ b/libc/src/stdlib/exit.cpp @@ -10,14 +10,12 @@ #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(); + __cxa_finalize(nullptr); quick_exit(status); __builtin_unreachable(); } diff --git a/libc/src/stdlib/str_from_util.h b/libc/src/stdlib/str_from_util.h new file mode 100644 index 0000000000000000000000000000000000000000..c4c1c0a0ba4ef073a62fdb7dfc4accd3bcc135cb --- /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 NULL 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..1d02a7ad11244282ebaf6f0b7fc9226ed4024324 --- /dev/null +++ b/libc/src/stdlib/strfromd.cpp @@ -0,0 +1,42 @@ +//===-- 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" + +#include <stdarg.h> +#include <stddef.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..40eff87eb454c50a1c4308aa9cb3a96ddc170319 --- /dev/null +++ b/libc/src/stdlib/strfromf.cpp @@ -0,0 +1,42 @@ +//===-- 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" + +#include <stdarg.h> +#include <stddef.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..6b8781e7c04e114271145dd9f1aceaee0dac6285 --- /dev/null +++ b/libc/src/stdlib/strfroml.cpp @@ -0,0 +1,47 @@ +//===-- 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" + +#include <stdarg.h> +#include <stddef.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/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/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/include/stdbit_test.cpp b/libc/test/include/stdbit_test.cpp index f3227eb86959ebd8f76ecb69ae9ff1cc04ea1aa4..bee1a19f9c031a0a72777a5392288771ec5dce1f 100644 --- a/libc/test/include/stdbit_test.cpp +++ b/libc/test/include/stdbit_test.cpp @@ -141,3 +141,20 @@ TEST(LlvmLibcStdbitTest, TypeGenericMacroBitCeil) { EXPECT_EQ(stdc_bit_ceil(0UL), 0x6DUL); EXPECT_EQ(stdc_bit_ceil(0ULL), 0x6EULL); } + +TEST(LlvmLibcStdbitTest, VersionMacro) { + // 7.18.1p2 an integer constant expression with a value equivalent to 202311L. + EXPECT_EQ(__STDC_VERSION_STDBIT_H__, 202311L); +} + +TEST(LlvmLibcStdbitTest, EndianMacros) { + // 7.18.2p3 The values of the integer constant expressions for + // __STDC_ENDIAN_LITTLE__ and __STDC_ENDIAN_BIG__ are not equal. + EXPECT_NE(__STDC_ENDIAN_LITTLE__, __STDC_ENDIAN_BIG__); + // The standard does allow for __STDC_ENDIAN_NATIVE__ to be an integer + // constant expression with an implementation defined value for non-big or + // little endianness environments. I assert such machines are no longer + // relevant. + EXPECT_TRUE(__STDC_ENDIAN_NATIVE__ == __STDC_ENDIAN_LITTLE__ || + __STDC_ENDIAN_NATIVE__ == __STDC_ENDIAN_BIG__); +} diff --git a/libc/test/integration/src/__support/CMakeLists.txt b/libc/test/integration/src/__support/CMakeLists.txt index 7c853ff10259f5893930023a081b255a0649b5cb..b5b6557e8d689954153ab2c898ae5376766d1f1d 100644 --- a/libc/test/integration/src/__support/CMakeLists.txt +++ b/libc/test/integration/src/__support/CMakeLists.txt @@ -1 +1,4 @@ add_subdirectory(threads) +if(LIBC_TARGET_OS_IS_GPU) + add_subdirectory(GPU) +endif() diff --git a/libc/test/integration/src/__support/GPU/CMakeLists.txt b/libc/test/integration/src/__support/GPU/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..7811e0da45ddcf5100f800e2952b4a60d7372223 --- /dev/null +++ b/libc/test/integration/src/__support/GPU/CMakeLists.txt @@ -0,0 +1,11 @@ +add_custom_target(libc-support-gpu-tests) +add_dependencies(libc-integration-tests libc-support-gpu-tests) + +add_integration_test( + scan_reduce_test + SUITE libc-support-gpu-tests + SRCS + scan_reduce.cpp + LOADER_ARGS + --threads 64 +) diff --git a/libc/test/integration/src/__support/GPU/scan_reduce.cpp b/libc/test/integration/src/__support/GPU/scan_reduce.cpp new file mode 100644 index 0000000000000000000000000000000000000000..bc621c3300cbe0d5e0370c4946b5642bc0596444 --- /dev/null +++ b/libc/test/integration/src/__support/GPU/scan_reduce.cpp @@ -0,0 +1,62 @@ +//===-- Test for the parallel scan and reduction operations on the GPU ----===// +// +// Part of the LLVM Project, under the Apache 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/bit.h" +#include "src/__support/GPU/utils.h" +#include "test/IntegrationTest/test.h" + +using namespace LIBC_NAMESPACE; + +static uint32_t sum(uint32_t n) { return n * (n + 1) / 2; } + +// Tests a reduction within a convergant warp or wavefront using some known +// values. For example, if every element in the lane is one, then the sum should +// be the size of the warp or wavefront, i.e. 1 + 1 + 1 ... + 1. +static void test_reduce() { + uint64_t mask = gpu::get_lane_mask(); + uint32_t x = gpu::reduce(mask, 1); + EXPECT_EQ(x, gpu::get_lane_size()); + + uint32_t y = gpu::reduce(mask, gpu::get_lane_id()); + EXPECT_EQ(y, sum(gpu::get_lane_size() - 1)); + + uint32_t z = 0; + if (gpu::get_lane_id() % 2) + z = gpu::reduce(gpu::get_lane_mask(), 1); + gpu::sync_lane(mask); + + EXPECT_EQ(z, gpu::get_lane_id() % 2 ? gpu::get_lane_size() / 2 : 0); +} + +// Tests an accumulation scan within a convergent warp or wavefront using some +// known values. For example, if every element in the lane is one, then the scan +// should have each element be equivalent to its ID, i.e. 1, 1 + 1, ... +static void test_scan() { + uint64_t mask = gpu::get_lane_mask(); + + uint32_t x = gpu::scan(mask, 1); + EXPECT_EQ(x, gpu::get_lane_id() + 1); + + uint32_t y = gpu::scan(mask, gpu::get_lane_id()); + EXPECT_EQ(y, sum(gpu::get_lane_id())); + + uint32_t z = 0; + if (gpu::get_lane_id() % 2) + z = gpu::scan(gpu::get_lane_mask(), 1); + gpu::sync_lane(mask); + + EXPECT_EQ(z, gpu::get_lane_id() % 2 ? gpu::get_lane_id() / 2 + 1 : 0); +} + +TEST_MAIN(int argc, char **argv, char **envp) { + test_reduce(); + + test_scan(); + + return 0; +} diff --git a/libc/test/src/__support/CMakeLists.txt b/libc/test/src/__support/CMakeLists.txt index 91dd0dc4decfe060a59c1e6be1510cee6f17a6a8..51b897f8b595a8591c8541d74ba4935f65be7441 100644 --- a/libc/test/src/__support/CMakeLists.txt +++ b/libc/test/src/__support/CMakeLists.txt @@ -78,6 +78,7 @@ add_libc_test( SRCS integer_to_string_test.cpp DEPENDS + libc.src.__support.CPP.limits libc.src.__support.CPP.string_view libc.src.__support.integer_literals libc.src.__support.integer_to_string 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 3deb1f41dcf8826ad03756a296ec7a2741e4b3a4..cee5b90c8f4bdb4e31bf113120e22f6b8f7b8018 100644 --- a/libc/test/src/__support/CPP/bit_test.cpp +++ b/libc/test/src/__support/CPP/bit_test.cpp @@ -228,38 +228,6 @@ TEST(LlvmLibcBitTest, Rotr) { rotr<uint64_t>(0x12345678deadbeefULL, -19)); } -TYPED_TEST(LlvmLibcBitTest, FirstLeadingZero, UnsignedTypesNoBigInt) { - EXPECT_EQ(first_leading_zero<T>(cpp::numeric_limits<T>::max()), 0); - for (int i = 0U; i != cpp::numeric_limits<T>::digits; ++i) - EXPECT_EQ(first_leading_zero<T>(~(T(1) << i)), - cpp::numeric_limits<T>::digits - i); -} - -TYPED_TEST(LlvmLibcBitTest, FirstLeadingOne, UnsignedTypesNoBigInt) { - EXPECT_EQ(first_leading_one<T>(static_cast<T>(0)), 0); - for (int i = 0U; i != cpp::numeric_limits<T>::digits; ++i) - EXPECT_EQ(first_leading_one<T>(T(1) << i), - cpp::numeric_limits<T>::digits - i); -} - -TYPED_TEST(LlvmLibcBitTest, FirstTrailingZero, UnsignedTypesNoBigInt) { - EXPECT_EQ(first_trailing_zero<T>(cpp::numeric_limits<T>::max()), 0); - for (int i = 0U; i != cpp::numeric_limits<T>::digits; ++i) - EXPECT_EQ(first_trailing_zero<T>(~(T(1) << i)), i + 1); -} - -TYPED_TEST(LlvmLibcBitTest, FirstTrailingOne, UnsignedTypesNoBigInt) { - EXPECT_EQ(first_trailing_one<T>(cpp::numeric_limits<T>::max()), 0); - for (int i = 0U; i != cpp::numeric_limits<T>::digits; ++i) - EXPECT_EQ(first_trailing_one<T>(T(1) << i), i + 1); -} - -TYPED_TEST(LlvmLibcBitTest, CountZeros, UnsignedTypesNoBigInt) { - EXPECT_EQ(count_zeros(T(0)), cpp::numeric_limits<T>::digits); - for (int i = 0; i != cpp::numeric_limits<T>::digits; ++i) - EXPECT_EQ(count_zeros<T>(cpp::numeric_limits<T>::max() >> i), i); -} - TYPED_TEST(LlvmLibcBitTest, CountOnes, UnsignedTypesNoBigInt) { EXPECT_EQ(popcount(T(0)), 0); for (int i = 0; i != cpp::numeric_limits<T>::digits; ++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/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/integer_to_string_test.cpp b/libc/test/src/__support/integer_to_string_test.cpp index a2a80c81b9f69fbb11657b98e65f7fd2c89e26e0..270fddd828b6801af8771125b216ddec653368b4 100644 --- a/libc/test/src/__support/integer_to_string_test.cpp +++ b/libc/test/src/__support/integer_to_string_test.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +#include "src/__support/CPP/limits.h" #include "src/__support/CPP/span.h" #include "src/__support/CPP/string_view.h" #include "src/__support/UInt.h" @@ -15,8 +16,6 @@ #include "test/UnitTest/Test.h" -#include "limits.h" - using LIBC_NAMESPACE::IntegerToString; using LIBC_NAMESPACE::cpp::span; using LIBC_NAMESPACE::cpp::string_view; diff --git a/libc/test/src/__support/math_extras_test.cpp b/libc/test/src/__support/math_extras_test.cpp index ed064363d446bbf2201192fbabf1671980e714c3..e642248881a41c29f6aad47a5a0bd14c8c656e9b 100644 --- a/libc/test/src/__support/math_extras_test.cpp +++ b/libc/test/src/__support/math_extras_test.cpp @@ -13,6 +13,14 @@ namespace LIBC_NAMESPACE { +// TODO: add UInt<128> support. +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>; + TEST(LlvmLibcBlockMathExtrasTest, mask_trailing_ones) { EXPECT_EQ(0_u8, (mask_leading_ones<uint8_t, 0>())); EXPECT_EQ(0_u8, (mask_trailing_ones<uint8_t, 0>())); @@ -61,4 +69,36 @@ TEST(LlvmLibcBlockMathExtrasTest, mask_trailing_ones) { (mask_leading_ones<UInt128, 128>())); } +TYPED_TEST(LlvmLibcBitTest, FirstLeadingZero, UnsignedTypesNoBigInt) { + EXPECT_EQ(first_leading_zero<T>(cpp::numeric_limits<T>::max()), 0); + for (int i = 0U; i != cpp::numeric_limits<T>::digits; ++i) + EXPECT_EQ(first_leading_zero<T>(~(T(1) << i)), + cpp::numeric_limits<T>::digits - i); +} + +TYPED_TEST(LlvmLibcBitTest, FirstLeadingOne, UnsignedTypesNoBigInt) { + EXPECT_EQ(first_leading_one<T>(static_cast<T>(0)), 0); + for (int i = 0U; i != cpp::numeric_limits<T>::digits; ++i) + EXPECT_EQ(first_leading_one<T>(T(1) << i), + cpp::numeric_limits<T>::digits - i); +} + +TYPED_TEST(LlvmLibcBitTest, FirstTrailingZero, UnsignedTypesNoBigInt) { + EXPECT_EQ(first_trailing_zero<T>(cpp::numeric_limits<T>::max()), 0); + for (int i = 0U; i != cpp::numeric_limits<T>::digits; ++i) + EXPECT_EQ(first_trailing_zero<T>(~(T(1) << i)), i + 1); +} + +TYPED_TEST(LlvmLibcBitTest, FirstTrailingOne, UnsignedTypesNoBigInt) { + EXPECT_EQ(first_trailing_one<T>(cpp::numeric_limits<T>::max()), 0); + for (int i = 0U; i != cpp::numeric_limits<T>::digits; ++i) + EXPECT_EQ(first_trailing_one<T>(T(1) << i), i + 1); +} + +TYPED_TEST(LlvmLibcBitTest, CountZeros, UnsignedTypesNoBigInt) { + EXPECT_EQ(count_zeros(T(0)), cpp::numeric_limits<T>::digits); + for (int i = 0; i != cpp::numeric_limits<T>::digits; ++i) + EXPECT_EQ(count_zeros<T>(cpp::numeric_limits<T>::max() >> i), i); +} + } // namespace LIBC_NAMESPACE 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..026bcd12928bdf7d413261ac0e443abd12289b69 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 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/atanf_test.cpp b/libc/test/src/math/atanf_test.cpp index 1fa7165805c7d19d58a36f37bcc136cb79bf602e..e51932fc495525b13f6c0833c454788c6b3d05cc 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,15 @@ 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 + 0x3feefcfbU, // x = 0x1.ddf9f6p+0f + 0xbd8d6b23U, // x = -0x1.1ad646p-4f + 0xbfeefcfbU, // x = -0x1.ddf9f6p+0f + 0x7F800000U, // x = +Inf + 0xFF800000U, // x = -Inf + 0xbffe2ec1U, // x = -0x1.fc5d82p+0f + }; 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..1345dca08a6a95c86243fbf37c4bbd391bb83436 100644 --- a/libc/test/src/math/smoke/CMakeLists.txt +++ b/libc/test/src/math/smoke/CMakeLists.txt @@ -839,6 +839,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,277 +1478,726 @@ 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 - # hermetic tests. - UNIT_TEST_ONLY ) add_fp_unittest( - nan_test + fmaximum_mag_numl_test SUITE libc-math-smoke-tests SRCS - nan_test.cpp + fmaximum_mag_numl_test.cpp + HDRS + FMaximumMagNumTest.h DEPENDS - libc.include.math - libc.include.signal - libc.src.math.nan + libc.src.math.fmaximum_mag_numl 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( - nanl_test + fmaximum_mag_numf128_test SUITE libc-math-smoke-tests SRCS - nanl_test.cpp + fmaximum_mag_numf128_test.cpp + HDRS + FMaximumMagNumTest.h DEPENDS - libc.include.math - libc.include.signal - libc.src.math.nanl + libc.src.math.fmaximum_mag_numf128 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 + fminimuml_test SUITE libc-math-smoke-tests SRCS - nextafter_test.cpp + fminimuml_test.cpp HDRS - NextAfterTest.h + FMinimumTest.h DEPENDS - libc.include.math - libc.src.math.nextafter - libc.src.__support.FPUtil.basic_operations + libc.src.math.fminimuml libc.src.__support.FPUtil.fp_bits ) add_fp_unittest( - nextafterf_test + fminimumf128_test SUITE libc-math-smoke-tests SRCS - nextafterf_test.cpp + fminimumf128_test.cpp HDRS - NextAfterTest.h + FMinimumTest.h DEPENDS - libc.include.math - libc.src.math.nextafterf - libc.src.__support.FPUtil.basic_operations + libc.src.math.fminimumf128 libc.src.__support.FPUtil.fp_bits ) add_fp_unittest( - nextafterl_test + fminimum_test SUITE libc-math-smoke-tests SRCS - nextafterl_test.cpp + fminimum_test.cpp HDRS - NextAfterTest.h + FMinimumTest.h DEPENDS - libc.include.math - libc.src.math.nextafterl - libc.src.__support.FPUtil.basic_operations + libc.src.math.fminimum 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( - nexttoward_test - SUITE - libc-math-smoke-tests +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 +) + +add_fp_unittest( + nan_test + SUITE + libc-math-smoke-tests + SRCS + nan_test.cpp + DEPENDS + libc.include.math + libc.include.signal + libc.src.math.nan + 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( + nanl_test + SUITE + libc-math-smoke-tests + SRCS + nanl_test.cpp + DEPENDS + libc.include.math + libc.include.signal + libc.src.math.nanl + 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( + 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 + libc-math-smoke-tests + SRCS + nextafter_test.cpp + HDRS + NextAfterTest.h + DEPENDS + libc.include.math + libc.src.math.nextafter + libc.src.__support.FPUtil.basic_operations + libc.src.__support.FPUtil.fp_bits +) + +add_fp_unittest( + nextafterf_test + SUITE + libc-math-smoke-tests + SRCS + nextafterf_test.cpp + HDRS + NextAfterTest.h + DEPENDS + libc.include.math + libc.src.math.nextafterf + libc.src.__support.FPUtil.basic_operations + libc.src.__support.FPUtil.fp_bits +) + +add_fp_unittest( + nextafterl_test + SUITE + libc-math-smoke-tests + SRCS + nextafterl_test.cpp + HDRS + NextAfterTest.h + DEPENDS + libc.include.math + libc.src.math.nextafterl + libc.src.__support.FPUtil.basic_operations + 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( + nexttoward_test + SUITE + libc-math-smoke-tests SRCS nexttoward_test.cpp HDRS @@ -1599,6 +2240,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( 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..2d4c4c5314c9ddf8aa1e5c1fd1a7409ca3fd6db8 --- /dev/null +++ b/libc/test/src/math/smoke/FromfpTest.h @@ -0,0 +1,416 @@ +//===-- 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(aNaN, func(inf, rnd, 32U)); + EXPECT_FP_EQ(aNaN, func(neg_inf, rnd, 32U)); + + EXPECT_FP_EQ(aNaN, func(aNaN, rnd, 32U)); + } + } + + void testSpecialNumbersZeroWidth(FromfpFunc func) { + for (int rnd : MATH_ROUNDING_DIRECTIONS_INCLUDING_UNKNOWN) { + EXPECT_FP_EQ(aNaN, func(zero, rnd, 0U)); + EXPECT_FP_EQ(aNaN, func(neg_zero, rnd, 0U)); + + EXPECT_FP_EQ(aNaN, func(inf, rnd, 0U)); + EXPECT_FP_EQ(aNaN, func(neg_inf, rnd, 0U)); + + EXPECT_FP_EQ(aNaN, func(aNaN, rnd, 0U)); + } + } + + 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)); + } + } + + void testRoundedNumbersOutsideRange(FromfpFunc func) { + for (int rnd : MATH_ROUNDING_DIRECTIONS_INCLUDING_UNKNOWN) { + EXPECT_FP_EQ(aNaN, func(T(1.0), rnd, 1U)); + EXPECT_FP_EQ(aNaN, func(T(10.0), rnd, 4U)); + EXPECT_FP_EQ(aNaN, func(T(-10.0), rnd, 4U)); + EXPECT_FP_EQ(aNaN, func(T(1234.0), rnd, 11U)); + EXPECT_FP_EQ(aNaN, func(T(-1234.0), rnd, 11U)); + } + } + + 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(aNaN, func(T(0.5), FP_INT_UPWARD, 1U)); + EXPECT_FP_EQ(aNaN, func(T(0.115), FP_INT_UPWARD, 1U)); + EXPECT_FP_EQ(aNaN, func(T(0.715), FP_INT_UPWARD, 1U)); + EXPECT_FP_EQ(aNaN, func(T(1.3), FP_INT_UPWARD, 2U)); + EXPECT_FP_EQ(aNaN, func(T(1.5), FP_INT_UPWARD, 2U)); + EXPECT_FP_EQ(aNaN, func(T(1.75), FP_INT_UPWARD, 2U)); + EXPECT_FP_EQ(aNaN, func(T(10.32), FP_INT_UPWARD, 4U)); + EXPECT_FP_EQ(aNaN, func(T(-10.32), FP_INT_UPWARD, 4U)); + EXPECT_FP_EQ(aNaN, func(T(10.65), FP_INT_UPWARD, 4U)); + EXPECT_FP_EQ(aNaN, func(T(-10.65), FP_INT_UPWARD, 4U)); + EXPECT_FP_EQ(aNaN, func(T(1234.38), FP_INT_UPWARD, 11U)); + EXPECT_FP_EQ(aNaN, func(T(-1234.38), FP_INT_UPWARD, 11U)); + EXPECT_FP_EQ(aNaN, func(T(1234.96), FP_INT_UPWARD, 11U)); + EXPECT_FP_EQ(aNaN, func(T(-1234.96), FP_INT_UPWARD, 11U)); + } + + 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(aNaN, func(T(1.3), FP_INT_DOWNWARD, 1U)); + EXPECT_FP_EQ(aNaN, func(T(-1.3), FP_INT_DOWNWARD, 1U)); + EXPECT_FP_EQ(aNaN, func(T(1.5), FP_INT_DOWNWARD, 1U)); + EXPECT_FP_EQ(aNaN, func(T(-1.5), FP_INT_DOWNWARD, 1U)); + EXPECT_FP_EQ(aNaN, func(T(1.75), FP_INT_DOWNWARD, 1U)); + EXPECT_FP_EQ(aNaN, func(T(-1.75), FP_INT_DOWNWARD, 1U)); + EXPECT_FP_EQ(aNaN, func(T(10.32), FP_INT_DOWNWARD, 4U)); + EXPECT_FP_EQ(aNaN, func(T(-10.32), FP_INT_DOWNWARD, 4U)); + EXPECT_FP_EQ(aNaN, func(T(10.65), FP_INT_DOWNWARD, 4U)); + EXPECT_FP_EQ(aNaN, func(T(-10.65), FP_INT_DOWNWARD, 4U)); + EXPECT_FP_EQ(aNaN, func(T(1234.38), FP_INT_DOWNWARD, 11U)); + EXPECT_FP_EQ(aNaN, func(T(-1234.38), FP_INT_DOWNWARD, 11U)); + EXPECT_FP_EQ(aNaN, func(T(1234.96), FP_INT_DOWNWARD, 11U)); + EXPECT_FP_EQ(aNaN, func(T(-1234.96), FP_INT_DOWNWARD, 11U)); + } + + 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(aNaN, func(T(1.3), FP_INT_TOWARDZERO, 1U)); + EXPECT_FP_EQ(aNaN, func(T(1.5), FP_INT_TOWARDZERO, 1U)); + EXPECT_FP_EQ(aNaN, func(T(1.75), FP_INT_TOWARDZERO, 1U)); + EXPECT_FP_EQ(aNaN, func(T(10.32), FP_INT_TOWARDZERO, 4U)); + EXPECT_FP_EQ(aNaN, func(T(-10.32), FP_INT_TOWARDZERO, 4U)); + EXPECT_FP_EQ(aNaN, func(T(10.65), FP_INT_TOWARDZERO, 4U)); + EXPECT_FP_EQ(aNaN, func(T(-10.65), FP_INT_TOWARDZERO, 4U)); + EXPECT_FP_EQ(aNaN, func(T(1234.38), FP_INT_TOWARDZERO, 11U)); + EXPECT_FP_EQ(aNaN, func(T(-1234.38), FP_INT_TOWARDZERO, 11U)); + EXPECT_FP_EQ(aNaN, func(T(1234.96), FP_INT_TOWARDZERO, 11U)); + EXPECT_FP_EQ(aNaN, func(T(-1234.96), FP_INT_TOWARDZERO, 11U)); + } + + 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(aNaN, func(T(0.5), FP_INT_TONEARESTFROMZERO, 1U)); + EXPECT_FP_EQ(aNaN, func(T(0.715), FP_INT_TONEARESTFROMZERO, 1U)); + EXPECT_FP_EQ(aNaN, func(T(1.3), FP_INT_TONEARESTFROMZERO, 1U)); + EXPECT_FP_EQ(aNaN, func(T(1.5), FP_INT_TONEARESTFROMZERO, 2U)); + EXPECT_FP_EQ(aNaN, func(T(-1.5), FP_INT_TONEARESTFROMZERO, 1U)); + EXPECT_FP_EQ(aNaN, func(T(1.75), FP_INT_TONEARESTFROMZERO, 2U)); + EXPECT_FP_EQ(aNaN, func(T(-1.75), FP_INT_TONEARESTFROMZERO, 1U)); + EXPECT_FP_EQ(aNaN, func(T(10.32), FP_INT_TONEARESTFROMZERO, 4U)); + EXPECT_FP_EQ(aNaN, func(T(-10.32), FP_INT_TONEARESTFROMZERO, 4U)); + EXPECT_FP_EQ(aNaN, func(T(10.65), FP_INT_TONEARESTFROMZERO, 4U)); + EXPECT_FP_EQ(aNaN, func(T(-10.65), FP_INT_TONEARESTFROMZERO, 4U)); + EXPECT_FP_EQ(aNaN, func(T(1234.38), FP_INT_TONEARESTFROMZERO, 11U)); + EXPECT_FP_EQ(aNaN, func(T(-1234.38), FP_INT_TONEARESTFROMZERO, 11U)); + EXPECT_FP_EQ(aNaN, func(T(1234.96), FP_INT_TONEARESTFROMZERO, 11U)); + EXPECT_FP_EQ(aNaN, func(T(-1234.96), FP_INT_TONEARESTFROMZERO, 11U)); + } + + 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(aNaN, func(T(0.715), FP_INT_TONEAREST, 1U)); + EXPECT_FP_EQ(aNaN, func(T(1.3), FP_INT_TONEAREST, 1U)); + EXPECT_FP_EQ(aNaN, func(T(1.5), FP_INT_TONEAREST, 2U)); + EXPECT_FP_EQ(aNaN, func(T(-1.5), FP_INT_TONEAREST, 1U)); + EXPECT_FP_EQ(aNaN, func(T(1.75), FP_INT_TONEAREST, 2U)); + EXPECT_FP_EQ(aNaN, func(T(-1.75), FP_INT_TONEAREST, 1U)); + EXPECT_FP_EQ(aNaN, func(T(10.32), FP_INT_TONEAREST, 4U)); + EXPECT_FP_EQ(aNaN, func(T(-10.32), FP_INT_TONEAREST, 4U)); + EXPECT_FP_EQ(aNaN, func(T(10.65), FP_INT_TONEAREST, 4U)); + EXPECT_FP_EQ(aNaN, func(T(-10.65), FP_INT_TONEAREST, 4U)); + EXPECT_FP_EQ(aNaN, func(T(1234.38), FP_INT_TONEAREST, 11U)); + EXPECT_FP_EQ(aNaN, func(T(-1234.38), FP_INT_TONEAREST, 11U)); + EXPECT_FP_EQ(aNaN, func(T(1234.96), FP_INT_TONEAREST, 11U)); + EXPECT_FP_EQ(aNaN, func(T(-1234.96), FP_INT_TONEAREST, 11U)); + + EXPECT_FP_EQ(aNaN, func(T(2.3), FP_INT_TONEAREST, 2U)); + EXPECT_FP_EQ(aNaN, func(T(-2.3), FP_INT_TONEAREST, 1U)); + EXPECT_FP_EQ(aNaN, func(T(2.5), FP_INT_TONEAREST, 2U)); + EXPECT_FP_EQ(aNaN, func(T(-2.5), FP_INT_TONEAREST, 1U)); + EXPECT_FP_EQ(aNaN, func(T(2.75), FP_INT_TONEAREST, 2U)); + EXPECT_FP_EQ(aNaN, func(T(-2.75), FP_INT_TONEAREST, 2U)); + EXPECT_FP_EQ(aNaN, func(T(5.3), FP_INT_TONEAREST, 3U)); + EXPECT_FP_EQ(aNaN, func(T(-5.3), FP_INT_TONEAREST, 3U)); + EXPECT_FP_EQ(aNaN, func(T(5.5), FP_INT_TONEAREST, 3U)); + EXPECT_FP_EQ(aNaN, func(T(-5.5), FP_INT_TONEAREST, 3U)); + EXPECT_FP_EQ(aNaN, func(T(5.75), FP_INT_TONEAREST, 3U)); + EXPECT_FP_EQ(aNaN, func(T(-5.75), FP_INT_TONEAREST, 3U)); + } + + 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(aNaN, func(T(0.715), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U)); + EXPECT_FP_EQ(aNaN, func(T(1.3), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U)); + EXPECT_FP_EQ(aNaN, func(T(1.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 2U)); + EXPECT_FP_EQ(aNaN, func(T(-1.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U)); + EXPECT_FP_EQ(aNaN, func(T(1.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 2U)); + EXPECT_FP_EQ(aNaN, func(T(-1.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U)); + EXPECT_FP_EQ(aNaN, func(T(10.32), UNKNOWN_MATH_ROUNDING_DIRECTION, 4U)); + EXPECT_FP_EQ(aNaN, func(T(-10.32), UNKNOWN_MATH_ROUNDING_DIRECTION, 4U)); + EXPECT_FP_EQ(aNaN, func(T(10.65), UNKNOWN_MATH_ROUNDING_DIRECTION, 4U)); + EXPECT_FP_EQ(aNaN, func(T(-10.65), UNKNOWN_MATH_ROUNDING_DIRECTION, 4U)); + EXPECT_FP_EQ(aNaN, func(T(1234.38), UNKNOWN_MATH_ROUNDING_DIRECTION, 11U)); + EXPECT_FP_EQ(aNaN, func(T(-1234.38), UNKNOWN_MATH_ROUNDING_DIRECTION, 11U)); + EXPECT_FP_EQ(aNaN, func(T(1234.96), UNKNOWN_MATH_ROUNDING_DIRECTION, 11U)); + EXPECT_FP_EQ(aNaN, func(T(-1234.96), UNKNOWN_MATH_ROUNDING_DIRECTION, 11U)); + + EXPECT_FP_EQ(aNaN, func(T(2.3), UNKNOWN_MATH_ROUNDING_DIRECTION, 2U)); + EXPECT_FP_EQ(aNaN, func(T(-2.3), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U)); + EXPECT_FP_EQ(aNaN, func(T(2.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 2U)); + EXPECT_FP_EQ(aNaN, func(T(-2.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U)); + EXPECT_FP_EQ(aNaN, func(T(2.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 2U)); + EXPECT_FP_EQ(aNaN, func(T(-2.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 2U)); + EXPECT_FP_EQ(aNaN, func(T(5.3), UNKNOWN_MATH_ROUNDING_DIRECTION, 3U)); + EXPECT_FP_EQ(aNaN, func(T(-5.3), UNKNOWN_MATH_ROUNDING_DIRECTION, 3U)); + EXPECT_FP_EQ(aNaN, func(T(5.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 3U)); + EXPECT_FP_EQ(aNaN, func(T(-5.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 3U)); + EXPECT_FP_EQ(aNaN, func(T(5.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 3U)); + EXPECT_FP_EQ(aNaN, func(T(-5.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 3U)); + } +}; + +#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..b3c14c7c09ba07141077b0cd1981a001d081422d --- /dev/null +++ b/libc/test/src/math/smoke/FromfpxTest.h @@ -0,0 +1,578 @@ +//===-- 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(aNaN, func(inf, rnd, 32U)); + EXPECT_FP_EQ(aNaN, func(neg_inf, rnd, 32U)); + + EXPECT_FP_EQ(aNaN, func(aNaN, rnd, 32U)); + } + } + + void testSpecialNumbersZeroWidth(FromfpxFunc func) { + for (int rnd : MATH_ROUNDING_DIRECTIONS_INCLUDING_UNKNOWN) { + EXPECT_FP_EQ(aNaN, func(zero, rnd, 0U)); + EXPECT_FP_EQ(aNaN, func(neg_zero, rnd, 0U)); + + EXPECT_FP_EQ(aNaN, func(inf, rnd, 0U)); + EXPECT_FP_EQ(aNaN, func(neg_inf, rnd, 0U)); + + EXPECT_FP_EQ(aNaN, func(aNaN, rnd, 0U)); + } + } + + 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)); + } + } + + void testRoundedNumbersOutsideRange(FromfpxFunc func) { + for (int rnd : MATH_ROUNDING_DIRECTIONS_INCLUDING_UNKNOWN) { + EXPECT_FP_EQ(aNaN, func(T(1.0), rnd, 1U)); + EXPECT_FP_EQ(aNaN, func(T(10.0), rnd, 4U)); + EXPECT_FP_EQ(aNaN, func(T(-10.0), rnd, 4U)); + EXPECT_FP_EQ(aNaN, func(T(1234.0), rnd, 11U)); + EXPECT_FP_EQ(aNaN, func(T(-1234.0), rnd, 11U)); + } + } + + 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(aNaN, func(T(0.5), FP_INT_UPWARD, 1U)); + EXPECT_FP_EQ(aNaN, func(T(0.115), FP_INT_UPWARD, 1U)); + EXPECT_FP_EQ(aNaN, func(T(0.715), FP_INT_UPWARD, 1U)); + EXPECT_FP_EQ(aNaN, func(T(1.3), FP_INT_UPWARD, 2U)); + EXPECT_FP_EQ(aNaN, func(T(1.5), FP_INT_UPWARD, 2U)); + EXPECT_FP_EQ(aNaN, func(T(1.75), FP_INT_UPWARD, 2U)); + EXPECT_FP_EQ(aNaN, func(T(10.32), FP_INT_UPWARD, 4U)); + EXPECT_FP_EQ(aNaN, func(T(-10.32), FP_INT_UPWARD, 4U)); + EXPECT_FP_EQ(aNaN, func(T(10.65), FP_INT_UPWARD, 4U)); + EXPECT_FP_EQ(aNaN, func(T(-10.65), FP_INT_UPWARD, 4U)); + EXPECT_FP_EQ(aNaN, func(T(1234.38), FP_INT_UPWARD, 11U)); + EXPECT_FP_EQ(aNaN, func(T(-1234.38), FP_INT_UPWARD, 11U)); + EXPECT_FP_EQ(aNaN, func(T(1234.96), FP_INT_UPWARD, 11U)); + EXPECT_FP_EQ(aNaN, func(T(-1234.96), FP_INT_UPWARD, 11U)); + } + + 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(aNaN, func(T(1.3), FP_INT_DOWNWARD, 1U)); + EXPECT_FP_EQ(aNaN, func(T(-1.3), FP_INT_DOWNWARD, 1U)); + EXPECT_FP_EQ(aNaN, func(T(1.5), FP_INT_DOWNWARD, 1U)); + EXPECT_FP_EQ(aNaN, func(T(-1.5), FP_INT_DOWNWARD, 1U)); + EXPECT_FP_EQ(aNaN, func(T(1.75), FP_INT_DOWNWARD, 1U)); + EXPECT_FP_EQ(aNaN, func(T(-1.75), FP_INT_DOWNWARD, 1U)); + EXPECT_FP_EQ(aNaN, func(T(10.32), FP_INT_DOWNWARD, 4U)); + EXPECT_FP_EQ(aNaN, func(T(-10.32), FP_INT_DOWNWARD, 4U)); + EXPECT_FP_EQ(aNaN, func(T(10.65), FP_INT_DOWNWARD, 4U)); + EXPECT_FP_EQ(aNaN, func(T(-10.65), FP_INT_DOWNWARD, 4U)); + EXPECT_FP_EQ(aNaN, func(T(1234.38), FP_INT_DOWNWARD, 11U)); + EXPECT_FP_EQ(aNaN, func(T(-1234.38), FP_INT_DOWNWARD, 11U)); + EXPECT_FP_EQ(aNaN, func(T(1234.96), FP_INT_DOWNWARD, 11U)); + EXPECT_FP_EQ(aNaN, func(T(-1234.96), FP_INT_DOWNWARD, 11U)); + } + + 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(aNaN, func(T(1.3), FP_INT_TOWARDZERO, 1U)); + EXPECT_FP_EQ(aNaN, func(T(1.5), FP_INT_TOWARDZERO, 1U)); + EXPECT_FP_EQ(aNaN, func(T(1.75), FP_INT_TOWARDZERO, 1U)); + EXPECT_FP_EQ(aNaN, func(T(10.32), FP_INT_TOWARDZERO, 4U)); + EXPECT_FP_EQ(aNaN, func(T(-10.32), FP_INT_TOWARDZERO, 4U)); + EXPECT_FP_EQ(aNaN, func(T(10.65), FP_INT_TOWARDZERO, 4U)); + EXPECT_FP_EQ(aNaN, func(T(-10.65), FP_INT_TOWARDZERO, 4U)); + EXPECT_FP_EQ(aNaN, func(T(1234.38), FP_INT_TOWARDZERO, 11U)); + EXPECT_FP_EQ(aNaN, func(T(-1234.38), FP_INT_TOWARDZERO, 11U)); + EXPECT_FP_EQ(aNaN, func(T(1234.96), FP_INT_TOWARDZERO, 11U)); + EXPECT_FP_EQ(aNaN, func(T(-1234.96), FP_INT_TOWARDZERO, 11U)); + } + + 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(aNaN, func(T(0.5), FP_INT_TONEARESTFROMZERO, 1U)); + EXPECT_FP_EQ(aNaN, func(T(0.715), FP_INT_TONEARESTFROMZERO, 1U)); + EXPECT_FP_EQ(aNaN, func(T(1.3), FP_INT_TONEARESTFROMZERO, 1U)); + EXPECT_FP_EQ(aNaN, func(T(1.5), FP_INT_TONEARESTFROMZERO, 2U)); + EXPECT_FP_EQ(aNaN, func(T(-1.5), FP_INT_TONEARESTFROMZERO, 1U)); + EXPECT_FP_EQ(aNaN, func(T(1.75), FP_INT_TONEARESTFROMZERO, 2U)); + EXPECT_FP_EQ(aNaN, func(T(-1.75), FP_INT_TONEARESTFROMZERO, 1U)); + EXPECT_FP_EQ(aNaN, func(T(10.32), FP_INT_TONEARESTFROMZERO, 4U)); + EXPECT_FP_EQ(aNaN, func(T(-10.32), FP_INT_TONEARESTFROMZERO, 4U)); + EXPECT_FP_EQ(aNaN, func(T(10.65), FP_INT_TONEARESTFROMZERO, 4U)); + EXPECT_FP_EQ(aNaN, func(T(-10.65), FP_INT_TONEARESTFROMZERO, 4U)); + EXPECT_FP_EQ(aNaN, func(T(1234.38), FP_INT_TONEARESTFROMZERO, 11U)); + EXPECT_FP_EQ(aNaN, func(T(-1234.38), FP_INT_TONEARESTFROMZERO, 11U)); + EXPECT_FP_EQ(aNaN, func(T(1234.96), FP_INT_TONEARESTFROMZERO, 11U)); + EXPECT_FP_EQ(aNaN, func(T(-1234.96), FP_INT_TONEARESTFROMZERO, 11U)); + } + + 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(aNaN, func(T(0.715), FP_INT_TONEAREST, 1U)); + EXPECT_FP_EQ(aNaN, func(T(1.3), FP_INT_TONEAREST, 1U)); + EXPECT_FP_EQ(aNaN, func(T(1.5), FP_INT_TONEAREST, 2U)); + EXPECT_FP_EQ(aNaN, func(T(-1.5), FP_INT_TONEAREST, 1U)); + EXPECT_FP_EQ(aNaN, func(T(1.75), FP_INT_TONEAREST, 2U)); + EXPECT_FP_EQ(aNaN, func(T(-1.75), FP_INT_TONEAREST, 1U)); + EXPECT_FP_EQ(aNaN, func(T(10.32), FP_INT_TONEAREST, 4U)); + EXPECT_FP_EQ(aNaN, func(T(-10.32), FP_INT_TONEAREST, 4U)); + EXPECT_FP_EQ(aNaN, func(T(10.65), FP_INT_TONEAREST, 4U)); + EXPECT_FP_EQ(aNaN, func(T(-10.65), FP_INT_TONEAREST, 4U)); + EXPECT_FP_EQ(aNaN, func(T(1234.38), FP_INT_TONEAREST, 11U)); + EXPECT_FP_EQ(aNaN, func(T(-1234.38), FP_INT_TONEAREST, 11U)); + EXPECT_FP_EQ(aNaN, func(T(1234.96), FP_INT_TONEAREST, 11U)); + EXPECT_FP_EQ(aNaN, func(T(-1234.96), FP_INT_TONEAREST, 11U)); + + EXPECT_FP_EQ(aNaN, func(T(2.3), FP_INT_TONEAREST, 2U)); + EXPECT_FP_EQ(aNaN, func(T(-2.3), FP_INT_TONEAREST, 1U)); + EXPECT_FP_EQ(aNaN, func(T(2.5), FP_INT_TONEAREST, 2U)); + EXPECT_FP_EQ(aNaN, func(T(-2.5), FP_INT_TONEAREST, 1U)); + EXPECT_FP_EQ(aNaN, func(T(2.75), FP_INT_TONEAREST, 2U)); + EXPECT_FP_EQ(aNaN, func(T(-2.75), FP_INT_TONEAREST, 2U)); + EXPECT_FP_EQ(aNaN, func(T(5.3), FP_INT_TONEAREST, 3U)); + EXPECT_FP_EQ(aNaN, func(T(-5.3), FP_INT_TONEAREST, 3U)); + EXPECT_FP_EQ(aNaN, func(T(5.5), FP_INT_TONEAREST, 3U)); + EXPECT_FP_EQ(aNaN, func(T(-5.5), FP_INT_TONEAREST, 3U)); + EXPECT_FP_EQ(aNaN, func(T(5.75), FP_INT_TONEAREST, 3U)); + EXPECT_FP_EQ(aNaN, func(T(-5.75), FP_INT_TONEAREST, 3U)); + } + + 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(aNaN, func(T(0.715), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U)); + EXPECT_FP_EQ(aNaN, func(T(1.3), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U)); + EXPECT_FP_EQ(aNaN, func(T(1.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 2U)); + EXPECT_FP_EQ(aNaN, func(T(-1.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U)); + EXPECT_FP_EQ(aNaN, func(T(1.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 2U)); + EXPECT_FP_EQ(aNaN, func(T(-1.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U)); + EXPECT_FP_EQ(aNaN, func(T(10.32), UNKNOWN_MATH_ROUNDING_DIRECTION, 4U)); + EXPECT_FP_EQ(aNaN, func(T(-10.32), UNKNOWN_MATH_ROUNDING_DIRECTION, 4U)); + EXPECT_FP_EQ(aNaN, func(T(10.65), UNKNOWN_MATH_ROUNDING_DIRECTION, 4U)); + EXPECT_FP_EQ(aNaN, func(T(-10.65), UNKNOWN_MATH_ROUNDING_DIRECTION, 4U)); + EXPECT_FP_EQ(aNaN, func(T(1234.38), UNKNOWN_MATH_ROUNDING_DIRECTION, 11U)); + EXPECT_FP_EQ(aNaN, func(T(-1234.38), UNKNOWN_MATH_ROUNDING_DIRECTION, 11U)); + EXPECT_FP_EQ(aNaN, func(T(1234.96), UNKNOWN_MATH_ROUNDING_DIRECTION, 11U)); + EXPECT_FP_EQ(aNaN, func(T(-1234.96), UNKNOWN_MATH_ROUNDING_DIRECTION, 11U)); + + EXPECT_FP_EQ(aNaN, func(T(2.3), UNKNOWN_MATH_ROUNDING_DIRECTION, 2U)); + EXPECT_FP_EQ(aNaN, func(T(-2.3), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U)); + EXPECT_FP_EQ(aNaN, func(T(2.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 2U)); + EXPECT_FP_EQ(aNaN, func(T(-2.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U)); + EXPECT_FP_EQ(aNaN, func(T(2.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 2U)); + EXPECT_FP_EQ(aNaN, func(T(-2.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 2U)); + EXPECT_FP_EQ(aNaN, func(T(5.3), UNKNOWN_MATH_ROUNDING_DIRECTION, 3U)); + EXPECT_FP_EQ(aNaN, func(T(-5.3), UNKNOWN_MATH_ROUNDING_DIRECTION, 3U)); + EXPECT_FP_EQ(aNaN, func(T(5.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 3U)); + EXPECT_FP_EQ(aNaN, func(T(-5.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 3U)); + EXPECT_FP_EQ(aNaN, func(T(5.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 3U)); + EXPECT_FP_EQ(aNaN, func(T(-5.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 3U)); + } +}; + +#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..e753fc489cdea7372311f9bb608911b80f8c6378 --- /dev/null +++ b/libc/test/src/math/smoke/UfromfpTest.h @@ -0,0 +1,348 @@ +//===-- 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(aNaN, func(inf, rnd, 32U)); + EXPECT_FP_EQ(aNaN, func(neg_inf, rnd, 32U)); + + EXPECT_FP_EQ(aNaN, func(aNaN, rnd, 32U)); + } + } + + void testSpecialNumbersZeroWidth(UfromfpFunc func) { + for (int rnd : MATH_ROUNDING_DIRECTIONS_INCLUDING_UNKNOWN) { + EXPECT_FP_EQ(aNaN, func(zero, rnd, 0U)); + EXPECT_FP_EQ(aNaN, func(neg_zero, rnd, 0U)); + + EXPECT_FP_EQ(aNaN, func(inf, rnd, 0U)); + EXPECT_FP_EQ(aNaN, func(neg_inf, rnd, 0U)); + + EXPECT_FP_EQ(aNaN, func(aNaN, rnd, 0U)); + } + } + + 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)); + } + } + + void testRoundedNumbersOutsideRange(UfromfpFunc func) { + for (int rnd : MATH_ROUNDING_DIRECTIONS_INCLUDING_UNKNOWN) { + EXPECT_FP_EQ(aNaN, func(T(-1.0), rnd, 32U)); + EXPECT_FP_EQ(aNaN, func(T(10.0), rnd, 3U)); + EXPECT_FP_EQ(aNaN, func(T(-10.0), rnd, 32U)); + EXPECT_FP_EQ(aNaN, func(T(1234.0), rnd, 10U)); + EXPECT_FP_EQ(aNaN, func(T(-1234.0), rnd, 32U)); + } + } + + 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(aNaN, func(T(1.3), FP_INT_UPWARD, 1U)); + EXPECT_FP_EQ(aNaN, func(T(-1.3), FP_INT_UPWARD, 32U)); + EXPECT_FP_EQ(aNaN, func(T(1.5), FP_INT_UPWARD, 1U)); + EXPECT_FP_EQ(aNaN, func(T(-1.5), FP_INT_UPWARD, 32U)); + EXPECT_FP_EQ(aNaN, func(T(1.75), FP_INT_UPWARD, 1U)); + EXPECT_FP_EQ(aNaN, func(T(-1.75), FP_INT_UPWARD, 32U)); + EXPECT_FP_EQ(aNaN, func(T(10.32), FP_INT_UPWARD, 3U)); + EXPECT_FP_EQ(aNaN, func(T(-10.32), FP_INT_UPWARD, 32U)); + EXPECT_FP_EQ(aNaN, func(T(10.65), FP_INT_UPWARD, 3U)); + EXPECT_FP_EQ(aNaN, func(T(-10.65), FP_INT_UPWARD, 3U)); + EXPECT_FP_EQ(aNaN, func(T(1234.38), FP_INT_UPWARD, 10U)); + EXPECT_FP_EQ(aNaN, func(T(-1234.38), FP_INT_UPWARD, 32U)); + EXPECT_FP_EQ(aNaN, func(T(1234.96), FP_INT_UPWARD, 10U)); + EXPECT_FP_EQ(aNaN, func(T(-1234.96), FP_INT_UPWARD, 32U)); + } + + 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(aNaN, func(T(-0.5), FP_INT_DOWNWARD, 32U)); + EXPECT_FP_EQ(aNaN, func(T(-0.115), FP_INT_DOWNWARD, 32U)); + EXPECT_FP_EQ(aNaN, func(T(-0.715), FP_INT_DOWNWARD, 32U)); + EXPECT_FP_EQ(aNaN, func(T(-1.3), FP_INT_DOWNWARD, 32U)); + EXPECT_FP_EQ(aNaN, func(T(-1.5), FP_INT_DOWNWARD, 32U)); + EXPECT_FP_EQ(aNaN, func(T(-1.75), FP_INT_DOWNWARD, 32U)); + EXPECT_FP_EQ(aNaN, func(T(10.32), FP_INT_DOWNWARD, 3U)); + EXPECT_FP_EQ(aNaN, func(T(-10.32), FP_INT_DOWNWARD, 32U)); + EXPECT_FP_EQ(aNaN, func(T(10.65), FP_INT_DOWNWARD, 3U)); + EXPECT_FP_EQ(aNaN, func(T(-10.65), FP_INT_DOWNWARD, 32U)); + EXPECT_FP_EQ(aNaN, func(T(1234.38), FP_INT_DOWNWARD, 10U)); + EXPECT_FP_EQ(aNaN, func(T(-1234.38), FP_INT_DOWNWARD, 32U)); + EXPECT_FP_EQ(aNaN, func(T(1234.96), FP_INT_DOWNWARD, 10U)); + EXPECT_FP_EQ(aNaN, func(T(-1234.96), FP_INT_DOWNWARD, 32U)); + } + + 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(aNaN, func(T(-1.3), FP_INT_TOWARDZERO, 32U)); + EXPECT_FP_EQ(aNaN, func(T(-1.5), FP_INT_TOWARDZERO, 32U)); + EXPECT_FP_EQ(aNaN, func(T(-1.75), FP_INT_TOWARDZERO, 32U)); + EXPECT_FP_EQ(aNaN, func(T(10.32), FP_INT_TOWARDZERO, 3U)); + EXPECT_FP_EQ(aNaN, func(T(-10.32), FP_INT_TOWARDZERO, 32U)); + EXPECT_FP_EQ(aNaN, func(T(10.65), FP_INT_TOWARDZERO, 3U)); + EXPECT_FP_EQ(aNaN, func(T(-10.65), FP_INT_TOWARDZERO, 32U)); + EXPECT_FP_EQ(aNaN, func(T(1234.38), FP_INT_TOWARDZERO, 10U)); + EXPECT_FP_EQ(aNaN, func(T(-1234.38), FP_INT_TOWARDZERO, 32U)); + EXPECT_FP_EQ(aNaN, func(T(1234.96), FP_INT_TOWARDZERO, 10U)); + EXPECT_FP_EQ(aNaN, func(T(-1234.96), FP_INT_TOWARDZERO, 32U)); + } + + 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(aNaN, func(T(-0.5), FP_INT_TONEARESTFROMZERO, 32U)); + EXPECT_FP_EQ(aNaN, func(T(-0.715), FP_INT_TONEARESTFROMZERO, 32U)); + EXPECT_FP_EQ(aNaN, func(T(-1.3), FP_INT_TONEARESTFROMZERO, 32U)); + EXPECT_FP_EQ(aNaN, func(T(1.5), FP_INT_TONEARESTFROMZERO, 1U)); + EXPECT_FP_EQ(aNaN, func(T(-1.5), FP_INT_TONEARESTFROMZERO, 32U)); + EXPECT_FP_EQ(aNaN, func(T(1.75), FP_INT_TONEARESTFROMZERO, 1U)); + EXPECT_FP_EQ(aNaN, func(T(-1.75), FP_INT_TONEARESTFROMZERO, 32U)); + EXPECT_FP_EQ(aNaN, func(T(10.32), FP_INT_TONEARESTFROMZERO, 3U)); + EXPECT_FP_EQ(aNaN, func(T(-10.32), FP_INT_TONEARESTFROMZERO, 32U)); + EXPECT_FP_EQ(aNaN, func(T(10.65), FP_INT_TONEARESTFROMZERO, 3U)); + EXPECT_FP_EQ(aNaN, func(T(-10.65), FP_INT_TONEARESTFROMZERO, 32U)); + EXPECT_FP_EQ(aNaN, func(T(1234.38), FP_INT_TONEARESTFROMZERO, 10U)); + EXPECT_FP_EQ(aNaN, func(T(-1234.38), FP_INT_TONEARESTFROMZERO, 32U)); + EXPECT_FP_EQ(aNaN, func(T(1234.96), FP_INT_TONEARESTFROMZERO, 10U)); + EXPECT_FP_EQ(aNaN, func(T(-1234.96), FP_INT_TONEARESTFROMZERO, 32U)); + } + + 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(aNaN, func(T(-0.715), FP_INT_TONEAREST, 32U)); + EXPECT_FP_EQ(aNaN, func(T(-1.3), FP_INT_TONEAREST, 32U)); + EXPECT_FP_EQ(aNaN, func(T(1.5), FP_INT_TONEAREST, 1U)); + EXPECT_FP_EQ(aNaN, func(T(-1.5), FP_INT_TONEAREST, 32U)); + EXPECT_FP_EQ(aNaN, func(T(1.75), FP_INT_TONEAREST, 1U)); + EXPECT_FP_EQ(aNaN, func(T(-1.75), FP_INT_TONEAREST, 32U)); + EXPECT_FP_EQ(aNaN, func(T(10.32), FP_INT_TONEAREST, 3U)); + EXPECT_FP_EQ(aNaN, func(T(-10.32), FP_INT_TONEAREST, 32U)); + EXPECT_FP_EQ(aNaN, func(T(10.65), FP_INT_TONEAREST, 3U)); + EXPECT_FP_EQ(aNaN, func(T(-10.65), FP_INT_TONEAREST, 32U)); + EXPECT_FP_EQ(aNaN, func(T(1234.38), FP_INT_TONEAREST, 10U)); + EXPECT_FP_EQ(aNaN, func(T(-1234.38), FP_INT_TONEAREST, 32U)); + EXPECT_FP_EQ(aNaN, func(T(1234.96), FP_INT_TONEAREST, 10U)); + EXPECT_FP_EQ(aNaN, func(T(-1234.96), FP_INT_TONEAREST, 32U)); + + EXPECT_FP_EQ(aNaN, func(T(2.3), FP_INT_TONEAREST, 1U)); + EXPECT_FP_EQ(aNaN, func(T(-2.3), FP_INT_TONEAREST, 32U)); + EXPECT_FP_EQ(aNaN, func(T(2.5), FP_INT_TONEAREST, 1U)); + EXPECT_FP_EQ(aNaN, func(T(-2.5), FP_INT_TONEAREST, 32U)); + EXPECT_FP_EQ(aNaN, func(T(2.75), FP_INT_TONEAREST, 1U)); + EXPECT_FP_EQ(aNaN, func(T(-2.75), FP_INT_TONEAREST, 32U)); + EXPECT_FP_EQ(aNaN, func(T(5.3), FP_INT_TONEAREST, 2U)); + EXPECT_FP_EQ(aNaN, func(T(-5.3), FP_INT_TONEAREST, 32U)); + EXPECT_FP_EQ(aNaN, func(T(5.5), FP_INT_TONEAREST, 2U)); + EXPECT_FP_EQ(aNaN, func(T(-5.5), FP_INT_TONEAREST, 32U)); + EXPECT_FP_EQ(aNaN, func(T(5.75), FP_INT_TONEAREST, 2U)); + EXPECT_FP_EQ(aNaN, func(T(-5.75), FP_INT_TONEAREST, 32U)); + } + + 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(aNaN, func(T(-0.715), UNKNOWN_MATH_ROUNDING_DIRECTION, 32U)); + EXPECT_FP_EQ(aNaN, func(T(-1.3), UNKNOWN_MATH_ROUNDING_DIRECTION, 32U)); + EXPECT_FP_EQ(aNaN, func(T(1.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U)); + EXPECT_FP_EQ(aNaN, func(T(-1.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 32U)); + EXPECT_FP_EQ(aNaN, func(T(1.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U)); + EXPECT_FP_EQ(aNaN, func(T(-1.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 32U)); + EXPECT_FP_EQ(aNaN, func(T(10.32), UNKNOWN_MATH_ROUNDING_DIRECTION, 3U)); + EXPECT_FP_EQ(aNaN, func(T(-10.32), UNKNOWN_MATH_ROUNDING_DIRECTION, 32U)); + EXPECT_FP_EQ(aNaN, func(T(10.65), UNKNOWN_MATH_ROUNDING_DIRECTION, 3U)); + EXPECT_FP_EQ(aNaN, func(T(-10.65), UNKNOWN_MATH_ROUNDING_DIRECTION, 32U)); + EXPECT_FP_EQ(aNaN, func(T(1234.38), UNKNOWN_MATH_ROUNDING_DIRECTION, 10U)); + EXPECT_FP_EQ(aNaN, func(T(-1234.38), UNKNOWN_MATH_ROUNDING_DIRECTION, 32U)); + EXPECT_FP_EQ(aNaN, func(T(1234.96), UNKNOWN_MATH_ROUNDING_DIRECTION, 10U)); + EXPECT_FP_EQ(aNaN, func(T(-1234.96), UNKNOWN_MATH_ROUNDING_DIRECTION, 32U)); + + EXPECT_FP_EQ(aNaN, func(T(2.3), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U)); + EXPECT_FP_EQ(aNaN, func(T(-2.3), UNKNOWN_MATH_ROUNDING_DIRECTION, 32U)); + EXPECT_FP_EQ(aNaN, func(T(2.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U)); + EXPECT_FP_EQ(aNaN, func(T(-2.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 32U)); + EXPECT_FP_EQ(aNaN, func(T(2.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U)); + EXPECT_FP_EQ(aNaN, func(T(-2.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 32U)); + EXPECT_FP_EQ(aNaN, func(T(5.3), UNKNOWN_MATH_ROUNDING_DIRECTION, 2U)); + EXPECT_FP_EQ(aNaN, func(T(-5.3), UNKNOWN_MATH_ROUNDING_DIRECTION, 32U)); + EXPECT_FP_EQ(aNaN, func(T(5.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 2U)); + EXPECT_FP_EQ(aNaN, func(T(-5.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 32U)); + EXPECT_FP_EQ(aNaN, func(T(5.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 2U)); + EXPECT_FP_EQ(aNaN, func(T(-5.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 32U)); + } +}; + +#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..47bf32c80f17056c8ba2c4b2ceac8d6b4428e8b6 --- /dev/null +++ b/libc/test/src/math/smoke/UfromfpxTest.h @@ -0,0 +1,437 @@ +//===-- 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(aNaN, func(inf, rnd, 32U)); + EXPECT_FP_EQ(aNaN, func(neg_inf, rnd, 32U)); + + EXPECT_FP_EQ(aNaN, func(aNaN, rnd, 32U)); + } + } + + void testSpecialNumbersZeroWidth(UfromfpxFunc func) { + for (int rnd : MATH_ROUNDING_DIRECTIONS_INCLUDING_UNKNOWN) { + EXPECT_FP_EQ(aNaN, func(zero, rnd, 0U)); + EXPECT_FP_EQ(aNaN, func(neg_zero, rnd, 0U)); + + EXPECT_FP_EQ(aNaN, func(inf, rnd, 0U)); + EXPECT_FP_EQ(aNaN, func(neg_inf, rnd, 0U)); + + EXPECT_FP_EQ(aNaN, func(aNaN, rnd, 0U)); + } + } + + 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)); + } + } + + void testRoundedNumbersOutsideRange(UfromfpxFunc func) { + for (int rnd : MATH_ROUNDING_DIRECTIONS_INCLUDING_UNKNOWN) { + EXPECT_FP_EQ(aNaN, func(T(-1.0), rnd, 32U)); + EXPECT_FP_EQ(aNaN, func(T(10.0), rnd, 3U)); + EXPECT_FP_EQ(aNaN, func(T(-10.0), rnd, 32U)); + EXPECT_FP_EQ(aNaN, func(T(1234.0), rnd, 10U)); + EXPECT_FP_EQ(aNaN, func(T(-1234.0), rnd, 32U)); + } + } + + 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(aNaN, func(T(1.3), FP_INT_UPWARD, 1U)); + EXPECT_FP_EQ(aNaN, func(T(-1.3), FP_INT_UPWARD, 32U)); + EXPECT_FP_EQ(aNaN, func(T(1.5), FP_INT_UPWARD, 1U)); + EXPECT_FP_EQ(aNaN, func(T(-1.5), FP_INT_UPWARD, 32U)); + EXPECT_FP_EQ(aNaN, func(T(1.75), FP_INT_UPWARD, 1U)); + EXPECT_FP_EQ(aNaN, func(T(-1.75), FP_INT_UPWARD, 32U)); + EXPECT_FP_EQ(aNaN, func(T(10.32), FP_INT_UPWARD, 3U)); + EXPECT_FP_EQ(aNaN, func(T(-10.32), FP_INT_UPWARD, 32U)); + EXPECT_FP_EQ(aNaN, func(T(10.65), FP_INT_UPWARD, 3U)); + EXPECT_FP_EQ(aNaN, func(T(-10.65), FP_INT_UPWARD, 3U)); + EXPECT_FP_EQ(aNaN, func(T(1234.38), FP_INT_UPWARD, 10U)); + EXPECT_FP_EQ(aNaN, func(T(-1234.38), FP_INT_UPWARD, 32U)); + EXPECT_FP_EQ(aNaN, func(T(1234.96), FP_INT_UPWARD, 10U)); + EXPECT_FP_EQ(aNaN, func(T(-1234.96), FP_INT_UPWARD, 32U)); + } + + 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(aNaN, func(T(-0.5), FP_INT_DOWNWARD, 32U)); + EXPECT_FP_EQ(aNaN, func(T(-0.115), FP_INT_DOWNWARD, 32U)); + EXPECT_FP_EQ(aNaN, func(T(-0.715), FP_INT_DOWNWARD, 32U)); + EXPECT_FP_EQ(aNaN, func(T(-1.3), FP_INT_DOWNWARD, 32U)); + EXPECT_FP_EQ(aNaN, func(T(-1.5), FP_INT_DOWNWARD, 32U)); + EXPECT_FP_EQ(aNaN, func(T(-1.75), FP_INT_DOWNWARD, 32U)); + EXPECT_FP_EQ(aNaN, func(T(10.32), FP_INT_DOWNWARD, 3U)); + EXPECT_FP_EQ(aNaN, func(T(-10.32), FP_INT_DOWNWARD, 32U)); + EXPECT_FP_EQ(aNaN, func(T(10.65), FP_INT_DOWNWARD, 3U)); + EXPECT_FP_EQ(aNaN, func(T(-10.65), FP_INT_DOWNWARD, 32U)); + EXPECT_FP_EQ(aNaN, func(T(1234.38), FP_INT_DOWNWARD, 10U)); + EXPECT_FP_EQ(aNaN, func(T(-1234.38), FP_INT_DOWNWARD, 32U)); + EXPECT_FP_EQ(aNaN, func(T(1234.96), FP_INT_DOWNWARD, 10U)); + EXPECT_FP_EQ(aNaN, func(T(-1234.96), FP_INT_DOWNWARD, 32U)); + } + + 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(aNaN, func(T(-1.3), FP_INT_TOWARDZERO, 32U)); + EXPECT_FP_EQ(aNaN, func(T(-1.5), FP_INT_TOWARDZERO, 32U)); + EXPECT_FP_EQ(aNaN, func(T(-1.75), FP_INT_TOWARDZERO, 32U)); + EXPECT_FP_EQ(aNaN, func(T(10.32), FP_INT_TOWARDZERO, 3U)); + EXPECT_FP_EQ(aNaN, func(T(-10.32), FP_INT_TOWARDZERO, 32U)); + EXPECT_FP_EQ(aNaN, func(T(10.65), FP_INT_TOWARDZERO, 3U)); + EXPECT_FP_EQ(aNaN, func(T(-10.65), FP_INT_TOWARDZERO, 32U)); + EXPECT_FP_EQ(aNaN, func(T(1234.38), FP_INT_TOWARDZERO, 10U)); + EXPECT_FP_EQ(aNaN, func(T(-1234.38), FP_INT_TOWARDZERO, 32U)); + EXPECT_FP_EQ(aNaN, func(T(1234.96), FP_INT_TOWARDZERO, 10U)); + EXPECT_FP_EQ(aNaN, func(T(-1234.96), FP_INT_TOWARDZERO, 32U)); + } + + 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(aNaN, func(T(-0.5), FP_INT_TONEARESTFROMZERO, 32U)); + EXPECT_FP_EQ(aNaN, func(T(-0.715), FP_INT_TONEARESTFROMZERO, 32U)); + EXPECT_FP_EQ(aNaN, func(T(-1.3), FP_INT_TONEARESTFROMZERO, 32U)); + EXPECT_FP_EQ(aNaN, func(T(1.5), FP_INT_TONEARESTFROMZERO, 1U)); + EXPECT_FP_EQ(aNaN, func(T(-1.5), FP_INT_TONEARESTFROMZERO, 32U)); + EXPECT_FP_EQ(aNaN, func(T(1.75), FP_INT_TONEARESTFROMZERO, 1U)); + EXPECT_FP_EQ(aNaN, func(T(-1.75), FP_INT_TONEARESTFROMZERO, 32U)); + EXPECT_FP_EQ(aNaN, func(T(10.32), FP_INT_TONEARESTFROMZERO, 3U)); + EXPECT_FP_EQ(aNaN, func(T(-10.32), FP_INT_TONEARESTFROMZERO, 32U)); + EXPECT_FP_EQ(aNaN, func(T(10.65), FP_INT_TONEARESTFROMZERO, 3U)); + EXPECT_FP_EQ(aNaN, func(T(-10.65), FP_INT_TONEARESTFROMZERO, 32U)); + EXPECT_FP_EQ(aNaN, func(T(1234.38), FP_INT_TONEARESTFROMZERO, 10U)); + EXPECT_FP_EQ(aNaN, func(T(-1234.38), FP_INT_TONEARESTFROMZERO, 32U)); + EXPECT_FP_EQ(aNaN, func(T(1234.96), FP_INT_TONEARESTFROMZERO, 10U)); + EXPECT_FP_EQ(aNaN, func(T(-1234.96), FP_INT_TONEARESTFROMZERO, 32U)); + } + + 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(aNaN, func(T(-0.715), FP_INT_TONEAREST, 32U)); + EXPECT_FP_EQ(aNaN, func(T(-1.3), FP_INT_TONEAREST, 32U)); + EXPECT_FP_EQ(aNaN, func(T(1.5), FP_INT_TONEAREST, 1U)); + EXPECT_FP_EQ(aNaN, func(T(-1.5), FP_INT_TONEAREST, 32U)); + EXPECT_FP_EQ(aNaN, func(T(1.75), FP_INT_TONEAREST, 1U)); + EXPECT_FP_EQ(aNaN, func(T(-1.75), FP_INT_TONEAREST, 32U)); + EXPECT_FP_EQ(aNaN, func(T(10.32), FP_INT_TONEAREST, 3U)); + EXPECT_FP_EQ(aNaN, func(T(-10.32), FP_INT_TONEAREST, 32U)); + EXPECT_FP_EQ(aNaN, func(T(10.65), FP_INT_TONEAREST, 3U)); + EXPECT_FP_EQ(aNaN, func(T(-10.65), FP_INT_TONEAREST, 32U)); + EXPECT_FP_EQ(aNaN, func(T(1234.38), FP_INT_TONEAREST, 10U)); + EXPECT_FP_EQ(aNaN, func(T(-1234.38), FP_INT_TONEAREST, 32U)); + EXPECT_FP_EQ(aNaN, func(T(1234.96), FP_INT_TONEAREST, 10U)); + EXPECT_FP_EQ(aNaN, func(T(-1234.96), FP_INT_TONEAREST, 32U)); + + EXPECT_FP_EQ(aNaN, func(T(2.3), FP_INT_TONEAREST, 1U)); + EXPECT_FP_EQ(aNaN, func(T(-2.3), FP_INT_TONEAREST, 32U)); + EXPECT_FP_EQ(aNaN, func(T(2.5), FP_INT_TONEAREST, 1U)); + EXPECT_FP_EQ(aNaN, func(T(-2.5), FP_INT_TONEAREST, 32U)); + EXPECT_FP_EQ(aNaN, func(T(2.75), FP_INT_TONEAREST, 1U)); + EXPECT_FP_EQ(aNaN, func(T(-2.75), FP_INT_TONEAREST, 32U)); + EXPECT_FP_EQ(aNaN, func(T(5.3), FP_INT_TONEAREST, 2U)); + EXPECT_FP_EQ(aNaN, func(T(-5.3), FP_INT_TONEAREST, 32U)); + EXPECT_FP_EQ(aNaN, func(T(5.5), FP_INT_TONEAREST, 2U)); + EXPECT_FP_EQ(aNaN, func(T(-5.5), FP_INT_TONEAREST, 32U)); + EXPECT_FP_EQ(aNaN, func(T(5.75), FP_INT_TONEAREST, 2U)); + EXPECT_FP_EQ(aNaN, func(T(-5.75), FP_INT_TONEAREST, 32U)); + } + + 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(aNaN, func(T(-0.715), UNKNOWN_MATH_ROUNDING_DIRECTION, 32U)); + EXPECT_FP_EQ(aNaN, func(T(-1.3), UNKNOWN_MATH_ROUNDING_DIRECTION, 32U)); + EXPECT_FP_EQ(aNaN, func(T(1.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U)); + EXPECT_FP_EQ(aNaN, func(T(-1.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 32U)); + EXPECT_FP_EQ(aNaN, func(T(1.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U)); + EXPECT_FP_EQ(aNaN, func(T(-1.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 32U)); + EXPECT_FP_EQ(aNaN, func(T(10.32), UNKNOWN_MATH_ROUNDING_DIRECTION, 3U)); + EXPECT_FP_EQ(aNaN, func(T(-10.32), UNKNOWN_MATH_ROUNDING_DIRECTION, 32U)); + EXPECT_FP_EQ(aNaN, func(T(10.65), UNKNOWN_MATH_ROUNDING_DIRECTION, 3U)); + EXPECT_FP_EQ(aNaN, func(T(-10.65), UNKNOWN_MATH_ROUNDING_DIRECTION, 32U)); + EXPECT_FP_EQ(aNaN, func(T(1234.38), UNKNOWN_MATH_ROUNDING_DIRECTION, 10U)); + EXPECT_FP_EQ(aNaN, func(T(-1234.38), UNKNOWN_MATH_ROUNDING_DIRECTION, 32U)); + EXPECT_FP_EQ(aNaN, func(T(1234.96), UNKNOWN_MATH_ROUNDING_DIRECTION, 10U)); + EXPECT_FP_EQ(aNaN, func(T(-1234.96), UNKNOWN_MATH_ROUNDING_DIRECTION, 32U)); + + EXPECT_FP_EQ(aNaN, func(T(2.3), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U)); + EXPECT_FP_EQ(aNaN, func(T(-2.3), UNKNOWN_MATH_ROUNDING_DIRECTION, 32U)); + EXPECT_FP_EQ(aNaN, func(T(2.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U)); + EXPECT_FP_EQ(aNaN, func(T(-2.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 32U)); + EXPECT_FP_EQ(aNaN, func(T(2.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U)); + EXPECT_FP_EQ(aNaN, func(T(-2.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 32U)); + EXPECT_FP_EQ(aNaN, func(T(5.3), UNKNOWN_MATH_ROUNDING_DIRECTION, 2U)); + EXPECT_FP_EQ(aNaN, func(T(-5.3), UNKNOWN_MATH_ROUNDING_DIRECTION, 32U)); + EXPECT_FP_EQ(aNaN, func(T(5.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 2U)); + EXPECT_FP_EQ(aNaN, func(T(-5.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 32U)); + EXPECT_FP_EQ(aNaN, func(T(5.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 2U)); + EXPECT_FP_EQ(aNaN, func(T(-5.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 32U)); + } +}; + +#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/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/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..4c38e8aba7d7f2cf85fbb4271e985d266baed506 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( 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/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..8dde95d02a96dca42a4d6efeca4d232299af3701 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 } diff --git a/libc/test/src/stdlib/CMakeLists.txt b/libc/test/src/stdlib/CMakeLists.txt index 5488a61c4ef1879b93ceccb33feeeaa8c2a15fd9..3ccc1cde91934c1db6e6c3ba1cd70fa68e9ec6cb 100644 --- a/libc/test/src/stdlib/CMakeLists.txt +++ b/libc/test/src/stdlib/CMakeLists.txt @@ -168,6 +168,47 @@ add_libc_test( .strtol_test_support ) +add_header_library( + strfrom_test_support + HDRS + StrfromTest.h + DEPENDS + libc.src.__support.CPP.type_traits +) + +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 +300,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..f695bbb335bdbe14cc20ca470a10fc19da6cade9 --- /dev/null +++ b/libc/test/src/stdlib/StrfromTest.h @@ -0,0 +1,435 @@ +//===-- 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 "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); + ASSERT_STREQ_LEN(written, buff, is_long_double ? "0X8P-3" : "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 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) { + char buff[100]; + 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) { + char buff[100]; + 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 + } +}; + +#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); \ + } 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/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/MPFRWrapper/MPFRUtils.cpp b/libc/utils/MPFRWrapper/MPFRUtils.cpp index 7cc18cfb624389067be678be3607ca5512475a4a..2e1c44e6fd5da9607ce0536915150c4c06d94334 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> diff --git a/libclc/CMakeLists.txt b/libclc/CMakeLists.txt index fa1d8e4adbcc4fb380d7cf3c60e4726c0755b8f7..745b848fba4901f7dd263016047c3f4e92d091b1 100644 --- a/libclc/CMakeLists.txt +++ b/libclc/CMakeLists.txt @@ -40,8 +40,7 @@ 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) @@ -49,16 +48,16 @@ include(AddLLVM) message( "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 ) @@ -75,15 +74,15 @@ message( "opt: ${LLVM_OPT}" ) message( "llvm-spirv: ${LLVM_SPIRV}" ) message( "" ) if( NOT LLVM_CLANG OR NOT LLVM_OPT OR NOT LLVM_AS OR NOT LLVM_LINK ) - message( FATAL_ERROR "toolchain incomplete!" ) + message( FATAL_ERROR "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 +98,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 +141,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 +157,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( "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" ) + 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( " 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/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..9274932a764c55b5448af73e146355204fa76d81 --- /dev/null +++ b/libcxx/benchmarks/algorithms/mismatch.bench.cpp @@ -0,0 +1,31 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include <algorithm> +#include <benchmark/benchmark.h> +#include <random> + +// 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>)->DenseRange(1, 8)->Range(16, 1 << 20); +BENCHMARK(bm_mismatch<short>)->DenseRange(1, 8)->Range(16, 1 << 20); +BENCHMARK(bm_mismatch<int>)->DenseRange(1, 8)->Range(16, 1 << 20); + +BENCHMARK_MAIN(); 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/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt index 63adc03fae2980ae792a66ce52f0004f73a8d4ea..982b85e4e2d62fc54353d1ef5c46e21c3eba0710 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 @@ -755,10 +756,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 +772,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 +796,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_backward.h b/libcxx/include/__algorithm/copy_backward.h index 3ec88d8bd5cc3a6a6656c3cc0d6f3fc6f4919dac..591dd21e2b032eb23e8b309092fdfaabea94adb1 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> diff --git a/libcxx/include/__algorithm/copy_move_common.h b/libcxx/include/__algorithm/copy_move_common.h index 0fc7a5e3cee70095c2d1637fdd626a63b8f08f12..845967b05038d6b554275213143f22d027c961fb 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> 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..4eb693a1f2e9d8c6e848e1ec471f5d028d4c5b34 100644 --- a/libcxx/include/__algorithm/mismatch.h +++ b/libcxx/include/__algorithm/mismatch.h @@ -11,23 +11,93 @@ #define _LIBCPP___ALGORITHM_MISMATCH_H #include <__algorithm/comp.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/operation_traits.h> +#include <__utility/move.h> #include <__utility/pair.h> +#include <__utility/unreachable.h> #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()) { + 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; + } + } + // TODO: Consider vectorizing the tail + 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> @@ -59,4 +129,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..bf574b5274093dddd44769d417fc1128ae5bb5bb 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> diff --git a/libcxx/include/__algorithm/move_backward.h b/libcxx/include/__algorithm/move_backward.h index aeedf4241dce9cbc4635a27fa228adb4d464db7a..6bb7c91d66c7ce2cde92012b1a78c7b48e587ce4 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> 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_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..1aedb3db010f77defc3434b832aa1af6b4213b6f --- /dev/null +++ b/libcxx/include/__algorithm/simd_utils.h @@ -0,0 +1,123 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache 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 <__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 + +// 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::__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 + +#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/__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/__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/__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/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_context.h b/libcxx/include/__format/format_context.h index d131e942aca60b0042ba9e9cfc5bfbcf470d6169..bf603c5c62d9db88a1fb7e9279e550b377519140 100644 --- a/libcxx/include/__format/format_context.h +++ b/libcxx/include/__format/format_context.h @@ -27,7 +27,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_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/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/__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/__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..794a794d8fd85a2daae0a483411fb278beded058 100644 --- a/libcxx/include/__memory/shared_ptr.h +++ b/libcxx/include/__memory/shared_ptr.h @@ -37,8 +37,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/__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/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..d3665a149a7ca6cbc3fafad128af81275f838515 100644 --- a/libcxx/include/__ranges/zip_view.h +++ b/libcxx/include/__ranges/zip_view.h @@ -30,7 +30,7 @@ #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> @@ -489,12 +489,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/__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_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/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..0056806877e13ca0e170d9eda0eafc48fc141967 100644 --- a/libcxx/include/__utility/pair.h +++ b/libcxx/include/__utility/pair.h @@ -30,16 +30,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> 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..a6212fedfa2cd0a6a9ab9496e3d363032b43eae5 100644 --- a/libcxx/include/any +++ b/libcxx/include/any @@ -92,9 +92,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/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..146613464534f7bc251878d37944557c02da0fe3 100644 --- a/libcxx/include/format +++ b/libcxx/include/format @@ -221,4 +221,8 @@ namespace std { # pragma GCC system_header #endif +#if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 +# include <locale> +#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/ios b/libcxx/include/ios index 4b1306fc2ad83089db86e70ae8a16ccbe9e2f246..00c1d5c2d4bc584e5a32c6223b4d29504206e9df 100644 --- a/libcxx/include/ios +++ b/libcxx/include/ios @@ -359,7 +359,13 @@ public: } protected: - _LIBCPP_HIDE_FROM_ABI ios_base() { // purposefully does no initialization + _LIBCPP_HIDE_FROM_ABI ios_base() : __loc_(nullptr) { + // Purposefully does no initialization + // + // Except for the locale, this is a sentinel to avoid destroying + // an uninitialized object. See + // test/libcxx/input.output/iostreams.base/ios.base/ios.base.cons/dtor.uninitialized.pass.cpp + // for the details. } void init(void* __sb); @@ -571,7 +577,9 @@ public: _LIBCPP_HIDE_FROM_ABI char_type widen(char __c) const; protected: - _LIBCPP_HIDE_FROM_ABI basic_ios() { // purposefully does no initialization + _LIBCPP_HIDE_FROM_ABI basic_ios() { + // purposefully does no initialization + // since the destructor does nothing this does not have ios_base issues. } _LIBCPP_HIDE_FROM_ABI void init(basic_streambuf<char_type, traits_type>* __sb); diff --git a/libcxx/include/libcxx.imp b/libcxx/include/libcxx.imp index b1e728cde868da1e8c91ae8e62b678a86ef490a3..56ea58262828a0411480eaf8e17f9f58a8d388d0 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" ] }, @@ -751,10 +752,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 +768,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 +792,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..03d18775631ed64279298ebf14eea047adbd60c0 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" } @@ -1902,7 +1906,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 +1930,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 +1978,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" } 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/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/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/tuple b/libcxx/include/tuple index e63e4e25a7d2bd7ad9ea7276590d20f3ae5b9f88..a9f0d680fe0e72f5420e26c4667ecdeb6b02560a 100644 --- a/libcxx/include/tuple +++ b/libcxx/include/tuple @@ -232,20 +232,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> @@ -1369,9 +1360,6 @@ inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_T1, _T2>::pair( 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 +1377,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/variant b/libcxx/include/variant index d1eea52f0a93010c5abdb5bb12547d3c317b77ae..f5e99fc3239e84564af204af88674690c29f8359 100644 --- a/libcxx/include/variant +++ b/libcxx/include/variant @@ -228,17 +228,16 @@ 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_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/type_identity.h> @@ -347,13 +346,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 +1084,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 +1094,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..0908482600c533f694eae8bf5a783e3d8472c85e 100644 --- a/libcxx/include/vector +++ b/libcxx/include/vector @@ -346,7 +346,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> @@ -2990,6 +2990,7 @@ _LIBCPP_POP_MACROS # include <concepts> # include <cstdlib> # 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/ios.cpp b/libcxx/src/ios.cpp index d58827fa1255cfde58b1f09c9207726118133b39..a727855c4655e89d949297bf7fef25175fa7a15c 100644 --- a/libcxx/src/ios.cpp +++ b/libcxx/src/ios.cpp @@ -195,6 +195,10 @@ void ios_base::register_callback(event_callback fn, int index) { } ios_base::~ios_base() { + // Avoid UB when not properly initialized. See ios_base::ios_base for + // more information. + if (!__loc_) + return; __call_callbacks(erase_event); locale& loc_storage = *reinterpret_cast<locale*>(&__loc_); loc_storage.~locale(); 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.cpp b/libcxx/src/tzdb.cpp index 2bb801e48694ee3900d9073d676428215fee5f52..0307f754caabf38191991f7837701c2d95a2065d 100644 --- a/libcxx/src/tzdb.cpp +++ b/libcxx/src/tzdb.cpp @@ -511,14 +511,33 @@ static string __parse_version(istream& __input) { return chrono::__parse_string(__input); } +[[nodiscard]] +static __tz::__rule& __create_entry(__tz::__rules_storage_type& __rules, const string& __name) { + auto __result = [&]() -> __tz::__rule& { + auto& __rule = __rules.emplace_back(__name, vector<__tz::__rule>{}); + return __rule.second.emplace_back(); + }; + + if (__rules.empty()) + return __result(); + + // Typically rules are in contiguous order in the database. + // But there are exceptions, some rules are interleaved. + if (__rules.back().first == __name) + return __rules.back().second.emplace_back(); + + if (auto __it = ranges::find(__rules, __name, [](const auto& __r) { return __r.first; }); + __it != ranges::end(__rules)) + return __it->second.emplace_back(); + + return __result(); +} + static void __parse_rule(tzdb& __tzdb, __tz::__rules_storage_type& __rules, istream& __input) { chrono::__skip_mandatory_whitespace(__input); string __name = chrono::__parse_string(__input); - if (__rules.empty() || __rules.back().first != __name) - __rules.emplace_back(__name, vector<__tz::__rule>{}); - - __tz::__rule& __rule = __rules.back().second.emplace_back(); + __tz::__rule& __rule = __create_entry(__rules, __name); chrono::__skip_mandatory_whitespace(__input); __rule.__from = chrono::__parse_year(__input); 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/iostreams.base/ios.base/ios.base.cons/dtor.uninitialized.pass.cpp b/libcxx/test/libcxx/input.output/iostreams.base/ios.base/ios.base.cons/dtor.uninitialized.pass.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ea42203d0544693f53af0460732e6da28867062a --- /dev/null +++ b/libcxx/test/libcxx/input.output/iostreams.base/ios.base/ios.base.cons/dtor.uninitialized.pass.cpp @@ -0,0 +1,80 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: no-exceptions + +// The fix for issue 57964 requires an updated dylib due to explicit +// instantiations. That means Apple backdeployment targets remain broken. +// UNSUPPORTED: using-built-library-before-llvm-19 + +// <ios> + +// class ios_base + +// ~ios_base() +// +// Destroying a constructed ios_base object that has not been +// initialized by basic_ios::init is undefined behaviour. This can +// happen in practice, make sure the undefined behaviour is handled +// gracefully. +// +// +// [ios.base.cons]/1 +// +// ios_base(); +// Effects: Each ios_base member has an indeterminate value after construction. +// The object's members shall be initialized by calling basic_ios::init before +// the object's first use or before it is destroyed, whichever comes first; +// otherwise the behavior is undefined. +// +// [basic.ios.cons]/2 +// +// basic_ios(); +// Effects: Leaves its member objects uninitialized. The object shall be +// initialized by calling basic_ios::init before its first use or before it is +// destroyed, whichever comes first; otherwise the behavior is undefined. +// +// ostream and friends have a basic_ios virtual base. +// [class.base.init]/13 +// In a non-delegating constructor, initialization proceeds in the +// following order: +// - First, and only for the constructor of the most derived class +// ([intro.object]), virtual base classes are initialized ... +// +// So in this example +// struct Foo : AlwaysThrows, std::ostream { +// Foo() : AlwaysThrows{}, std::ostream{nullptr} {} +// }; +// +// Here +// - the ios_base object is constructed +// - the AlwaysThrows object is constructed and throws an exception +// - the AlwaysThrows object is destrodyed +// - the ios_base object is destroyed +// +// The ios_base object is destroyed before it has been initialized and runs +// into undefined behavior. By using __loc_ as a sentinel we can avoid +// accessing uninitialized memory in the destructor. + +#include <ostream> + +struct AlwaysThrows { + AlwaysThrows() { throw 1; } +}; + +struct Foo : AlwaysThrows, std::ostream { + Foo() : AlwaysThrows(), std::ostream(nullptr) {} +}; + +int main(int, char**) { + try { + Foo foo; + } catch (...) { + }; + return 0; +} 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 5ae2ed1e91ebe50c5ad09ea7be8c3ed0411e815f..4814f4aad87fbc04b013724f20b07dbf2d68d0bc 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 @@ -550,6 +550,29 @@ R a 0 1 - Ja Su>=31 1w 2s abc assert(result.rules[0].second[2].__letters == "abc"); } +static void test_mixed_order() { + // This is a part of the real database. The interesting part is that the + // rules NZ and Chatham are interleaved. Make sure the parse algorithm + // handles this correctly. + parse_result result{ + R"( +# Since 1957 Chatham has been 45 minutes ahead of NZ, but until 2018a +# there was no documented single notation for the date and time of this +# transition. Duplicate the Rule lines for now, to give the 2018a change +# time to percolate out. +Rule NZ 1974 only - Nov Sun>=1 2:00s 1:00 D +Rule Chatham 1974 only - Nov Sun>=1 2:45s 1:00 - +Rule NZ 1975 only - Feb lastSun 2:00s 0 S +Rule Chatham 1975 only - Feb lastSun 2:45s 0 - +Rule NZ 1975 1988 - Oct lastSun 2:00s 1:00 D +Rule Chatham 1975 1988 - Oct lastSun 2:45s 1:00 - +)"}; + + assert(result.rules.size() == 2); + assert(result.rules[0].second.size() == 3); + assert(result.rules[1].second.size() == 3); +} + int main(int, const char**) { test_invalid(); test_name(); @@ -560,6 +583,7 @@ int main(int, const char**) { test_at(); test_save(); test_letter(); + test_mixed_order(); return 0; } diff --git a/libcxx/test/libcxx/transitive_includes/cxx03.csv b/libcxx/test/libcxx/transitive_includes/cxx03.csv index 678a986e522aa0945b5d167e837c1d5cb5ad98de..c65b9b9d705e27e1a82a6e683ec9ca3d726d18ef 100644 --- a/libcxx/test/libcxx/transitive_includes/cxx03.csv +++ b/libcxx/test/libcxx/transitive_includes/cxx03.csv @@ -266,9 +266,14 @@ filesystem system_error filesystem type_traits filesystem version format array +format cctype +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..b3d9e327fc7aa9bafdeb2020d40bfff5eedc605a 100644 --- a/libcxx/test/libcxx/transitive_includes/cxx11.csv +++ b/libcxx/test/libcxx/transitive_includes/cxx11.csv @@ -267,9 +267,14 @@ filesystem system_error filesystem type_traits filesystem version format array +format cctype +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..d723409422a3ebc9b90fd68ba50e1d079eab7308 100644 --- a/libcxx/test/libcxx/transitive_includes/cxx14.csv +++ b/libcxx/test/libcxx/transitive_includes/cxx14.csv @@ -269,9 +269,14 @@ filesystem system_error filesystem type_traits filesystem version format array +format cctype +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..d723409422a3ebc9b90fd68ba50e1d079eab7308 100644 --- a/libcxx/test/libcxx/transitive_includes/cxx17.csv +++ b/libcxx/test/libcxx/transitive_includes/cxx17.csv @@ -269,9 +269,14 @@ filesystem system_error filesystem type_traits filesystem version format array +format cctype +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..03b4eda8b4d86820a73608dce7e98dede6c6a2cf 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,14 @@ filesystem system_error filesystem type_traits filesystem version format array +format cctype +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..062127364adfeea434d3594549fc78a4c81777be 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,12 +189,16 @@ filesystem string filesystem string_view filesystem version format array +format cctype +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 @@ -201,6 +207,7 @@ format stdexcept format string format string_view format tuple +format typeinfo format version forward_list compare forward_list cstddef @@ -397,7 +404,6 @@ optional cstddef optional cstdint optional cstring optional initializer_list -optional limits optional new optional version ostream bitset diff --git a/libcxx/test/libcxx/transitive_includes/cxx26.csv b/libcxx/test/libcxx/transitive_includes/cxx26.csv index daa3e17698bbed1c36bcf58e9be900df5d89ffaf..062127364adfeea434d3594549fc78a4c81777be 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,12 +189,16 @@ filesystem string filesystem string_view filesystem version format array +format cctype +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 @@ -201,6 +207,7 @@ format stdexcept format string format string_view format tuple +format typeinfo format version forward_list compare forward_list cstddef @@ -397,7 +404,6 @@ optional cstddef optional cstdint optional cstring optional initializer_list -optional limits optional new optional version ostream bitset 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/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..e7f3994d977dcdad5cd72582a30e3b574f5e5744 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,173 @@ // 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; + } + } + } 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/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/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/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.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_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/variant/variant.variant/variant.assign/T.pass.cpp b/libcxx/test/std/utilities/variant/variant.variant/variant.assign/T.pass.cpp index b3fc2021a6b223761fbcd38be48bd3589eb0e0a6..b38b10d89dfd7eeafe6f9d0fa188551c24f2d396 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 {}; @@ -188,7 +183,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 +192,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"; @@ -299,13 +292,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..6b7de888884986f271ebea293cc431e4e8b03c14 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 @@ -68,8 +68,7 @@ void test_T_ctor_sfinae() { } { 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>; @@ -78,12 +77,8 @@ void test_T_ctor_sfinae() { 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 {}; @@ -128,13 +123,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); @@ -202,12 +195,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/support/variant_test_helpers.h b/libcxx/test/support/variant_test_helpers.h index c174cba3284019b4e9c346c5ab391ac655e4d6dc..345e32170e584493d7424710d4ded9b82ad7c3b2 100644 --- a/libcxx/test/support/variant_test_helpers.h +++ b/libcxx/test/support/variant_test_helpers.h @@ -24,16 +24,6 @@ // 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 225de937cc869a075ef7b4b09170c2c3debbf307..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 @@ -65,6 +64,12 @@ RUN <<EOF echo "ALL ALL = (ALL) NOPASSWD: ALL" | tee /etc/sudoers || true EOF +# Installing tzdata before other packages avoids the time zone prompts. +# These prompts seem to ignore DEBIAN_FRONTEND=noninteractive. +RUN sudo apt-get update \ + && sudo apt-get install -y \ + tzdata + RUN sudo apt-get update \ && sudo apt-get install -y \ python3 \ 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/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 4fd8798b794a1ec16017f5aa0f9904d6d3677e71..307d35349f3a467c4c447ca1b1629a55f994004d 100644 --- a/libcxx/utils/libcxx/test/features.py +++ b/libcxx/utils/libcxx/test/features.py @@ -176,7 +176,7 @@ DEFAULT_FEATURES = [ cfg, """ #include <atomic> - struct Large { int storage[1024/8]; }; + struct Large { char storage[1024/8]; }; std::atomic<Large> x; int main(int, char**) { (void)x.load(); (void)x.is_lock_free(); return 0; } """, @@ -421,6 +421,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/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/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..8f85929f1bea7fd6f55425672ebcdd4686f8e3af 100644 --- a/lld/COFF/Config.h +++ b/lld/COFF/Config.h @@ -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..1b075389325a91ad7de8a0c76397e6c5c29c1dfa 100644 --- a/lld/COFF/Driver.cpp +++ b/lld/COFF/Driver.cpp @@ -2028,6 +2028,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/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/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 691ebfc074320f7e91ecbb1941f4dd0dd12653e0..bb3608da80b21fe76b3521b02ce1ec380025fa89 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); @@ -222,7 +222,9 @@ struct Config { CGProfileSortKind callGraphProfileSort; bool checkSections; bool checkDynamicRelocs; - llvm::DebugCompressionType compressDebugSections; + std::optional<llvm::DebugCompressionType> compressDebugSections; + llvm::SmallVector<std::pair<llvm::GlobPattern, llvm::DebugCompressionType>, 0> + compressSections; bool cref; llvm::SmallVector<std::pair<llvm::GlobPattern, uint64_t>, 0> deadRelocInNonAlloc; @@ -271,6 +273,7 @@ struct Config { bool printGcSections; bool printIcfSections; bool printMemoryUsage; + bool rejectMismatch; bool relax; bool relaxGP; bool relocatable; diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp index de4b2e345ac917e119ef4b72866af81f715e7973..7257ebd0fac9949383b7306ca23c0bce3c62f8f2 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) { @@ -1224,9 +1224,10 @@ static void readConfigs(opt::InputArgList &args) { config->checkSections = args.hasFlag(OPT_check_sections, OPT_no_check_sections, true); config->chroot = args.getLastArgValue(OPT_chroot); - config->compressDebugSections = getCompressionType( - args.getLastArgValue(OPT_compress_debug_sections, "none"), - "--compress-debug-sections"); + if (auto *arg = args.getLastArg(OPT_compress_debug_sections)) { + config->compressDebugSections = + getCompressionType(arg->getValue(), "--compress-debug-sections"); + } config->cref = args.hasArg(OPT_cref); config->optimizeBBJumps = args.hasFlag(OPT_optimize_bb_jumps, OPT_no_optimize_bb_jumps, false); @@ -1347,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); @@ -1516,6 +1518,23 @@ static void readConfigs(opt::InputArgList &args) { } } + for (opt::Arg *arg : args.filtered(OPT_compress_sections)) { + SmallVector<StringRef, 0> fields; + StringRef(arg->getValue()).split(fields, '='); + if (fields.size() != 2 || fields[1].empty()) { + error(arg->getSpelling() + + ": parse error, not 'section-glob=[none|zlib|zstd]'"); + continue; + } + auto type = getCompressionType(fields[1], arg->getSpelling()); + if (Expected<GlobPattern> pat = GlobPattern::create(fields[0])) { + config->compressSections.emplace_back(std::move(*pat), type); + } else { + error(arg->getSpelling() + ": " + toString(pat.takeError())); + continue; + } + } + for (opt::Arg *arg : args.filtered(OPT_z)) { std::pair<StringRef, StringRef> option = StringRef(arg->getValue()).split('='); @@ -1781,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) { @@ -2661,45 +2711,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)) @@ -2720,7 +2733,7 @@ void LinkerDriver::link(opt::InputArgList &args) { 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]); + doParseFile<ELFT>(files[i]); } if (armCmseImpLib) parseArmCMSEImportLib(*armCmseImpLib); @@ -2854,7 +2867,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. @@ -2862,7 +2875,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=. @@ -2927,7 +2940,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; }); } @@ -2985,10 +2998,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. @@ -3001,7 +3014,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 @@ -3041,8 +3054,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 @@ -3050,9 +3063,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..4c614c865d24a90ee942c726814cf39c8317d153 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -288,7 +288,7 @@ static bool isCompatible(InputFile *file) { return false; } -template <class ELFT> static void doParseFile(InputFile *file) { +template <class ELFT> void elf::doParseFile(InputFile *file) { if (!isCompatible(file)) return; @@ -741,6 +741,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 +761,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 +788,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 +811,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 +845,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. diff --git a/lld/ELF/InputFiles.h b/lld/ELF/InputFiles.h index 54de842a81cf35858856ad37c7b323261cf3effd..3beb5a3cb9a8946b045fffa3765f12f34f50bb11 100644 --- a/lld/ELF/InputFiles.h +++ b/lld/ELF/InputFiles.h @@ -46,6 +46,7 @@ extern std::unique_ptr<llvm::TarWriter> tar; std::optional<MemoryBufferRef> readFile(StringRef path); // Add symbols in File to the symbol table. +template <class ELFT> void doParseFile(InputFile *file); void parseFile(InputFile *file); void parseArmCMSEImportLib(InputFile *file); diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp index 7508a1336c91a44879b889c8d604f59f2b97cd1d..c34bf08757b156143cedfd44444cce71fa0c7901 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) { 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..3af09a32b6511370835297e37708b356d04e1fe5 100644 --- a/lld/ELF/LinkerScript.cpp +++ b/lld/ELF/LinkerScript.cpp @@ -740,13 +740,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; } 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 c10a73e2d9c36f97467103df4a9f74162a8a9552..c5e95d0d25c1aeb5388ca6d691c9b8fc1fcb785e 100644 --- a/lld/ELF/Options.td +++ b/lld/ELF/Options.td @@ -67,6 +67,10 @@ defm compress_debug_sections: Eq<"compress-debug-sections", "Compress DWARF debug sections">, MetaVarName<"[none,zlib,zstd]">; +defm compress_sections: EEq<"compress-sections", + "Compress non-SHF_ALLOC output sections matching <section-glob>">, + MetaVarName<"<section-glob>=[none|zlib|zstd]">; + defm defsym: Eq<"defsym", "Define a symbol alias">, MetaVarName<"<symbol>=<value>">; defm optimize_bb_jumps: BB<"optimize-bb-jumps", @@ -308,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)">; @@ -749,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 ee937418678707cac0e78b0d422c2e85f0449b7a..eadab9d745d6870a9e9c7a4141b17d9654ea35ef 100644 --- a/lld/ELF/OutputSections.cpp +++ b/lld/ELF/OutputSections.cpp @@ -326,17 +326,30 @@ static SmallVector<uint8_t, 0> deflateShard(ArrayRef<uint8_t> in, int level, } #endif -// Compress section contents if this section contains debug info. +// Compress certain non-SHF_ALLOC sections: +// +// * (if --compress-debug-sections is specified) non-empty .debug_* sections +// * (if --compress-sections is specified) matched sections template <class ELFT> void OutputSection::maybeCompress() { using Elf_Chdr = typename ELFT::Chdr; (void)sizeof(Elf_Chdr); - // Compress only DWARF debug sections. - if (config->compressDebugSections == DebugCompressionType::None || - (flags & SHF_ALLOC) || !name.starts_with(".debug_") || size == 0) + DebugCompressionType ctype = DebugCompressionType::None; + for (auto &[glob, t] : config->compressSections) + if (glob.match(name)) + ctype = t; + if (!(flags & SHF_ALLOC) && config->compressDebugSections && + name.starts_with(".debug_") && size) + ctype = *config->compressDebugSections; + if (ctype == DebugCompressionType::None) + return; + if (flags & SHF_ALLOC) { + errorOrWarn("--compress-sections: section '" + name + + "' with the SHF_ALLOC flag cannot be compressed"); return; + } - llvm::TimeTraceScope timeScope("Compress debug sections"); + llvm::TimeTraceScope timeScope("Compress sections"); compressed.uncompressedSize = size; auto buf = std::make_unique<uint8_t[]>(size); // Write uncompressed data to a temporary zero-initialized buffer. @@ -344,14 +357,21 @@ template <class ELFT> void OutputSection::maybeCompress() { parallel::TaskGroup tg; writeTo<ELFT>(buf.get(), tg); } + // The generic ABI specifies "The sh_size and sh_addralign fields of the + // section header for a compressed section reflect the requirements of the + // compressed section." However, 1-byte alignment has been wildly accepted + // and utilized for a long time. Removing alignment padding is particularly + // useful when there are many compressed output sections. + addralign = 1; #if LLVM_ENABLE_ZSTD // Use ZSTD's streaming compression API which permits parallel workers working // on the stream. See http://facebook.github.io/zstd/zstd_manual.html // "Streaming compression - HowTo". - if (config->compressDebugSections == DebugCompressionType::Zstd) { + if (ctype == DebugCompressionType::Zstd) { // Allocate a buffer of half of the input size, and grow it by 1.5x if // insufficient. + compressed.type = ELFCOMPRESS_ZSTD; compressed.shards = std::make_unique<SmallVector<uint8_t, 0>[]>(1); SmallVector<uint8_t, 0> &out = compressed.shards[0]; out.resize_for_overwrite(std::max<size_t>(size / 2, 32)); @@ -424,6 +444,7 @@ template <class ELFT> void OutputSection::maybeCompress() { } size += 4; // checksum + compressed.type = ELFCOMPRESS_ZLIB; compressed.shards = std::move(shardsOut); compressed.numShards = numShards; compressed.checksum = checksum; @@ -450,20 +471,18 @@ void OutputSection::writeTo(uint8_t *buf, parallel::TaskGroup &tg) { if (type == SHT_NOBITS) return; - // If --compress-debug-section is specified and if this is a debug section, - // we've already compressed section contents. If that's the case, - // just write it down. + // If the section is compressed due to + // --compress-debug-section/--compress-sections, the content is already known. if (compressed.shards) { auto *chdr = reinterpret_cast<typename ELFT::Chdr *>(buf); + chdr->ch_type = compressed.type; chdr->ch_size = compressed.uncompressedSize; chdr->ch_addralign = addralign; buf += sizeof(*chdr); - if (config->compressDebugSections == DebugCompressionType::Zstd) { - chdr->ch_type = ELFCOMPRESS_ZSTD; + if (compressed.type == ELFCOMPRESS_ZSTD) { memcpy(buf, compressed.shards[0].data(), compressed.shards[0].size()); return; } - chdr->ch_type = ELFCOMPRESS_ZLIB; // Compute shard offsets. auto offsets = std::make_unique<size_t[]>(compressed.numShards); @@ -564,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. @@ -596,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. @@ -731,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/OutputSections.h b/lld/ELF/OutputSections.h index c7931471a6ed30a14c614651af3c0dc937a09fb6..421a0181feb5dfaa388bacae11b983477ab24211 100644 --- a/lld/ELF/OutputSections.h +++ b/lld/ELF/OutputSections.h @@ -23,6 +23,7 @@ struct PhdrEntry; struct CompressedData { std::unique_ptr<SmallVector<uint8_t, 0>[]> shards; + uint32_t type = 0; uint32_t numShards = 0; uint32_t checksum = 0; uint64_t uncompressedSize; @@ -116,12 +117,13 @@ public: void sortInitFini(); void sortCtorsDtors(); + // Used for implementation of --compress-debug-sections and + // --compress-sections. + CompressedData compressed; + private: SmallVector<InputSection *, 0> storage; - // Used for implementation of --compress-debug-sections option. - CompressedData compressed; - std::array<uint8_t, 4> getFiller(); }; diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp index 619fbaf5dc5452f3eb615b3178c45828289faa1e..33c50133bec4951e24184c35ba4496530a8f15c6 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 @@ -1662,7 +1661,7 @@ static bool handleNonPreemptibleIfunc(Symbol &sym, uint16_t flags) { // section/value fixed. auto *directSym = makeDefined(cast<Defined>(sym)); directSym->allocateAux(); - addPltEntry(*in.iplt, *in.igotPlt, *in.relaIplt, target->iRelativeRel, + addPltEntry(*in.iplt, *in.igotPlt, *mainPart->relaDyn, target->iRelativeRel, *directSym); sym.allocateAux(); symAux.back().pltIdx = symAux[directSym->auxIdx].pltIdx; diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp index 206fb0f53766649eb036e330e2f726df06b91b5b..650bd6cd39006068390ed0acd54c0ec5ee4ee2db 100644 --- a/lld/ELF/SyntheticSections.cpp +++ b/lld/ELF/SyntheticSections.cpp @@ -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/Driver.cpp b/lld/MachO/Driver.cpp index 9edb6b9c60a1fecba8828b620c2ee4da27475066..14c111ce9685c9143597fc19fe145f9378625cb9 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. @@ -1220,53 +1220,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 +1387,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 +1404,8 @@ bool link(ArrayRef<const char *> argsArr, llvm::raw_ostream &stdoutOS, resetOutputSegments(); resetWriter(); InputFile::resetIdCount(); + + objc::doCleanup(); }; ctx->e.logName = args::getFilenameWithoutExe(argsArr[0]); @@ -1979,9 +1948,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..22930d52dd1db2809ca86f8bea078e8eb8c90893 100644 --- a/lld/MachO/InputSection.cpp +++ b/lld/MachO/InputSection.cpp @@ -37,6 +37,44 @@ 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->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(); diff --git a/lld/MachO/InputSection.h b/lld/MachO/InputSection.h index becb01017d633abd308a20012891fe03a858bea9..694bdf734907ba617e87f8350407e2a1db6f91e8 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; }; @@ -302,6 +302,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 { @@ -369,6 +371,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/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..9fbe984e6223ecddc8d0b75c758c0214f4fa48b1 100644 --- a/lld/MachO/ObjC.h +++ b/lld/MachO/ObjC.h @@ -17,14 +17,26 @@ 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 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..0d8ee2a0926be2df54df72f69872aead040243dc 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">, diff --git a/lld/MachO/SyntheticSections.cpp b/lld/MachO/SyntheticSections.cpp index 7ee3261ce3075f70f837dc001360f6f8e78335b8..0afbbd478bb9fd75e14b449d323ac8a5c4d2693c 100644 --- a/lld/MachO/SyntheticSections.cpp +++ b/lld/MachO/SyntheticSections.cpp @@ -793,7 +793,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 +806,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 +835,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; @@ -855,13 +856,13 @@ ConcatInputSection *ObjCSelRefsSection::makeSelRef(StringRef methname) { /*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 +891,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 +941,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, diff --git a/lld/MachO/SyntheticSections.h b/lld/MachO/SyntheticSections.h index 6d85f0aea8e04ced71069a9e98b54ffdfd9f53b3..4586a4a0bf4361f69c06182c22331115a9ffb022 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; }; @@ -813,7 +805,6 @@ struct InStruct { LazyPointerSection *lazyPointers = nullptr; StubsSection *stubs = nullptr; StubHelperSection *stubHelper = nullptr; - ObjCSelRefsSection *objcSelRefs = nullptr; ObjCStubsSection *objcStubs = nullptr; UnwindInfoSection *unwindInfo = nullptr; ObjCImageInfoSection *objCImageInfo = nullptr; diff --git a/lld/MachO/Writer.cpp b/lld/MachO/Writer.cpp index 8f335188e12c7bf92c80edaeb30e8db7c0ec8fa3..a18b5268fd42aac3c98712cd3740e9f5cda76feb 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()) @@ -1359,7 +1359,6 @@ 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>(); 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/ReleaseNotes.rst b/lld/docs/ReleaseNotes.rst index 6f60efd87c975b725ae942631c96568d1f3efa5e..97ed0604891005c0e8bf087f0af88008268a28f8 100644 --- a/lld/docs/ReleaseNotes.rst +++ b/lld/docs/ReleaseNotes.rst @@ -26,6 +26,10 @@ Non-comprehensive list of changes in this release ELF Improvements ---------------- +* ``--compress-sections <section-glib>=[none|zlib|zstd]`` is added to compress + matched output sections without the ``SHF_ALLOC`` flag. + (`#84855 <https://github.com/llvm/llvm-project/pull/84855>`_) + Breaking changes ---------------- diff --git a/lld/docs/ld.lld.1 b/lld/docs/ld.lld.1 index e4d39e47f5c5ab03ef6e4e20124c334b13bba2a1..65e50e349c8cc004b5fd4cd9780edad66eab428a 100644 --- a/lld/docs/ld.lld.1 +++ b/lld/docs/ld.lld.1 @@ -164,6 +164,10 @@ to set the compression level to 6. The compression level is 5. .El .Pp +.It Fl -compress-sections Ns = Ns Ar section-glob=[none|zlib|zstd] +Compress output sections that match the glob and do not have the SHF_ALLOC flag. +This is like a generalized +.Cm --compress-debug-sections. .It Fl -cref Output cross reference table. If .Fl Map @@ -374,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/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/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/compress-sections-err.s b/lld/test/ELF/compress-sections-err.s index 09780380708319c99a848e46f8b682301bc64ce2..1b46aea12e9cd53f47fc1c63f04d63ff8cd4ddb9 100644 --- a/lld/test/ELF/compress-sections-err.s +++ b/lld/test/ELF/compress-sections-err.s @@ -5,8 +5,11 @@ # RUN: ld.lld %t.o --compress-debug-sections=zlib --compress-debug-sections=none -o /dev/null 2>&1 | count 0 # RUN: not ld.lld %t.o --compress-debug-sections=zlib -o /dev/null 2>&1 | \ # RUN: FileCheck %s --implicit-check-not=error: +# RUN: not ld.lld %t.o --compress-sections=foo=zlib -o /dev/null 2>&1 | \ +# RUN: FileCheck %s --check-prefix=CHECK2 --implicit-check-not=error: # CHECK: error: --compress-debug-sections: LLVM was not built with LLVM_ENABLE_ZLIB or did not find zlib at build time +# CHECK2: error: --compress-sections: LLVM was not built with LLVM_ENABLE_ZLIB or did not find zlib at build time .globl _start _start: diff --git a/lld/test/ELF/compress-sections-special.s b/lld/test/ELF/compress-sections-special.s new file mode 100644 index 0000000000000000000000000000000000000000..80c61fe626a436f3dbae06f520730ab9f1bb0259 --- /dev/null +++ b/lld/test/ELF/compress-sections-special.s @@ -0,0 +1,31 @@ +# REQUIRES: x86, zlib + +# RUN: rm -rf %t && mkdir %t && cd %t +# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o a.o +# RUN: ld.lld -pie a.o --compress-sections .strtab=zlib --compress-sections .symtab=zlib -o out +# RUN: llvm-readelf -Ss -x .strtab out 2>&1 | FileCheck %s + +# CHECK: nonalloc0 PROGBITS 0000000000000000 [[#%x,]] [[#%x,]] 00 0 0 1 +# CHECK: .symtab SYMTAB 0000000000000000 [[#%x,]] [[#%x,]] 18 C 12 3 1 +# CHECK-NEXT: .shstrtab STRTAB 0000000000000000 [[#%x,]] [[#%x,]] 00 0 0 1 +# CHECK-NEXT: .strtab STRTAB 0000000000000000 [[#%x,]] [[#%x,]] 00 C 0 0 1 + +## TODO Add compressed SHT_STRTAB/SHT_SYMTAB support to llvm-readelf +# CHECK: warning: {{.*}}: unable to get the string table for the SHT_SYMTAB section: SHT_STRTAB string table section + +# CHECK: Hex dump of section '.strtab': +# CHECK-NEXT: 01000000 00000000 1a000000 00000000 +# CHECK-NEXT: 01000000 00000000 {{.*}} + +# RUN: not ld.lld -shared a.o --compress-sections .dynstr=zlib 2>&1 | FileCheck %s --check-prefix=ERR-ALLOC +# ERR-ALLOC: error: --compress-sections: section '.dynstr' with the SHF_ALLOC flag cannot be compressed + +.globl _start, g0, g1 +_start: +l0: +g0: +g1: + +.section nonalloc0,"" +.quad .text+1 +.quad .text+2 diff --git a/lld/test/ELF/compress-sections.s b/lld/test/ELF/compress-sections.s new file mode 100644 index 0000000000000000000000000000000000000000..59b5408c9624ac7055165be91e6454634493dec7 --- /dev/null +++ b/lld/test/ELF/compress-sections.s @@ -0,0 +1,91 @@ +# REQUIRES: x86, zlib, zstd + +# RUN: rm -rf %t && mkdir %t && cd %t +# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o a.o +# RUN: ld.lld -pie a.o -o out --compress-sections '*0=zlib' --compress-sections '*0=none' --compress-sections 'nomatch=none' +# RUN: llvm-readelf -SrsX out | FileCheck %s --check-prefix=CHECK1 + +# CHECK1: Name Type Address Off Size ES Flg Lk Inf Al +# CHECK1: foo0 PROGBITS [[#%x,FOO0:]] [[#%x,]] [[#%x,]] 00 A 0 0 8 +# CHECK1-NEXT: foo1 PROGBITS [[#%x,FOO1:]] [[#%x,]] [[#%x,]] 00 A 0 0 8 +# CHECK1-NEXT: .text PROGBITS [[#%x,TEXT:]] [[#%x,]] [[#%x,]] 00 AX 0 0 4 +# CHECK1: nonalloc0 PROGBITS 0000000000000000 [[#%x,]] [[#%x,]] 00 0 0 8 +# CHECK1-NEXT: nonalloc1 PROGBITS 0000000000000000 [[#%x,]] [[#%x,]] 00 0 0 8 +# CHECK1-NEXT: .debug_str PROGBITS 0000000000000000 [[#%x,]] [[#%x,]] 01 MS 0 0 1 + +# CHECK1: 0000000000000010 0 NOTYPE LOCAL DEFAULT [[#]] (nonalloc0) sym0 +# CHECK1: 0000000000000008 0 NOTYPE LOCAL DEFAULT [[#]] (nonalloc1) sym1 + +# RUN: ld.lld -pie a.o --compress-sections '*c0=zlib' --compress-sections .debug_str=zstd -o out2 +# RUN: llvm-readelf -SrsX -x nonalloc0 -x .debug_str out2 | FileCheck %s --check-prefix=CHECK2 + +# CHECK2: Name Type Address Off Size ES Flg Lk Inf Al +# CHECK2: foo0 PROGBITS [[#%x,FOO0:]] [[#%x,]] [[#%x,]] 00 A 0 0 8 +# CHECK2-NEXT: foo1 PROGBITS [[#%x,FOO1:]] [[#%x,]] [[#%x,]] 00 A 0 0 8 +# CHECK2-NEXT: .text PROGBITS [[#%x,TEXT:]] [[#%x,]] [[#%x,]] 00 AX 0 0 4 +# CHECK2: nonalloc0 PROGBITS 0000000000000000 [[#%x,]] [[#%x,]] 00 C 0 0 1 +# CHECK2-NEXT: nonalloc1 PROGBITS 0000000000000000 [[#%x,]] [[#%x,]] 00 0 0 8 +# CHECK2-NEXT: .debug_str PROGBITS 0000000000000000 [[#%x,]] [[#%x,]] 01 MSC 0 0 1 + +# CHECK2: 0000000000000010 0 NOTYPE LOCAL DEFAULT [[#]] (nonalloc0) sym0 +# CHECK2: 0000000000000008 0 NOTYPE LOCAL DEFAULT [[#]] (nonalloc1) sym1 + +# CHECK2: Hex dump of section 'nonalloc0': +## zlib with ch_size=0x10 +# CHECK2-NEXT: 01000000 00000000 10000000 00000000 +# CHECK2-NEXT: 01000000 00000000 {{.*}} +# CHECK2: Hex dump of section '.debug_str': +## zstd with ch_size=0x38 +# CHECK2-NEXT: 02000000 00000000 38000000 00000000 +# CHECK2-NEXT: 01000000 00000000 {{.*}} + +## --compress-debug-sections=none takes precedence. +# RUN: ld.lld a.o --compress-debug-sections=none --compress-sections .debug_str=zstd -o out3 +# RUN: llvm-readelf -S out3 | FileCheck %s --check-prefix=CHECK3 + +# CHECK3: .debug_str PROGBITS 0000000000000000 [[#%x,]] [[#%x,]] 01 MS 0 0 1 + +# RUN: not ld.lld a.o --compress-sections '*0=zlib' 2>&1 | \ +# RUN: FileCheck %s --check-prefix=ERR-ALLOC --implicit-check-not=error: +# ERR-ALLOC: error: --compress-sections: section 'foo0' with the SHF_ALLOC flag cannot be compressed + +# RUN: not ld.lld --compress-sections=foo a.o 2>&1 | \ +# RUN: FileCheck %s --check-prefix=ERR1 --implicit-check-not=error: +# ERR1: error: --compress-sections: parse error, not 'section-glob=[none|zlib|zstd]' + +# RUN: not ld.lld --compress-sections 'a[=zlib' a.o 2>&1 | \ +# RUN: FileCheck %s --check-prefix=ERR2 --implicit-check-not=error: +# ERR2: error: --compress-sections: invalid glob pattern, unmatched '[' + +# RUN: not ld.lld a.o --compress-sections='.debug*=zlib-gabi' --compress-sections='.debug*=' 2>&1 | \ +# RUN: FileCheck -check-prefix=ERR3 %s +# ERR3: unknown --compress-sections value: zlib-gabi +# ERR3-NEXT: --compress-sections: parse error, not 'section-glob=[none|zlib|zstd]' + +.globl _start +_start: + ret + +.section foo0,"a" +.balign 8 +.quad .text-. +.quad .text-. +.section foo1,"a" +.balign 8 +.quad .text-. +.quad .text-. +.section nonalloc0,"" +.balign 8 +.quad .text+1 +.quad .text+2 +sym0: +.section nonalloc1,"" +.balign 8 +.quad 42 +sym1: + +.section .debug_str,"MS",@progbits,1 +.Linfo_string0: + .asciz "AAAAAAAAAAAAAAAAAAAAAAAAAAA" +.Linfo_string1: + .asciz "BBBBBBBBBBBBBBBBBBBBBBBBBBB" diff --git a/lld/test/ELF/driver.test b/lld/test/ELF/driver.test index 260be8e8f883bbcb99d6405b158f2139ae78edcb..b8f4584a3267a3581d7ec4244cbd2043a3e7c024 100644 --- a/lld/test/ELF/driver.test +++ b/lld/test/ELF/driver.test @@ -53,12 +53,13 @@ # 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 -# 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 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/compress-sections.s b/lld/test/ELF/linkerscript/compress-sections.s new file mode 100644 index 0000000000000000000000000000000000000000..9b4574a1778c4325789643ddd74a13c50bdc2963 --- /dev/null +++ b/lld/test/ELF/linkerscript/compress-sections.s @@ -0,0 +1,62 @@ +# REQUIRES: x86, zlib + +# 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 -T a.lds a.o --compress-sections nonalloc=zlib --compress-sections str=zlib -o out +# RUN: llvm-readelf -SsXz -p str out | FileCheck %s + +# CHECK: Name Type Address Off Size ES Flg Lk Inf Al +# CHECK: nonalloc PROGBITS 0000000000000000 [[#%x,]] [[#%x,]] 00 C 0 0 1 +# CHECK-NEXT: str PROGBITS 0000000000000000 [[#%x,]] [[#%x,]] 01 MSC 0 0 1 + +# CHECK: 0000000000000000 0 NOTYPE GLOBAL DEFAULT [[#]] (nonalloc) nonalloc_start +# CHECK: 0000000000000023 0 NOTYPE GLOBAL DEFAULT [[#]] (nonalloc) nonalloc_end +# CHECK: String dump of section 'str': +# CHECK-NEXT: [ 0] AAA +# CHECK-NEXT: [ 4] BBB + +## TODO The uncompressed size of 'nonalloc' is dependent on linker script +## commands, which is not handled. We should report an error. +# RUN: ld.lld -T b.lds a.o --compress-sections nonalloc=zlib + +#--- a.s +.globl _start +_start: + ret + +.section nonalloc0,"" +.balign 8 +.quad .text +.quad .text +.section nonalloc1,"" +.balign 8 +.quad 42 + +.section str,"MS",@progbits,1 + .asciz "AAA" + .asciz "BBB" + +#--- a.lds +SECTIONS { + .text : { *(.text) } + c = SIZEOF(.text); + b = c+1; + a = b+1; + nonalloc : { + nonalloc_start = .; +## In general, using data commands is error-prone. This case is correct, though. + *(nonalloc*) QUAD(SIZEOF(.text)) + . += a; + nonalloc_end = .; + } + str : { *(str) } +} + +#--- b.lds +SECTIONS { + nonalloc : { *(nonalloc*) . += a; } + .text : { *(.text) } + a = b+1; + b = c+1; + c = SIZEOF(.text); +} 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/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/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.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/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/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/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/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/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..eb3af9816dc6ca251e41272994551ca32ccd6aa7 100644 --- a/lldb/include/lldb/Core/Progress.h +++ b/lldb/include/lldb/Core/Progress.h @@ -66,7 +66,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 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/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/ConstString.h b/lldb/include/lldb/Utility/ConstString.h index 470a554ca04869dcdafbc90a004c6aa1e6761629..f7f7ec7605eba4fef1e9dd6a79e3ba047d3bab26 100644 --- a/lldb/include/lldb/Utility/ConstString.h +++ b/lldb/include/lldb/Utility/ConstString.h @@ -168,8 +168,8 @@ public: // Implicitly convert \class ConstString instances to \class StringRef. operator llvm::StringRef() const { return GetStringRef(); } - // Implicitly convert \class ConstString instances to \class std::string_view. - operator std::string_view() const { + // Explicitly convert \class ConstString instances to \class std::string_view. + explicit operator std::string_view() const { return std::string_view(m_string, GetLength()); } 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/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/Mangled.cpp b/lldb/source/Core/Mangled.cpp index 23ae3913093faf03e76e74d205e41632a4f5355e..b167c51fdce24717b6f5d43b11088f04b4267fb2 100644 --- a/lldb/source/Core/Mangled.cpp +++ b/lldb/source/Core/Mangled.cpp @@ -125,7 +125,7 @@ void Mangled::SetValue(ConstString name) { } // Local helpers for different demangling implementations. -static char *GetMSVCDemangledStr(std::string_view M) { +static char *GetMSVCDemangledStr(llvm::StringRef M) { char *demangled_cstr = llvm::microsoftDemangle( M, nullptr, nullptr, llvm::MSDemangleFlags( @@ -169,27 +169,29 @@ static char *GetItaniumDemangledStr(const char *M) { return demangled_cstr; } -static char *GetRustV0DemangledStr(std::string_view M) { +static char *GetRustV0DemangledStr(llvm::StringRef M) { char *demangled_cstr = llvm::rustDemangle(M); if (Log *log = GetLog(LLDBLog::Demangle)) { if (demangled_cstr && demangled_cstr[0]) LLDB_LOG(log, "demangled rustv0: {0} -> \"{1}\"", M, demangled_cstr); else - LLDB_LOG(log, "demangled rustv0: {0} -> error: failed to demangle", M); + LLDB_LOG(log, "demangled rustv0: {0} -> error: failed to demangle", + static_cast<std::string_view>(M)); } return demangled_cstr; } -static char *GetDLangDemangledStr(std::string_view M) { +static char *GetDLangDemangledStr(llvm::StringRef M) { char *demangled_cstr = llvm::dlangDemangle(M); if (Log *log = GetLog(LLDBLog::Demangle)) { if (demangled_cstr && demangled_cstr[0]) LLDB_LOG(log, "demangled dlang: {0} -> \"{1}\"", M, demangled_cstr); else - LLDB_LOG(log, "demangled dlang: {0} -> error: failed to demangle", M); + LLDB_LOG(log, "demangled dlang: {0} -> error: failed to demangle", + static_cast<std::string_view>(M)); } return demangled_cstr; 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..245cdc7ae5c2da19b6a2d4f59e85c7e073133b75 --- /dev/null +++ b/lldb/source/Host/common/Alarm.cpp @@ -0,0 +1,216 @@ +//===-- 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. + 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) { + 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) + entry.callback(); + } + continue; + } + + // 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; + } + } + 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/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..bcb04fae15bd46e5231a435622d5adf7bbf7448b 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: 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/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/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..ebcc3bc99a801f55ab943ce931d07d47f6e821b9 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: @@ -4755,6 +4757,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: @@ -5088,6 +5091,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: 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/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..3af62f52d575465509da4fdf552a746618f5a12d 100644 --- a/lldb/source/Target/StackFrame.cpp +++ b/lldb/source/Target/StackFrame.cpp @@ -1922,7 +1922,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/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/expression/completion/Makefile b/lldb/test/API/commands/expression/completion/Makefile index 020dce7c31d11de3c62810651ab508a3f8a7da2c..9882622b2189ea4a719d2606aaeeb82de3a10426 100644 --- a/lldb/test/API/commands/expression/completion/Makefile +++ b/lldb/test/API/commands/expression/completion/Makefile @@ -1,3 +1,4 @@ CXX_SOURCES := main.cpp other.cpp +CXXFLAGS += -isystem $(SRCDIR)/sys include Makefile.rules diff --git a/lldb/test/API/commands/expression/completion/TestExprCompletion.py b/lldb/test/API/commands/expression/completion/TestExprCompletion.py index c6a1e3c0f42275faa6d8f0810673af0c2cfcea02..022b9436ee8ea6de61209eddd7b6ac93b663dc5f 100644 --- a/lldb/test/API/commands/expression/completion/TestExprCompletion.py +++ b/lldb/test/API/commands/expression/completion/TestExprCompletion.py @@ -246,6 +246,11 @@ class CommandLineExprCompletionTestCase(TestBase): "expr some_expr.Self(). FooNoArgs", "expr some_expr.Self(). FooNoArgsBar()" ) + self.complete_from_to("expr myVec.__f", "expr myVec.__func()") + self.complete_from_to("expr myVec._F", "expr myVec._Func()") + self.complete_from_to("expr myVec.__m", "expr myVec.__mem") + self.complete_from_to("expr myVec._M", "expr myVec._Mem") + def test_expr_completion_with_descriptions(self): self.build() self.main_source = "main.cpp" diff --git a/lldb/test/API/commands/expression/completion/main.cpp b/lldb/test/API/commands/expression/completion/main.cpp index 908bebbebff5684086fc57785943f9e079367995..5e03805a7a4d5c13327159bdd47dcb32012e951d 100644 --- a/lldb/test/API/commands/expression/completion/main.cpp +++ b/lldb/test/API/commands/expression/completion/main.cpp @@ -1,3 +1,5 @@ +#include <reserved.h> + namespace LongNamespaceName { class NestedClass { long m; }; } // Defined in other.cpp, we only have a forward declaration here. @@ -31,5 +33,8 @@ int main() some_expr.FooNumbersBar1(); Expr::StaticMemberMethodBar(); ForwardDecl *fwd_decl_ptr = &fwd_decl; + MyVec myVec; + myVec.__func(); + myVec._Func(); return 0; // Break here } diff --git a/lldb/test/API/commands/expression/completion/sys/reserved.h b/lldb/test/API/commands/expression/completion/sys/reserved.h new file mode 100644 index 0000000000000000000000000000000000000000..0ce10ebec62bfda3593b711e62c43a790e1b5a00 --- /dev/null +++ b/lldb/test/API/commands/expression/completion/sys/reserved.h @@ -0,0 +1,8 @@ +class MyVec { + int __mem; + int _Mem; + +public: + void __func() {} + void _Func() {} +}; 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/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/tools/debugserver/source/MacOSX/MachProcess.mm b/lldb/tools/debugserver/source/MacOSX/MachProcess.mm index 87bdbf835bfd1017e10a3649559dbf4a2988b6f1..70b4564a027b1b85f7eb26afda3c7957a6f644f2 100644 --- a/lldb/tools/debugserver/source/MacOSX/MachProcess.mm +++ b/lldb/tools/debugserver/source/MacOSX/MachProcess.mm @@ -472,6 +472,8 @@ FBSCreateOptionsDictionary(const char *app_bundle_path, // And there are some other options at the top level in this dictionary: [options setObject:[NSNumber numberWithBool:YES] forKey:FBSOpenApplicationOptionKeyUnlockDevice]; + [options setObject:[NSNumber numberWithBool:YES] + forKey:FBSOpenApplicationOptionKeyPromptUnlockDevice]; // We have to get the "sequence ID & UUID" for this app bundle path and send // them to FBS: diff --git a/lldb/tools/debugserver/source/RNBSocket.cpp b/lldb/tools/debugserver/source/RNBSocket.cpp index 1282ea221625a0bde29e97564b15d794a096abfb..fc55dbf2e1f1b0f5d9834b344fd6ca12d0e953d7 100644 --- a/lldb/tools/debugserver/source/RNBSocket.cpp +++ b/lldb/tools/debugserver/source/RNBSocket.cpp @@ -120,8 +120,13 @@ rnb_err_t RNBSocket::Listen(const char *listen_host, uint16_t port, while (!accept_connection) { struct kevent event_list[4]; - int num_events = - kevent(queue_id, events.data(), events.size(), event_list, 4, NULL); + int num_events; + do { + errno = 0; + num_events = + kevent(queue_id, events.data(), events.size(), event_list, 4, NULL); + } while (num_events == -1 && + (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR)); if (num_events < 0) { err.SetError(errno, DNBError::MachKernel); @@ -291,7 +296,12 @@ rnb_err_t RNBSocket::Read(std::string &p) { // DNBLogThreadedIf(LOG_RNB_COMM, "%8u RNBSocket::%s calling read()", // (uint32_t)m_timer.ElapsedMicroSeconds(true), __FUNCTION__); DNBError err; - ssize_t bytesread = read(m_fd, buf, sizeof(buf)); + ssize_t bytesread; + do { + errno = 0; + bytesread = read(m_fd, buf, sizeof(buf)); + } while (bytesread == -1 && + (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR)); if (bytesread <= 0) err.SetError(errno, DNBError::POSIX); else 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 6a2ea8c4a41b1cd02d45dae694aecfc7d6620c03..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, @@ -527,7 +527,6 @@ TEST_F(SymbolFilePDBTests, TestTypedefs) { SymbolFilePDB *symfile = static_cast<SymbolFilePDB *>(module->GetSymbolFile()); llvm::pdb::IPDBSession &session = symfile->GetPDBSession(); - TypeMap results; const char *TypedefsToCheck[] = {"ClassTypedef", "NSClassTypedef", "FuncPointerTypedef", 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/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 f5f37d9e8a3b0367321e80957393a80ae94fb087..6e6d6b15714809ed01195e506f72fa3d43429c4b 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,10 +1449,20 @@ 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-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: @@ -1540,6 +1557,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: @@ -3917,6 +3953,11 @@ same *vendor-name*. If omitted, "normal" is assumed. + ".max_num_work_groups_{x,y,z}" integer The max number of + launched work-groups + in the X, Y, and Z + dimensions. Each number + must be >=1. =================================== ============== ========= ================================ .. 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..54622cc61fdfdab311fbb188183073ade82d8557 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,6 +1953,315 @@ 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 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/GettingStarted.rst b/llvm/docs/GettingStarted.rst index 705f6427d9ed5306eceebf3c95f54469928b1f19..7ecef78c405b6f2e6bad6bd2e7a37331477f919c 100644 --- a/llvm/docs/GettingStarted.rst +++ b/llvm/docs/GettingStarted.rst @@ -42,10 +42,14 @@ Getting the Source Code and Building LLVM ``git clone --depth 1 https://github.com/llvm/llvm-project.git`` - * You are likely only interested in the main branch moving forward, if - you don't want `git fetch` (or `git pull`) to download user branches, use: + * You are likely not interested in the user branches in the repo (used for + stacked pull-requests and reverts), you can filter them from your + `git fetch` (or `git pull`) with this configuration: - ``sed 's#fetch = +refs/heads/\*:refs/remotes/origin/\*#fetch = +refs/heads/main:refs/remotes/origin/main#' -i llvm-project/.git/config`` +.. code-block:: console + + git config --add remote.origin.fetch '^refs/heads/users/*' + git config --add remote.origin.fetch '^refs/heads/revert-*' #. Configure and build LLVM and Clang: diff --git a/llvm/docs/GlobalISel/GenericOpcode.rst b/llvm/docs/GlobalISel/GenericOpcode.rst index f9f9e1186460eeb8772b08d4e77867b2ff6dfa5e..cae2c21b80d7e7e4770b533a340751c3d37aa798 100644 --- a/llvm/docs/GlobalISel/GenericOpcode.rst +++ b/llvm/docs/GlobalISel/GenericOpcode.rst @@ -607,6 +607,17 @@ See the LLVM LangRef entry on '``llvm.lround.*'`` for details on behaviour. Vector Specific Operations -------------------------- +G_VSCALE +^^^^^^^^ + +Puts the value of the runtime ``vscale`` multiplied by the value in the source +operand into the destination register. This can be useful in determining the +actual runtime number of elements in a vector. + +.. code-block:: + + %0:_(s32) = G_VSCALE 4 + G_INSERT_SUBVECTOR ^^^^^^^^^^^^^^^^^^ @@ -779,11 +790,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. @@ -922,6 +939,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/LangRef.rst b/llvm/docs/LangRef.rst index 77ec72f176d6edcd4654ea642146ccb3643182c8..030b76935c7b4e7cf520711167081a929228b7cd 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. @@ -7365,7 +7365,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 +11049,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 +11197,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 @@ -13577,12 +13577,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 +13603,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 +14574,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 +17713,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 +18037,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 +18741,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 +22026,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 +24442,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 +26584,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 +26926,8 @@ Arguments: The argument should be an MDTuple containing any number of MDStrings. +.. _llvm.trap: + '``llvm.trap``' Intrinsic ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -26896,6 +26955,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 +26984,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 +27013,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 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -27553,12 +27616,12 @@ in example below: .. code-block:: text %cond = call i1 @llvm.experimental.widenable.condition() - br i1 %cond, label %solution_1, label %solution_2 + br i1 %cond, label %fast_path, label %slow_path - label %fast_path: + fast_path: ; Apply memory-consuming but fast solution for a task. - label %slow_path: + slow_path: ; Cheap in memory but slow solution. Whether the result of intrinsic's call is `true` or `false`, @@ -27891,7 +27954,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. @@ -27967,7 +28030,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. @@ -28046,7 +28109,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..01ecbdba5060b081d5fd5343c190410a93d70d05 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 ----------------------------- @@ -106,6 +108,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 +134,18 @@ 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`` + Changes to the CodeGen infrastructure ------------------------------------- @@ -153,10 +168,17 @@ 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. + Changes to LLDB --------------------------------- diff --git a/llvm/docs/RemoveDIsDebugInfo.md b/llvm/docs/RemoveDIsDebugInfo.md index a9857733c70d30728389d76ec16f80065247f267..a2f1e173d9d9350674f56ae238e7aab4fc1555ee 100644 --- a/llvm/docs/RemoveDIsDebugInfo.md +++ b/llvm/docs/RemoveDIsDebugInfo.md @@ -24,12 +24,33 @@ 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. +``` + # 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 +61,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 +82,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 +124,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/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..f56a6c961aad74e87e738ef13aba1c2e6903a8e6 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. * @@ -2730,6 +2748,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. * diff --git a/llvm/include/llvm-c/DebugInfo.h b/llvm/include/llvm-c/DebugInfo.h index 5924294708cc354e769b87f1a63edf88f514390f..b23ff63c862f8424cf34856b474fc83982a0d244 100644 --- a/llvm/include/llvm-c/DebugInfo.h +++ b/llvm/include/llvm-c/DebugInfo.h @@ -1248,7 +1248,24 @@ LLVMMetadataRef LLVMDIBuilderCreateTempGlobalVariableFwdDecl( unsigned LineNo, LLVMMetadataRef Ty, LLVMBool LocalToUnit, LLVMMetadataRef Decl, uint32_t AlignInBits); +/* + * 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. + * \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. + */ +LLVMValueRef +LLVMDIBuilderInsertDeclareBefore(LLVMDIBuilderRef Builder, LLVMValueRef Storage, + LLVMMetadataRef VarInfo, LLVMMetadataRef Expr, + LLVMMetadataRef DebugLoc, LLVMValueRef Instr); /** + * Soon to be deprecated. + * Only use in "old debug mode" (LLVMIsNewDbgFormat() 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,9 +1274,25 @@ 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" (LLVMIsNewDbgFormat() 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 llvm.dbg.declare intrinsic call at the end of the given basic @@ -1275,6 +1308,42 @@ LLVMValueRef LLVMDIBuilderInsertDeclareBefore( LLVMValueRef LLVMDIBuilderInsertDeclareAtEnd( LLVMDIBuilderRef Builder, LLVMValueRef Storage, LLVMMetadataRef VarInfo, LLVMMetadataRef Expr, LLVMMetadataRef DebugLoc, LLVMBasicBlockRef Block); +/** + * Soon to be deprecated. + * Only use in "old debug mode" (LLVMIsNewDbgFormat() 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. + * \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. + */ +LLVMValueRef LLVMDIBuilderInsertDeclareIntrinsicAtEnd( + LLVMDIBuilderRef Builder, LLVMValueRef Storage, LLVMMetadataRef VarInfo, + LLVMMetadataRef Expr, LLVMMetadataRef DebugLoc, LLVMBasicBlockRef Block); +/** + * Soon to be deprecated. + * Only use in "new debug mode" (LLVMIsNewDbgFormat() 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 llvm.dbg.value intrinsic call before the given instruction. @@ -1285,12 +1354,42 @@ 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 +LLVMDIBuilderInsertDbgValueBefore(LLVMDIBuilderRef Builder, LLVMValueRef Val, + LLVMMetadataRef VarInfo, LLVMMetadataRef Expr, + LLVMMetadataRef DebugLoc, LLVMValueRef Instr); +/** + * Soon to be deprecated. + * Only use in "old debug mode" (Module::IsNewDbgInfoFormat 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. + * \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. + */ +LLVMValueRef LLVMDIBuilderInsertDbgValueIntrinsicBefore( + LLVMDIBuilderRef Builder, LLVMValueRef Val, LLVMMetadataRef VarInfo, + LLVMMetadataRef Expr, LLVMMetadataRef DebugLoc, LLVMValueRef Instr); +/** + * Soon to be deprecated. + * Only use in "new debug mode" (Module::IsNewDbgInfoFormat 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 llvm.dbg.value intrinsic call at the end of the given basic @@ -1303,12 +1402,45 @@ 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); +LLVMValueRef LLVMDIBuilderInsertDbgValueAtEnd( + LLVMDIBuilderRef Builder, LLVMValueRef Val, LLVMMetadataRef VarInfo, + LLVMMetadataRef Expr, LLVMMetadataRef DebugLoc, LLVMBasicBlockRef Block); +/** + * Soon to be deprecated. + * Only use in "old debug mode" (Module::IsNewDbgInfoFormat 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" (Module::IsNewDbgInfoFormat 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. + * \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 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..1abea9eb24a3c45fa847334934cb8bfa0caf16ac 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,18 @@ 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); + /// 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/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/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..7c47d3c2338a877eb14ca30bd2cd84edb526c7c4 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); 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/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/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..4018ef03f960cae1e883a42563c7e9de86091319 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 @@ -624,6 +625,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..9e8fc5d635c50a4433f8517032267419ac11f5e9 100644 --- a/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h @@ -696,10 +696,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 +806,15 @@ 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); + private: /// Checks for legality of an indexed variant of \p LdSt. bool isIndexedLoadStoreLegal(GLoadStore &LdSt) const; @@ -919,6 +918,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..261cfcf504d5fef8be01772d1e803715ababca5e 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(); @@ -359,6 +359,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 +431,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 { 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/MachineIRBuilder.h b/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h index 4732eaf4ee27c5bcf961e1a6eb1704358eb67625..3ba036ae713f64bba0b5d9f106f8b500c34f6d33 100644 --- a/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h @@ -1143,6 +1143,28 @@ public: MachineInstrBuilder buildInsert(const DstOp &Res, const SrcOp &Src, const SrcOp &Op, unsigned Index); + /// 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, unsigned 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 ConstantInt &MinElts); + /// Build and insert a G_INTRINSIC instruction. /// /// There are four different opcodes based on combinations of whether the @@ -2091,6 +2113,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/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..c2bff27944939889af3316b3a88df6e3203de0ce 100644 --- a/llvm/include/llvm/CodeGen/MachineFunction.h +++ b/llvm/include/llvm/CodeGen/MachineFunction.h @@ -1026,18 +1026,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 +1055,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 +1074,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 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..3faffe5c4cab29ce08efa0e4d0a3e140bd29a9d8 100644 --- a/llvm/include/llvm/CodeGen/MachinePassManager.h +++ b/llvm/include/llvm/CodeGen/MachinePassManager.h @@ -56,7 +56,7 @@ struct MachinePassConcept }; template <typename PassT> struct MachinePassModel : MachinePassConcept { - explicit MachinePassModel(PassT Pass) : Pass(std::move(Pass)) {} + 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) {} @@ -72,6 +72,7 @@ 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); 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/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..574c63552ce0ae109388eb1b1e1f315a0540e7af 100644 --- a/llvm/include/llvm/CodeGen/SelectionDAG.h +++ b/llvm/include/llvm/CodeGen/SelectionDAG.h @@ -883,7 +883,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 +1299,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 +1307,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, 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..59fad88f91b1d1f7119e0b460c586faa3a9ca60f 100644 --- a/llvm/include/llvm/CodeGen/TargetLowering.h +++ b/llvm/include/llvm/CodeGen/TargetLowering.h @@ -2722,17 +2722,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 +2772,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 { 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/LVELFReader.h b/llvm/include/llvm/DebugInfo/LogicalView/Readers/LVDWARFReader.h similarity index 88% rename from llvm/include/llvm/DebugInfo/LogicalView/Readers/LVELFReader.h rename to llvm/include/llvm/DebugInfo/LogicalView/Readers/LVDWARFReader.h index 0837b886a273a62a31114f255126565472628820..22e804a459f873804ca8fbbf49dd18901666d96e 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 @@ -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/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/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..0eea4cdccca5bb19cf122a231319c1604af91eb8 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())) ^ + 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/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..e50cd1f1c73efae664a9bf9df9ebc6f5433c6fa3 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" @@ -1195,31 +1196,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 +1290,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/IRBuilder.h b/llvm/include/llvm/IR/IRBuilder.h index f2922311097e9b236fb04274ee7d02c065b6bece..c07ffea71151151d6550ef791f80e40409813e88 100644 --- a/llvm/include/llvm/IR/IRBuilder.h +++ b/llvm/include/llvm/IR/IRBuilder.h @@ -962,9 +962,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 +983,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 +993,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 +1003,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); } 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..d2b33fe9c651a17616b2e6798fee9179d3636f94 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; @@ -1057,6 +1058,17 @@ public: static CmpInst *Create(OtherOps Op, Predicate predicate, 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 { return static_cast<OtherOps>(Instruction::getOpcode()); @@ -1917,7 +1929,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 +2166,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/Intrinsics.td b/llvm/include/llvm/IR/Intrinsics.td index 144298fd7c0162e34de73bf17edf58e1a25658ac..091f9b381079893eab4128fb7d480c5beab08fec 100644 --- a/llvm/include/llvm/IR/Intrinsics.td +++ b/llvm/include/llvm/IR/Intrinsics.td @@ -1528,6 +1528,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 -------------------------===// // diff --git a/llvm/include/llvm/IR/IntrinsicsAMDGPU.td b/llvm/include/llvm/IR/IntrinsicsAMDGPU.td index 051e603c0819d201258e71b0a6e2f7e480bb20c8..fff03dee20a18bd2bef912a0da097e795feeac0d 100644 --- a/llvm/include/llvm/IR/IntrinsicsAMDGPU.td +++ b/llvm/include/llvm/IR/IntrinsicsAMDGPU.td @@ -2653,6 +2653,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 +2670,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 +2690,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 +2723,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 +2748,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>; @@ -3012,6 +3016,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 +3037,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 +3049,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 +3061,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 +3075,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 +3084,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 +3092,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..1164b241ba7b0d215f031ff91c3cbc1e4c72458e 100644 --- a/llvm/include/llvm/IR/IntrinsicsDirectX.td +++ b/llvm/include/llvm/IR/IntrinsicsDirectX.td @@ -21,20 +21,33 @@ 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 : Intrinsic<[LLVMVectorElementType<0>], - [llvm_anyvector_ty, LLVMScalarOrSameVectorWidth<0, 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/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..ec8b809d40bfbcf788a66171a67e1fde6620eb28 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) diff --git a/llvm/include/llvm/IR/PatternMatch.h b/llvm/include/llvm/IR/PatternMatch.h index 487ae170210de91ce02df23812015b5606b092ea..04feb1fd17fd622e69703bfe4dd4a513c15fca23 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); } }; @@ -1303,6 +1319,26 @@ 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. // 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/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/COFFImportFile.h b/llvm/include/llvm/Object/COFFImportFile.h index 402ded0d64fef229a091df8ee7b075cc1141f36c..7268faa87eb70baf829fd25353fd0ec88b9307af 100644 --- a/llvm/include/llvm/Object/COFFImportFile.h +++ b/llvm/include/llvm/Object/COFFImportFile.h @@ -26,6 +26,12 @@ namespace llvm { namespace object { +constexpr std::string_view ImportDescriptorPrefix = "__IMPORT_DESCRIPTOR_"; +constexpr std::string_view NullImportDescriptorSymbolName = + "__NULL_IMPORT_DESCRIPTOR"; +constexpr std::string_view NullThunkDataPrefix = "\x7f"; +constexpr std::string_view NullThunkDataSuffix = "_NULL_THUNK_DATA"; + class COFFImportFile : public SymbolicFile { private: enum SymbolIndex { ImpSymbol, ThunkSymbol, ECAuxSymbol, ECThunkSymbol }; 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..f57a7ab8882ad2e26a7a4478c8e626b4ac9124cb 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::TargetEndianness)) + return E; + break; } return Error::success(); } 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/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/MemProf.h b/llvm/include/llvm/ProfileData/MemProf.h index 37c19094bc2a630bc1de0ce152098144a5d377c1..75ea0e49d453731edf2061c89210202e188aa871 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" @@ -252,18 +253,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 +631,16 @@ 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 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/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 3dade14f043b60a21dc38200da711df09af345f6..5765926d6d93d36e8495255d8f7efb3f692cda51 100644 --- a/llvm/include/llvm/Support/TargetOpcodes.def +++ b/llvm/include/llvm/Support/TargetOpcodes.def @@ -727,6 +727,9 @@ HANDLE_TARGET_OPCODE(G_BR) /// Generic branch to jump table entry. HANDLE_TARGET_OPCODE(G_BRJT) +/// Generic vscale. +HANDLE_TARGET_OPCODE(G_VSCALE) + /// Generic insert subvector. HANDLE_TARGET_OPCODE(G_INSERT_SUBVECTOR) @@ -834,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 8dc84fb0ba0524f149248917a51610fcd47fcc9c..d0f471eb29b6fdc726b9200537ffeb577f38361b 100644 --- a/llvm/include/llvm/Target/GenericOpcodes.td +++ b/llvm/include/llvm/Target/GenericOpcodes.td @@ -1289,6 +1289,15 @@ def G_MERGE_VALUES : GenericInstruction { let variadicOpsType = type1; } +// Generic vscale. +// Puts the value of the runtime vscale multiplied by the value in the source +// operand into the destination register. +def G_VSCALE : GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins unknown:$src); + let hasSideEffects = false; +} + /// Create a vector from multiple scalar registers. No implicit /// conversion is performed (i.e. the result element type must be the /// same as all source operands) @@ -1566,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..6980cbd04aeb1c7f9118c9d39eff8e16665cf91f 100644 --- a/llvm/include/llvm/Target/GlobalISel/Combine.td +++ b/llvm/include/llvm/Target/GlobalISel/Combine.td @@ -264,7 +264,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, @@ -1090,12 +1090,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 +1285,12 @@ 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}); }])>; + // Combines concat operations def concat_matchinfo : GIDefMatchData<"SmallVector<Register>">; def combine_concat_vector : GICombineRule< @@ -1326,7 +1326,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<[ @@ -1356,7 +1356,7 @@ def constant_fold_binops : GICombineGroup<[constant_fold_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, + 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 +1373,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..cb1c0ed2513d45ca122e0bab9b13b1762c0b9410 100644 --- a/llvm/include/llvm/Target/Target.td +++ b/llvm/include/llvm/Target/Target.td @@ -697,7 +697,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 +960,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 +1575,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 +1890,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/Record.h b/llvm/include/llvm/TextAPI/Record.h index 98639b064eaadda753b55de5736bbfd06bcbaf84..ef152ce433877c8781b6ff235f24222d3b1b7398 100644 --- a/llvm/include/llvm/TextAPI/Record.h +++ b/llvm/include/llvm/TextAPI/Record.h @@ -51,7 +51,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 +80,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 +93,7 @@ protected: StringRef Name; RecordLinkage Linkage; SymbolFlags Flags; + bool Verified; friend class RecordsSlice; }; 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/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..158c358a9e4618c09b6b4d3207e1010a3f904b4a 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 *getAndroidSanitizerSlotPtr(IRBuilder<> &IRB); } // 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/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/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/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/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/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..797665cf06c8755f29fb8ce772bf1583e60b4542 100644 --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -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)) { diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp index 2e0f5ba82220c9c26e05756276832b76eec6d894..f0be021668afa7d9c2e4b55e4a6639e7105f21c3 100644 --- a/llvm/lib/AsmParser/LLParser.cpp +++ b/llvm/lib/AsmParser/LLParser.cpp @@ -4169,11 +4169,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 +4205,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 +4215,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 +4255,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 +4332,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 +4342,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 +5207,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 +5226,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 +6581,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 +6592,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 +6607,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 +6672,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; } //===----------------------------------------------------------------------===// 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..6ee93f17792b4f6c774a4d3742e17952a369a062 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)) @@ -6398,6 +6425,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 +6790,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..a8b69f89e7deffc1820c5c8ab3b73aa1f6525a8c 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 @@ -1825,6 +1829,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 +2751,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 +3522,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 +3852,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(); } 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/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/CodeGenPrepare.cpp b/llvm/lib/CodeGen/CodeGenPrepare.cpp index 59a0c64d3c9f2df93b2417c26eb4741338427851..9f99bb7e693f7e53f3f358dc4b66e4144e04e240 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()); @@ -2946,7 +2982,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 +2994,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 +3019,7 @@ class TypePromotionTransaction { Inst->insertBefore(*Point.BB, Position); } - Inst->getParent()->reinsertInstInDbgRecords(Inst, BeforeDPValue); + Inst->getParent()->reinsertInstInDbgRecords(Inst, BeforeDbgRecord); } }; @@ -3187,7 +3223,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 +3244,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 +3261,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 +4153,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 +6467,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 +6488,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 +7117,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 +8275,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 +8385,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 +8417,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 +8541,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 +8568,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 +8583,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 +8654,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/ExpandLargeFpConvert.cpp b/llvm/lib/CodeGen/ExpandLargeFpConvert.cpp index 78ad2a25d0e47a9e793d04b51c392c60bc166c0e..308f13c19f7564defbafb77044bc58f5bf6d9ef0 100644 --- a/llvm/lib/CodeGen/ExpandLargeFpConvert.cpp +++ b/llvm/lib/CodeGen/ExpandLargeFpConvert.cpp @@ -375,7 +375,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/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..2a521b6b068af75e0ae11729ea386983485946e1 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; @@ -891,7 +893,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. @@ -1490,7 +1492,7 @@ void CombinerHelper::applyOptBrCondByInvertingCond(MachineInstr &MI, Observer.changedInstr(*BrCond); } - + bool CombinerHelper::tryEmitMemcpyInline(MachineInstr &MI) { MachineIRBuilder HelperBuilder(MI); GISelObserverWrapper DummyObserver; @@ -4936,24 +4938,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) @@ -6354,6 +6338,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 +6932,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/GISelKnownBits.cpp b/llvm/lib/CodeGen/GlobalISel/GISelKnownBits.cpp index 099bf45b2734cbaa18b1c1bf9e2a4ad6ab257883..2e2cc9a95bd95c74a27d6329d7870d169cd2e9a2 100644 --- a/llvm/lib/CodeGen/GlobalISel/GISelKnownBits.cpp +++ b/llvm/lib/CodeGen/GlobalISel/GISelKnownBits.cpp @@ -415,7 +415,8 @@ void GISelKnownBits::computeKnownBitsImpl(Register R, KnownBits &Known, if (DstTy.isVector()) break; // Everything above the retrieved bits is zero - Known.Zero.setBitsFrom((*MI.memoperands_begin())->getSizeInBits()); + Known.Zero.setBitsFrom( + (*MI.memoperands_begin())->getSizeInBits().getValue()); break; } case TargetOpcode::G_ASHR: { @@ -666,7 +667,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 +676,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..ef95ceec18a171723cf96721c545146649b31f28 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); @@ -1770,6 +1771,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 +2100,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 +2485,11 @@ 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::amdgcn_cs_chain: return translateCallBase(CI, MIRBuilder); case Intrinsic::fptrunc_round: { @@ -2474,12 +2555,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 +2629,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 +2754,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 +3062,7 @@ bool IRTranslator::translateUnreachable(const User &U, MachineIRBuilder &MIRBuil } } - MIRBuilder.buildIntrinsic(Intrinsic::trap, ArrayRef<Register>()); + MIRBuilder.buildTrap(); return true; } @@ -3278,25 +3391,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..1b25da8833e4fba5800ab63aeeea31b77a68b1bd 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()); @@ -4456,7 +4456,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 +5411,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: @@ -7852,7 +7855,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 +8215,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/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 9b12d443c96e986d09bd94bfe4cb7210fc3ee1d6..f7aaa0f02efcb313e85bc63b0ec53ca7eafd538b 100644 --- a/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp +++ b/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp @@ -793,6 +793,24 @@ MachineInstrBuilder MachineIRBuilder::buildInsert(const DstOp &Res, return buildInstr(TargetOpcode::G_INSERT, Res, {Src, Op, uint64_t(Index)}); } +MachineInstrBuilder MachineIRBuilder::buildVScale(const DstOp &Res, + unsigned MinElts) { + + auto IntN = IntegerType::get(getMF().getFunction().getContext(), + Res.getLLTTy(*getMRI()).getScalarSizeInBits()); + ConstantInt *CI = ConstantInt::get(IntN, MinElts); + return buildVScale(Res, *CI); +} + +MachineInstrBuilder MachineIRBuilder::buildVScale(const DstOp &Res, + const ConstantInt &MinElts) { + auto VScale = buildInstr(TargetOpcode::G_VSCALE); + VScale->setDebugLoc(DebugLoc()); + Res.addDefToMIB(*getMRI(), VScale); + VScale.addCImm(&MinElts); + return VScale; +} + static unsigned getIntrinsicOpcode(bool HasSideEffects, bool IsConvergent) { if (HasSideEffects && IsConvergent) return TargetOpcode::G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS; 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..09d282d12c5fb11e657edef44130d9ac8969aa29 100644 --- a/llvm/lib/CodeGen/IntrinsicLowering.cpp +++ b/llvm/lib/CodeGen/IntrinsicLowering.cpp @@ -472,7 +472,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..5caf20add2a11ef06d862f356a4e6d0dc9aa9bd1 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(); } diff --git a/llvm/lib/CodeGen/MIRParser/MIParser.cpp b/llvm/lib/CodeGen/MIRParser/MIParser.cpp index d41fc97cb806037c617b4e2f8885e16538727e54..691c60d22724f36290cc7d3389090bb5666c02d9 100644 --- a/llvm/lib/CodeGen/MIRParser/MIParser.cpp +++ b/llvm/lib/CodeGen/MIRParser/MIParser.cpp @@ -1919,10 +1919,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 +1983,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/MIRPrinter.cpp b/llvm/lib/CodeGen/MIRPrinter.cpp index 4ed44d1c06f48c332d7a24d38d9b18c8faf51d04..8efe67a9a72be6a0b2a629c2e4a5238cd13a912b 100644 --- a/llvm/lib/CodeGen/MIRPrinter.cpp +++ b/llvm/lib/CodeGen/MIRPrinter.cpp @@ -982,7 +982,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 +996,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/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..8102bb971ba66e3db20d331a1bd9403f01eef138 100644 --- a/llvm/lib/CodeGen/MachineInstr.cpp +++ b/llvm/lib/CodeGen/MachineInstr.cpp @@ -1302,10 +1302,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 +1322,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 +1341,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, @@ -2357,15 +2374,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 +2392,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 +2411,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..cbeb02a7255210c1bc5953a21176b73bdbf4874e 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); @@ -3715,7 +3721,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 } @@ -3891,6 +3897,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 +3979,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 +4070,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 +4085,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 +4101,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 90cbf097370de214b11f5ac69e33e2e92f3035f6..9a1498d4070ed2e3e6e97a1d783d7c2d3d76e87b 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); } @@ -1613,6 +1616,17 @@ void MachineVerifier::verifyPreISelGenericInstruction(const MachineInstr *MI) { report("G_BSWAP size must be a multiple of 16 bits", MI); break; } + case TargetOpcode::G_VSCALE: { + if (!MI->getOperand(1).isCImm()) { + report("G_VSCALE operand must be cimm", MI); + break; + } + if (MI->getOperand(1).getCImm()->isZero()) { + report("G_VSCALE immediate cannot be zero", MI); + break; + } + break; + } case TargetOpcode::G_INSERT_SUBVECTOR: { const MachineOperand &Src0Op = MI->getOperand(1); if (!Src0Op.isReg()) { @@ -1853,6 +1867,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()); @@ -3683,6 +3708,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; } @@ -3698,6 +3726,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/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 5476ef87971436aab9d4f092db697cae8d13a821..05b4ce3aaa2cae687d50052d10862792b0a56a1c 100644 --- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -38,6 +38,7 @@ #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineMemOperand.h" #include "llvm/CodeGen/RuntimeLibcalls.h" +#include "llvm/CodeGen/SDPatternMatch.h" #include "llvm/CodeGen/SelectionDAG.h" #include "llvm/CodeGen/SelectionDAGAddressAnalysis.h" #include "llvm/CodeGen/SelectionDAGNodes.h" @@ -79,6 +80,7 @@ #include "MatchContext.h" using namespace llvm; +using namespace llvm::SDPatternMatch; #define DEBUG_TYPE "dagcombine" @@ -595,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, @@ -2527,6 +2529,31 @@ static SDValue foldAddSubBoolOfMaskedVal(SDNode *N, SelectionDAG &DAG) { return DAG.getNode(IsAdd ? ISD::SUB : ISD::ADD, DL, VT, C1, LowBit); } +// Attempt to form avgceil(A, B) from (A | B) - ((A ^ B) >> 1) +static SDValue combineFixedwidthToAVGCEIL(SDNode *N, SelectionDAG &DAG) { + const TargetLowering &TLI = DAG.getTargetLoweringInfo(); + SDValue N0 = N->getOperand(0); + EVT VT = N0.getValueType(); + SDLoc DL(N); + SDValue A, B; + + if (TLI.isOperationLegal(ISD::AVGCEILU, VT)) { + if (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 (TLI.isOperationLegal(ISD::AVGCEILS, VT)) { + if (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) { @@ -2697,52 +2724,45 @@ SDValue DAGCombiner::visitADDLike(SDNode *N) { reassociateReduction(ISD::VECREDUCE_ADD, ISD::ADD, DL, VT, N0, N1)) return SD; } + + SDValue A, B, C; + // fold ((0-A) + B) -> B-A - if (N0.getOpcode() == ISD::SUB && isNullOrNullSplat(N0.getOperand(0))) - return DAG.getNode(ISD::SUB, DL, VT, N1, N0.getOperand(1)); + 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 (N1.getOpcode() == ISD::SUB && isNullOrNullSplat(N1.getOperand(0))) - return DAG.getNode(ISD::SUB, DL, VT, N0, N1.getOperand(1)); + if (sd_match(N1, m_Neg(m_Value(B)))) + return DAG.getNode(ISD::SUB, DL, VT, N0, B); // fold (A+(B-A)) -> B - if (N1.getOpcode() == ISD::SUB && N0 == N1.getOperand(1)) - return N1.getOperand(0); + if (sd_match(N1, m_Sub(m_Value(B), m_Specific(N0)))) + return B; // fold ((B-A)+A) -> B - if (N0.getOpcode() == ISD::SUB && N1 == N0.getOperand(1)) - return N0.getOperand(0); + if (sd_match(N0, m_Sub(m_Value(B), m_Specific(N1)))) + return B; // fold ((A-B)+(C-A)) -> (C-B) - if (N0.getOpcode() == ISD::SUB && N1.getOpcode() == ISD::SUB && - N0.getOperand(0) == N1.getOperand(1)) - return DAG.getNode(ISD::SUB, DL, VT, N1.getOperand(0), - N0.getOperand(1)); + if (sd_match(N0, m_Sub(m_Value(A), m_Value(B))) && + sd_match(N1, m_Sub(m_Value(C), m_Specific(A)))) + return DAG.getNode(ISD::SUB, DL, VT, C, B); // fold ((A-B)+(B-C)) -> (A-C) - if (N0.getOpcode() == ISD::SUB && N1.getOpcode() == ISD::SUB && - N0.getOperand(1) == N1.getOperand(0)) - return DAG.getNode(ISD::SUB, DL, VT, N0.getOperand(0), - N1.getOperand(1)); + if (sd_match(N0, m_Sub(m_Value(A), m_Value(B))) && + sd_match(N1, m_Sub(m_Specific(B), m_Value(C)))) + return DAG.getNode(ISD::SUB, DL, VT, A, C); // fold (A+(B-(A+C))) to (B-C) - if (N1.getOpcode() == ISD::SUB && N1.getOperand(1).getOpcode() == ISD::ADD && - N0 == N1.getOperand(1).getOperand(0)) - return DAG.getNode(ISD::SUB, DL, VT, N1.getOperand(0), - N1.getOperand(1).getOperand(1)); - // fold (A+(B-(C+A))) to (B-C) - if (N1.getOpcode() == ISD::SUB && N1.getOperand(1).getOpcode() == ISD::ADD && - N0 == N1.getOperand(1).getOperand(1)) - return DAG.getNode(ISD::SUB, DL, VT, N1.getOperand(0), - N1.getOperand(1).getOperand(0)); + if (sd_match(N1, m_Sub(m_Value(B), m_Add(m_Specific(N0), m_Value(C))))) + return DAG.getNode(ISD::SUB, DL, VT, B, C); // fold (A+((B-A)+or-C)) to (B+or-C) - if ((N1.getOpcode() == ISD::SUB || N1.getOpcode() == ISD::ADD) && - N1.getOperand(0).getOpcode() == ISD::SUB && - N0 == N1.getOperand(0).getOperand(1)) - return DAG.getNode(N1.getOpcode(), DL, VT, N1.getOperand(0).getOperand(0), - N1.getOperand(1)); + if (sd_match(N1, + m_AnyOf(m_Add(m_Sub(m_Value(B), m_Specific(N0)), m_Value(C)), + m_Sub(m_Sub(m_Value(B), m_Specific(N0)), m_Value(C))))) + return DAG.getNode(N1.getOpcode(), DL, VT, B, C); // fold (A-B)+(C-D) to (A+C)-(B+D) when A or C is constant if (N0.getOpcode() == ISD::SUB && N1.getOpcode() == ISD::SUB && @@ -2804,8 +2824,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); } } @@ -2826,6 +2845,32 @@ SDValue DAGCombiner::visitADDLike(SDNode *N) { return SDValue(); } +// Attempt to form avgfloor(A, B) from (A & B) + ((A ^ B) >> 1) +static SDValue combineFixedwidthToAVGFLOOR(SDNode *N, SelectionDAG &DAG) { + const TargetLowering &TLI = DAG.getTargetLoweringInfo(); + SDValue N0 = N->getOperand(0); + EVT VT = N0.getValueType(); + SDLoc DL(N); + SDValue A, B; + + if (TLI.isOperationLegal(ISD::AVGFLOORU, VT)) { + if (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 (TLI.isOperationLegal(ISD::AVGFLOORS, VT)) { + if (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); @@ -2841,6 +2886,10 @@ SDValue DAGCombiner::visitADD(SDNode *N) { if (SDValue V = foldAddSubOfSignBit(N, DAG)) return V; + // Try to match AVGFLOOR fixedwidth pattern + if (SDValue V = combineFixedwidthToAVGFLOOR(N, DAG)) + 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)) @@ -3030,8 +3079,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); } @@ -3442,6 +3490,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). @@ -3489,7 +3542,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); } @@ -3603,7 +3656,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(); @@ -3618,18 +3671,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))) @@ -3640,10 +3693,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(); @@ -3664,6 +3717,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) { @@ -3694,16 +3748,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) @@ -3794,63 +3844,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()) @@ -3864,18 +3885,19 @@ SDValue DAGCombiner::visitSUB(SDNode *N) { if (SDValue V = foldAddSubOfSignBit(N, DAG)) return V; + // Try to match AVGCEIL fixedwidth pattern + if (SDValue V = combineFixedwidthToAVGCEIL(N, DAG)) + return V; + if (SDValue V = foldAddSubMasked1(false, N0, N1, DAG, SDLoc(N))) return V; - if (SDValue V = foldSubToUSubSat(VT, N)) + if (SDValue V = foldSubToUSubSat(VT, N, 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)); - } + // (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) @@ -3931,7 +3953,7 @@ 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)) + if (C->getAPIntValue() == (BitWidth - 1)) return DAG.getNode(ISD::ABS, SDLoc(N), VT, S0); } } @@ -3974,8 +3996,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); } @@ -3986,7 +4007,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); } @@ -4019,23 +4040,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(); } @@ -4128,13 +4143,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)) @@ -6694,35 +6707,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, @@ -6812,34 +6815,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())) @@ -6859,8 +6862,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()); @@ -6882,7 +6885,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; @@ -6891,12 +6894,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 @@ -6916,18 +6919,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))) @@ -6939,7 +6940,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))); @@ -6960,8 +6960,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 @@ -7071,9 +7071,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)); } } @@ -7090,8 +7090,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()); @@ -7143,7 +7143,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)); } } @@ -7157,7 +7157,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. @@ -7212,10 +7212,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 @@ -10772,7 +10772,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) @@ -10784,7 +10784,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(); @@ -10843,9 +10842,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) @@ -10854,7 +10854,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))) @@ -10864,7 +10864,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, @@ -13855,11 +13854,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. @@ -14660,6 +14668,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()) @@ -14667,10 +14676,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 @@ -14679,10 +14688,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); @@ -14696,8 +14705,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); } } @@ -14732,8 +14741,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)); @@ -14748,7 +14755,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); } } @@ -14760,22 +14767,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. @@ -14784,7 +14789,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()) { @@ -14798,7 +14802,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))); @@ -14830,7 +14833,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); } } @@ -14893,7 +14896,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); } } @@ -14907,11 +14910,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)); } } @@ -14956,7 +14957,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); @@ -14973,7 +14973,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)); @@ -14990,7 +14989,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; } @@ -22484,17 +22483,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 @@ -23471,9 +23469,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; @@ -23483,7 +23479,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(); @@ -23503,13 +23499,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); } @@ -24222,7 +24217,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()) { @@ -27867,15 +27862,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*/, @@ -27917,6 +27907,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; @@ -27947,18 +27944,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; } @@ -27975,12 +27976,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..27b8472ddb73d807ee80eb6e439a4294166f378b 100644 --- a/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp @@ -1192,40 +1192,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";); } } 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..808e3c622033e08a96e246f2a5fb7fabd4b3c446 100644 --- a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp @@ -267,7 +267,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)); } 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/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp index c24303592769a008834ff8e2b7f92421b56cd51f..e8d1ac1d3a916714c497dac633d68745a0897860 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( @@ -4068,6 +4071,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 +4296,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 +4879,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 +5043,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 +5362,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); @@ -6043,30 +6085,14 @@ static std::optional<APInt> FoldValue(unsigned Opcode, const APInt &C1, 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: @@ -8412,11 +8438,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 +8603,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 +8724,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 +8777,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 +8872,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 +9025,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 +9628,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 +11765,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 b6a35f7ad4c4c6be67ab85d8dcbf32e43280f5d6..ae6bd7e938e849362450d8e270f4c7f54f0d18b5 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) @@ -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) @@ -6904,7 +6907,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 +6936,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); } @@ -8087,7 +8090,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) @@ -8110,8 +8113,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, @@ -8151,7 +8154,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); @@ -8174,7 +8177,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, @@ -8217,7 +8220,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, @@ -8240,7 +8243,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], @@ -10498,14 +10501,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); @@ -10517,7 +10520,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/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..8be03b66e155f6d62721cb62ed3880d856bb7804 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()) { @@ -10694,7 +10702,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..9990556f89ed8be8dcbe2ff951cdca0495b64d9c 100644 --- a/llvm/lib/CodeGen/TargetLoweringBase.cpp +++ b/llvm/lib/CodeGen/TargetLoweringBase.cpp @@ -2011,6 +2011,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; 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..4120c74c23b19341318666aea3003bdc6a542ea3 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[Idx].Size; +} + +unsigned TargetRegisterInfo::getSubRegIdxOffset(unsigned Idx) const { + assert(Idx && Idx < getNumSubRegIndices() && + "This is not a subregister index"); + return SubRegIdxRanges[Idx].Offset; +} + Register TargetRegisterInfo::lookThruCopyLike(Register SrcReg, const MachineRegisterInfo *MRI) const { 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 94% rename from llvm/lib/DebugInfo/LogicalView/Readers/LVELFReader.cpp rename to llvm/lib/DebugInfo/LogicalView/Readers/LVDWARFReader.cpp index 4469092099dacab74b751b7fbbb70f9484be8300..91e5a037054da04958cada70058fff3dc755a704 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()); @@ -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/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/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/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..38c191a2dec60e2d677ddeba5e67e48c624df593 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; @@ -862,7 +862,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 +1139,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,6 +1414,10 @@ 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"; @@ -1685,18 +1695,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 +2140,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 +2717,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 +4604,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 +4672,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 +4907,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 +4931,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 +4954,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 +4970,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 +5220,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..c17419b529ac008747ddbc563c339c061c00f6ed 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); @@ -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..023cabc46911e5ff04ce35560a3a43575599164d 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) { @@ -2414,6 +2422,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)); 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..09bce9df1f3328eb5fdeeafb26c347e8d168f680 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( @@ -1663,6 +1669,12 @@ LLVMValueRef LLVMDIBuilderInsertDeclareBefore(LLVMDIBuilderRef Builder, LLVMValueRef Storage, LLVMMetadataRef VarInfo, LLVMMetadataRef Expr, LLVMMetadataRef DL, LLVMValueRef Instr) { + return LLVMDIBuilderInsertDeclareIntrinsicBefore(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), @@ -1671,11 +1683,27 @@ LLVMDIBuilderInsertDeclareBefore(LLVMDIBuilderRef Builder, LLVMValueRef Storage, "Inserted a DbgRecord into function using old debug info mode"); return wrap(cast<Instruction *>(DbgInst)); } +LLVMDbgRecordRef LLVMDIBuilderInsertDeclareRecordBefore( + LLVMDIBuilderRef Builder, LLVMValueRef Storage, LLVMMetadataRef VarInfo, + LLVMMetadataRef Expr, LLVMMetadataRef DL, LLVMValueRef Instr) { + return wrap( + unwrap(Builder) + ->insertDeclare(unwrap(Storage), unwrap<DILocalVariable>(VarInfo), + unwrap<DIExpression>(Expr), unwrap<DILocation>(DL), + unwrap<Instruction>(Instr)) + .get<DbgRecord *>()); +} LLVMValueRef LLVMDIBuilderInsertDeclareAtEnd(LLVMDIBuilderRef Builder, LLVMValueRef Storage, LLVMMetadataRef VarInfo, LLVMMetadataRef Expr, LLVMMetadataRef DL, LLVMBasicBlockRef Block) { + return LLVMDIBuilderInsertDeclareIntrinsicAtEnd(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)); @@ -1683,10 +1711,26 @@ LLVMDIBuilderInsertDeclareAtEnd(LLVMDIBuilderRef Builder, LLVMValueRef Storage, "Inserted a DbgRecord into function using old debug info mode"); return wrap(cast<Instruction *>(DbgInst)); } +LLVMDbgRecordRef LLVMDIBuilderInsertDeclareRecordAtEnd( + LLVMDIBuilderRef Builder, LLVMValueRef Storage, LLVMMetadataRef VarInfo, + LLVMMetadataRef Expr, LLVMMetadataRef DL, LLVMBasicBlockRef Block) { + return wrap(unwrap(Builder) + ->insertDeclare(unwrap(Storage), + unwrap<DILocalVariable>(VarInfo), + unwrap<DIExpression>(Expr), + unwrap<DILocation>(DL), unwrap(Block)) + .get<DbgRecord *>()); +} LLVMValueRef LLVMDIBuilderInsertDbgValueBefore( LLVMDIBuilderRef Builder, LLVMValueRef Val, LLVMMetadataRef VarInfo, LLVMMetadataRef Expr, LLVMMetadataRef DebugLoc, LLVMValueRef Instr) { + return LLVMDIBuilderInsertDbgValueIntrinsicBefore(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)); @@ -1694,10 +1738,26 @@ LLVMValueRef LLVMDIBuilderInsertDbgValueBefore( "Inserted a DbgRecord into function using old debug info mode"); return wrap(cast<Instruction *>(DbgInst)); } +LLVMDbgRecordRef LLVMDIBuilderInsertDbgValueRecordBefore( + LLVMDIBuilderRef Builder, LLVMValueRef Val, LLVMMetadataRef VarInfo, + LLVMMetadataRef Expr, LLVMMetadataRef DebugLoc, LLVMValueRef Instr) { + return wrap(unwrap(Builder) + ->insertDbgValueIntrinsic( + unwrap(Val), unwrap<DILocalVariable>(VarInfo), + unwrap<DIExpression>(Expr), unwrap<DILocation>(DebugLoc), + unwrap<Instruction>(Instr)) + .get<DbgRecord *>()); +} LLVMValueRef LLVMDIBuilderInsertDbgValueAtEnd( LLVMDIBuilderRef Builder, LLVMValueRef Val, LLVMMetadataRef VarInfo, LLVMMetadataRef Expr, LLVMMetadataRef DebugLoc, LLVMBasicBlockRef Block) { + return LLVMDIBuilderInsertDbgValueIntrinsicAtEnd(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)); @@ -1705,6 +1765,16 @@ LLVMValueRef LLVMDIBuilderInsertDbgValueAtEnd( "Inserted a DbgRecord into function using old debug info mode"); return wrap(cast<Instruction *>(DbgInst)); } +LLVMDbgRecordRef LLVMDIBuilderInsertDbgValueRecordAtEnd( + LLVMDIBuilderRef Builder, LLVMValueRef Val, LLVMMetadataRef VarInfo, + LLVMMetadataRef Expr, LLVMMetadataRef DebugLoc, LLVMBasicBlockRef Block) { + return wrap(unwrap(Builder) + ->insertDbgValueIntrinsic( + unwrap(Val), unwrap<DILocalVariable>(VarInfo), + unwrap<DIExpression>(Expr), unwrap<DILocation>(DebugLoc), + unwrap(Block)) + .get<DbgRecord *>()); +} LLVMMetadataRef LLVMDIBuilderCreateAutoVariable( LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name, @@ -1800,14 +1870,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 +1895,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 +1909,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 +2086,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 +2183,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 +2301,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 +2327,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 +2370,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/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..47a7f2c9de790f99bcd11c9ac10395adde9d5d37 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 { diff --git a/llvm/lib/IR/Instructions.cpp b/llvm/lib/IR/Instructions.cpp index c55d6cff84ed55099013269282790d1a8dd2964a..8ca211e6e2e72f6312c2ee722315724d7f763ae6 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; @@ -4615,6 +4623,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/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..b9cd219d94dc8ab7ca0ffddcc9d9ce52a2fb0329 100644 --- a/llvm/lib/IR/Operator.cpp +++ b/llvm/lib/IR/Operator.cpp @@ -37,7 +37,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 +69,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/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..819722566831c655c5be452eb4a8f5e43924aec4 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); } } @@ -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)) @@ -6219,22 +6244,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 +6268,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 +6347,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 +6711,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 +6733,7 @@ void Verifier::verifyFragmentExpression(const DPValue &DPV) { if (V->isArtificial()) return; - verifyFragmentExpression(*V, *Fragment, &DPV); + verifyFragmentExpression(*V, *Fragment, &DVR); } template <typename ValueOrMetadata> @@ -6755,7 +6781,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 +6789,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 +6806,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 +6833,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 +6854,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/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/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..f4c6cbc8dd444268ef1d1881cd4c146cc698cd79 100644 --- a/llvm/lib/MC/ELFObjectWriter.cpp +++ b/llvm/lib/MC/ELFObjectWriter.cpp @@ -939,51 +939,32 @@ 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()); - // 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 +972,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)); + } } } 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/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/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.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 be51093933a87c5908f065a6925fc1c4e8279ffd..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,32 @@ 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} || + (Name.starts_with(NullThunkDataPrefix) && + Name.ends_with(NullThunkDataSuffix)); +} + static Expected<std::vector<unsigned>> getSymbols(SymbolicFile *Obj, uint16_t Index, raw_ostream &SymNames, @@ -704,6 +731,10 @@ static Expected<std::vector<unsigned>> getSymbols(SymbolicFile *Obj, if (Map == &SymMap->Map) { Ret.push_back(SymNames.tell()); SymNames << Name << '\0'; + // If EC is enabled, then the import descriptors are NOT put into EC + // objects so we need to copy them to the EC map manually. + if (SymMap->UseECMap && isImportDescriptor(Name)) + SymMap->ECMap[Name] = Index; } } else { Ret.push_back(SymNames.tell()); @@ -719,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 = @@ -783,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 @@ -825,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. @@ -868,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; } @@ -890,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); @@ -953,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; @@ -965,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; @@ -997,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 @@ -1225,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) @@ -1262,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 376dd126baf61a9f8fae73d3a9201978436aa5f2..8224a1492502f654ba9cc62e458d6e06848673c7 100644 --- a/llvm/lib/Object/COFFImportFile.cpp +++ b/llvm/lib/Object/COFFImportFile.cpp @@ -108,7 +108,7 @@ template <class T> static void append(std::vector<uint8_t> &B, const T &Data) { } static void writeStringTable(std::vector<uint8_t> &B, - ArrayRef<const std::string> Strings) { + ArrayRef<const std::string_view> Strings) { // The COFF string table consists of a 4-byte value which is the size of the // table, including the length field itself. This value is followed by the // string content itself, which is an array of null-terminated C-style @@ -171,9 +171,6 @@ static Expected<std::string> replace(StringRef S, StringRef From, return (Twine(S.substr(0, Pos)) + To + S.substr(Pos + From.size())).str(); } -static const std::string NullImportDescriptorSymbolName = - "__NULL_IMPORT_DESCRIPTOR"; - namespace { // This class constructs various small object files necessary to support linking // symbols imported from a DLL. The contents are pretty strictly defined and @@ -192,8 +189,9 @@ class ObjectFactory { public: ObjectFactory(StringRef S, MachineTypes M) : NativeMachine(M), ImportName(S), Library(llvm::sys::path::stem(S)), - ImportDescriptorSymbolName(("__IMPORT_DESCRIPTOR_" + Library).str()), - NullThunkSymbolName(("\x7f" + Library + "_NULL_THUNK_DATA").str()) {} + ImportDescriptorSymbolName((ImportDescriptorPrefix + Library).str()), + NullThunkSymbolName( + (NullThunkDataPrefix + Library + NullThunkDataSuffix).str()) {} // Creates an Import Descriptor. This is a small object file which contains a // reference to the terminators and contains the library name (entry) for the @@ -628,8 +626,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); 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/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/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..f60f4eb3f0ef8c92bedbd566640bba38d9515347 100644 --- a/llvm/lib/Passes/PassBuilder.cpp +++ b/llvm/lib/Passes/PassBuilder.cpp @@ -358,7 +358,7 @@ 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(); } @@ -503,15 +503,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 +514,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 +620,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 +666,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 +1020,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 +1042,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 +1069,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 +1158,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 +1187,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 +1214,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 +1255,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 +1277,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 +1286,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/InstrProfWriter.cpp b/llvm/lib/ProfileData/InstrProfWriter.cpp index e757c735719b1f3cdbbfd676a91270bb7d4e6bc9..d9fe88a00bdfc45ea49c4ab1259200cbddebcd67 100644 --- a/llvm/lib/ProfileData/InstrProfWriter.cpp +++ b/llvm/lib/ProfileData/InstrProfWriter.cpp @@ -60,16 +60,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 +78,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)); } } @@ -575,7 +575,7 @@ Error InstrProfWriter::writeImpl(ProfOStream &OS) { {MemProfSectionStart + sizeof(uint64_t), &FramePayloadOffset, 1}, {MemProfSectionStart + 2 * sizeof(uint64_t), &FrameTableOffset, 1}, }; - OS.patch(PatchItems, 3); + OS.patch(PatchItems); } // BinaryIdSection has two parts: @@ -693,7 +693,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 +713,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) diff --git a/llvm/lib/ProfileData/MemProf.cpp b/llvm/lib/ProfileData/MemProf.cpp index 0461f0e9f840789d7b65d87e31d4839b53d96bf3..bffa4ed19be8c8bb807443fc698c43a667d3bbf0 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 { @@ -117,5 +119,28 @@ 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 verifyFunctionProfileData( + const llvm::MapVector<GlobalValue::GUID, IndexedMemProfRecord> + &FunctionProfileData) { + for (const auto &[GUID, Record] : FunctionProfileData) { + (void)GUID; + for (const auto &AS : Record.AllocSites) { + assert(AS.CSId == hashCallStack(AS.CallStack)); + (void)AS; + } + } +} + } // 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..7a383c3236d9b17a9f3fd9c359f8ab6db522dc20 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,23 @@ 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); +} diff --git a/llvm/lib/Support/AutoConvert.cpp b/llvm/lib/Support/AutoConvert.cpp index 74842e9167bde5ff768223167923a5ace639802e..c509284ee916efec2b86fe2b6ac80fa1409e1a48 100644 --- a/llvm/lib/Support/AutoConvert.cpp +++ b/llvm/lib/Support/AutoConvert.cpp @@ -14,6 +14,7 @@ #ifdef __MVS__ #include "llvm/Support/AutoConvert.h" +#include "llvm/Support/Error.h" #include <cassert> #include <fcntl.h> #include <sys/stat.h> 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/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/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/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..9b5cbe3de137b368dfb97e892002acd7a05296c2 100644 --- a/llvm/lib/Target/AArch64/AArch64Arm64ECCallLowering.cpp +++ b/llvm/lib/Target/AArch64/AArch64Arm64ECCallLowering.cpp @@ -30,6 +30,7 @@ #include "llvm/TargetParser/Triple.h" using namespace llvm; +using namespace llvm::COFF; using namespace llvm::object; 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..043a617898a69ed47367ef511bdf6439b43508d6 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)); } } @@ -7197,11 +7200,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. @@ -7751,7 +7754,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 +7762,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 +7789,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 +7802,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 +7817,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 +8049,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 @@ -8289,9 +8320,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 +8476,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 +8486,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,13 +8621,12 @@ 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); } @@ -16585,6 +16616,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 +16724,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 +18629,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 +18646,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 +21493,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 +21513,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/AArch64PassRegistry.def b/llvm/lib/Target/AArch64/AArch64PassRegistry.def new file mode 100644 index 0000000000000000000000000000000000000000..ca944579f93a935f981d0b490a517cb561fad11c --- /dev/null +++ b/llvm/lib/Target/AArch64/AArch64PassRegistry.def @@ -0,0 +1,20 @@ +//===- 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. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file is used as the registry of passes that are part of the +// AArch64 backend. +// +//===----------------------------------------------------------------------===// + +// NOTE: NO INCLUDE GUARD DESIRED! + +#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..b65c67e70a4e0f0be3c93c782eae1d48882ac484 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, @@ -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/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..08238fdf167bf2928560973d6b97ff704d2666a2 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()); diff --git a/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp b/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp index 755b034764ed2d372fc85ab759c2028a699164b1..7a86c5c608812003cd2223d884e1b1b4222a7b10 100644 --- a/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp +++ b/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp @@ -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/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..34e2c1d9c8e2f9ced383a6107471141a491d8802 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) @@ -628,7 +628,9 @@ AArch64LegalizerInfo::AArch64LegalizerInfo(const AArch64Subtarget &ST) return DstTy.isVector() && SrcTy.getSizeInBits() > 128 && DstTy.getScalarSizeInBits() * 2 <= SrcTy.getScalarSizeInBits(); }) - + .clampMinNumElements(0, s8, 8) + .clampMinNumElements(0, s16, 4) + .clampMinNumElements(0, s32, 2) .alwaysLegal(); getActionDefinitionsBuilder(G_SEXT_INREG) @@ -1010,6 +1012,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 +1269,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..72e8b59e0a4096111a65381f7e7d6d6f9a73d703 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPUAsmPrinter.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPUAsmPrinter.cpp @@ -1033,6 +1033,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 +1085,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 +1140,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/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..8969b3b5b6ce0869f316b9ea70b926e6bf004384 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPUCallLowering.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPUCallLowering.cpp @@ -715,10 +715,13 @@ bool AMDGPUCallLowering::lowerFormalArguments( if (!IsEntryFunc && !IsGraphics) { // For the fixed ABI, pass workitem IDs in the last argument register. TLI.allocateSpecialInputVGPRsFixed(CCInfo, MF, *TRI, *Info); + } + if (!IsEntryFunc) { if (!Subtarget.enableFlatScratch()) CCInfo.AllocateReg(Info->getScratchRSrcReg()); - TLI.allocateSpecialInputSGPRs(CCInfo, MF, *TRI, *Info); + if (!IsGraphics) + TLI.allocateSpecialInputSGPRs(CCInfo, MF, *TRI, *Info); } IncomingValueAssigner Assigner(AssignFn); @@ -1301,6 +1304,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 +1489,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/AMDGPUCallingConv.td b/llvm/lib/Target/AMDGPU/AMDGPUCallingConv.td index 4be64629ddac82311233325ae7ccec2e871974ff..9bd0fd7eca76fbc38a5faa594680cb40bead5406 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPUCallingConv.td +++ b/llvm/lib/Target/AMDGPU/AMDGPUCallingConv.td @@ -23,6 +23,7 @@ def CC_SI_Gfx : CallingConv<[ // 33 is reserved for the frame pointer // 34 is reserved for the base pointer CCIfInReg<CCIfType<[f32, i32, f16, i16, v2i16, v2f16, bf16, v2bf16] , CCAssignToReg<[ + SGPR0, SGPR1, SGPR2, SGPR3, SGPR4, SGPR5, SGPR6, SGPR7, SGPR8, SGPR9, SGPR10, SGPR11, SGPR12, SGPR13, SGPR14, SGPR15, SGPR16, SGPR17, SGPR18, SGPR19, SGPR20, SGPR21, SGPR22, SGPR23, diff --git a/llvm/lib/Target/AMDGPU/AMDGPUCodeGenPrepare.cpp b/llvm/lib/Target/AMDGPU/AMDGPUCodeGenPrepare.cpp index 0edbbf7cb0af544484841b70427591059f4e8608..bddf3d958a1ae6223f9c6797191a0beb4f796219 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPUCodeGenPrepare.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPUCodeGenPrepare.cpp @@ -1749,7 +1749,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 +1761,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 +1987,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/AMDGPUHSAMetadataStreamer.cpp b/llvm/lib/Target/AMDGPU/AMDGPUHSAMetadataStreamer.cpp index c20fdd51607a5b3b1f9097f37463835f90f6f186..9e288ab50e17017905fc442fddb3c49ba14a77fb 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPUHSAMetadataStreamer.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPUHSAMetadataStreamer.cpp @@ -494,6 +494,14 @@ MetadataStreamerMsgPackV4::getHSAKernelProps(const MachineFunction &MF, Kern[".max_flat_workgroup_size"] = Kern.getDocument()->getNode(MFI.getMaxFlatWorkGroupSize()); + unsigned NumWGX = MFI.getMaxNumWorkGroupsX(); + unsigned NumWGY = MFI.getMaxNumWorkGroupsY(); + unsigned NumWGZ = MFI.getMaxNumWorkGroupsZ(); + if (NumWGX != 0 && NumWGY != 0 && NumWGZ != 0) { + Kern[".max_num_workgroups_x"] = Kern.getDocument()->getNode(NumWGX); + Kern[".max_num_workgroups_y"] = Kern.getDocument()->getNode(NumWGY); + Kern[".max_num_workgroups_z"] = Kern.getDocument()->getNode(NumWGZ); + } Kern[".sgpr_spill_count"] = Kern.getDocument()->getNode(MFI.getNumSpilledSGPRs()); Kern[".vgpr_spill_count"] = 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..bee43b6c18c880abb4a4455422e46d4562050da3 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 { 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..84b4ccc1ae7ba74c911d7ab9f81f1a6339024ced 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"); @@ -1655,7 +1657,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..0037825ce08938030bd21c2319a072c69535bedd 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 diff --git a/llvm/lib/Target/AMDGPU/AMDGPUSearchableTables.td b/llvm/lib/Target/AMDGPU/AMDGPUSearchableTables.td index bb1c6b73372999b1da3366d8b7cccd2aa9a7bc12..8eb46a9801482c8f756483190a9cb30e6e5f4cc8 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPUSearchableTables.td +++ b/llvm/lib/Target/AMDGPU/AMDGPUSearchableTables.td @@ -354,82 +354,17 @@ 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>; +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>; // The dummy boolean output is divergent from the IR's perspective, diff --git a/llvm/lib/Target/AMDGPU/AMDGPUSubtarget.cpp b/llvm/lib/Target/AMDGPU/AMDGPUSubtarget.cpp index bcc7dedf322969f02e27c0948256a80540883514..fa77b94fc22def281ca71d865de630bbaebd670d 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPUSubtarget.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPUSubtarget.cpp @@ -432,7 +432,7 @@ std::pair<unsigned, unsigned> AMDGPUSubtarget::getEffectiveWavesPerEU( std::pair<unsigned, unsigned> Default(1, getMaxWavesPerEU()); // If minimum/maximum flat work group sizes were explicitly requested using - // "amdgpu-flat-work-group-size" attribute, then set default minimum/maximum + // "amdgpu-flat-workgroup-size" attribute, then set default minimum/maximum // number of waves per execution unit to values implied by requested // minimum/maximum flat work group sizes. unsigned MinImpliedByFlatWorkGroupSize = @@ -1108,3 +1108,8 @@ void GCNUserSGPRUsageInfo::allocKernargPreloadSGPRs(unsigned NumSGPRs) { unsigned GCNUserSGPRUsageInfo::getNumFreeUserSGPRs() { return AMDGPU::getMaxNumUserSGPRs(ST) - NumUsedUserSGPRs; } + +SmallVector<unsigned> +AMDGPUSubtarget::getMaxNumWorkGroups(const Function &F) const { + return AMDGPU::getIntegerVecAttribute(F, "amdgpu-max-num-workgroups", 3); +} diff --git a/llvm/lib/Target/AMDGPU/AMDGPUSubtarget.h b/llvm/lib/Target/AMDGPU/AMDGPUSubtarget.h index b72697973be7a11a1a1cd07f998f6175151aadc0..e2d8b5d1ce9790c75181829a5d509b895168a92f 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPUSubtarget.h +++ b/llvm/lib/Target/AMDGPU/AMDGPUSubtarget.h @@ -288,6 +288,9 @@ public: /// 2) dimension. unsigned getMaxWorkitemID(const Function &Kernel, unsigned Dimension) const; + /// Return the number of work groups for the function. + SmallVector<unsigned> getMaxNumWorkGroups(const Function &F) const; + /// Return true if only a single workitem can be active in a wave. bool isSingleLaneExecution(const Function &Kernel) const; 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..4648df199c741d7c495956734a13e933a3962411 100644 --- a/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp +++ b/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "AMDKernelCodeT.h" +#include "MCTargetDesc/AMDGPUMCExpr.h" #include "MCTargetDesc/AMDGPUMCTargetDesc.h" #include "MCTargetDesc/AMDGPUTargetStreamer.h" #include "SIDefines.h" @@ -980,7 +981,7 @@ public: return Imm.Type; } - unsigned getReg() const override { + MCRegister getReg() const override { assert(isRegKind()); return Reg.RegNo; } @@ -1816,6 +1817,7 @@ private: public: void onBeginOfFile() override; + bool parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) override; ParseStatus parseCustomOperand(OperandVector &Operands, unsigned MCK); @@ -8330,6 +8332,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 cc763df5a4760bbb23516915e3baed4623ad75ed..e944dde159904274e6ef76992cff9babc15f0df0 100644 --- a/llvm/lib/Target/AMDGPU/DSInstructions.td +++ b/llvm/lib/Target/AMDGPU/DSInstructions.td @@ -65,6 +65,7 @@ class DS_Real <DS_Pseudo ps, string opName = ps.Mnemonic> : let SubtargetPredicate = ps.SubtargetPredicate; let WaveSizePredicate = ps.WaveSizePredicate; let OtherPredicates = ps.OtherPredicates; + let TSFlags = ps.TSFlags; let SchedRW = ps.SchedRW; let mayLoad = ps.mayLoad; let mayStore = ps.mayStore; @@ -1734,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..db1f8c1872652b5fb82afb7d152af2e39bc45621 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 @@ -1787,45 +1782,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 +1921,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 +1936,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 +2057,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 +2070,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 +2087,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 +2110,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 +2139,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 +2337,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 +2729,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/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/CMakeLists.txt b/llvm/lib/Target/AMDGPU/MCTargetDesc/CMakeLists.txt index 5dc76071b0594e9ff3573b8513f22361c1dd4935..0842a58f794b32bc679cd28e83085cc659474c3e 100644 --- a/llvm/lib/Target/AMDGPU/MCTargetDesc/CMakeLists.txt +++ b/llvm/lib/Target/AMDGPU/MCTargetDesc/CMakeLists.txt @@ -5,6 +5,7 @@ add_llvm_component_library(LLVMAMDGPUDesc AMDGPUInstPrinter.cpp AMDGPUMCAsmInfo.cpp AMDGPUMCCodeEmitter.cpp + AMDGPUMCExpr.cpp AMDGPUMCTargetDesc.cpp AMDGPUTargetStreamer.cpp R600InstPrinter.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..81a231f0cade6406cf7d0501ff04c01b25197087 100644 --- a/llvm/lib/Target/AMDGPU/SIISelLowering.cpp +++ b/llvm/lib/Target/AMDGPU/SIISelLowering.cpp @@ -2857,12 +2857,13 @@ SDValue SITargetLowering::LowerFormalArguments( } else if (!IsGraphics) { // For the fixed ABI, pass workitem IDs in the last argument register. allocateSpecialInputVGPRsFixed(CCInfo, MF, *TRI, *Info); + } - // FIXME: Sink this into allocateSpecialInputSGPRs + if (!IsEntryFunc) { if (!Subtarget->enableFlatScratch()) CCInfo.AllocateReg(Info->getScratchRSrcReg()); - - allocateSpecialInputSGPRs(CCInfo, MF, *TRI, *Info); + if (!IsGraphics) + allocateSpecialInputSGPRs(CCInfo, MF, *TRI, *Info); } if (!IsKernel) { @@ -4858,8 +4859,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(); @@ -5409,6 +5410,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 +12578,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 +12601,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 +12613,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 +12692,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 +12724,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 +12962,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 +15039,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 +15197,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 +15954,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 b73df5db98880b29819491ab7c8757dec0ff5e18..66e67f659cbfb7071653cd024598131b2474ba7c 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..1c942dcefdaceaf857df7e4bba4cc29883f7eb72 100644 --- a/llvm/lib/Target/AMDGPU/SIInstructions.td +++ b/llvm/lib/Target/AMDGPU/SIInstructions.td @@ -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 52d6fe6c7ba51cd6304727a3588225e4ec1f5228..12433dc83c4892e89c29eb9f90b25fbe03302ac2 100644 --- a/llvm/lib/Target/AMDGPU/SIMachineFunctionInfo.cpp +++ b/llvm/lib/Target/AMDGPU/SIMachineFunctionInfo.cpp @@ -46,6 +46,8 @@ SIMachineFunctionInfo::SIMachineFunctionInfo(const Function &F, const GCNSubtarget &ST = *static_cast<const GCNSubtarget *>(STI); FlatWorkGroupSizes = ST.getFlatWorkGroupSizes(F); WavesPerEU = ST.getWavesPerEU(F); + MaxNumWorkGroups = ST.getMaxNumWorkGroups(F); + assert(MaxNumWorkGroups.size() == 3); Occupancy = ST.computeOccupancy(F, getLDSSize()); CallingConv::ID CC = F.getCallingConv(); @@ -746,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/SIMachineFunctionInfo.h b/llvm/lib/Target/AMDGPU/SIMachineFunctionInfo.h index 0336ec4985ea7475ca7ac03a580e0aa38001ee88..7d0c1ba8448e6cd1726c208a5691de5c01ffd940 100644 --- a/llvm/lib/Target/AMDGPU/SIMachineFunctionInfo.h +++ b/llvm/lib/Target/AMDGPU/SIMachineFunctionInfo.h @@ -426,6 +426,9 @@ class SIMachineFunctionInfo final : public AMDGPUMachineFunction, const AMDGPUGWSResourcePseudoSourceValue GWSResourcePSV; + // Default/requested number of work groups for the function. + SmallVector<unsigned> MaxNumWorkGroups = {0, 0, 0}; + private: unsigned NumUserSGPRs = 0; unsigned NumSystemSGPRs = 0; @@ -1072,6 +1075,13 @@ public: // \returns true if a function needs or may need AGPRs. bool usesAGPRs(const MachineFunction &MF) const; + + /// \returns Default/requested number of work groups for this function. + SmallVector<unsigned> getMaxNumWorkGroups() const { return MaxNumWorkGroups; } + + unsigned getMaxNumWorkGroupsX() const { return MaxNumWorkGroups[0]; } + unsigned getMaxNumWorkGroupsY() const { return MaxNumWorkGroups[1]; } + unsigned getMaxNumWorkGroupsZ() const { return MaxNumWorkGroups[2]; } }; } // end namespace llvm 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/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 edb0e50da2896be360b2cafdafcedf7149802c82..7bb84d78442b24b89f3ed4f65b90f9b5d490c1b3 100644 --- a/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp +++ b/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp @@ -11,6 +11,7 @@ #include "AMDGPUAsmUtils.h" #include "AMDKernelCodeT.h" #include "MCTargetDesc/AMDGPUMCTargetDesc.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/BinaryFormat/ELF.h" #include "llvm/IR/Attributes.h" #include "llvm/IR/Constants.h" @@ -317,6 +318,7 @@ struct MUBUFInfo { bool has_srsrc; bool has_soffset; bool IsBufferInv; + bool tfe; }; struct MTBUFInfo { @@ -465,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; @@ -1080,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)) @@ -1107,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; } @@ -1298,6 +1305,42 @@ getIntegerPairAttribute(const Function &F, StringRef Name, return Ints; } +SmallVector<unsigned> getIntegerVecAttribute(const Function &F, StringRef Name, + unsigned Size) { + assert(Size > 2); + SmallVector<unsigned> Default(Size, 0); + + Attribute A = F.getFnAttribute(Name); + if (!A.isStringAttribute()) + return Default; + + SmallVector<unsigned> Vals(Size, 0); + + LLVMContext &Ctx = F.getContext(); + + StringRef S = A.getValueAsString(); + unsigned i = 0; + for (; !S.empty() && i < Size; i++) { + std::pair<StringRef, StringRef> Strs = S.split(','); + unsigned IntVal; + if (Strs.first.trim().getAsInteger(0, IntVal)) { + Ctx.emitError("can't parse integer attribute " + Strs.first + " in " + + Name); + return Default; + } + Vals[i] = IntVal; + S = Strs.second; + } + + if (!S.empty() || i < Size) { + Ctx.emitError("attribute " + Name + + " has incorrect number of integers; expected " + + llvm::utostr(Size)); + return Default; + } + return Vals; +} + unsigned getVmcntBitMask(const IsaVersion &Version) { return (1 << (getVmcntBitWidthLo(Version.Major) + getVmcntBitWidthHi(Version.Major))) - @@ -3018,6 +3061,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 d7ea2a3eff4b7280ce9f8f3a5c20ea7eef622389..f4f9a787100b5b4b586ba77ce206696defa9c5cd 100644 --- a/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.h +++ b/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.h @@ -525,6 +525,9 @@ bool getMUBUFHasSoffset(unsigned Opc); LLVM_READONLY bool getMUBUFIsBufferInv(unsigned Opc); +LLVM_READONLY +bool getMUBUFTfe(unsigned Opc); + LLVM_READONLY bool getSMEMIsBuffer(unsigned Opc); @@ -863,6 +866,14 @@ bool isReadOnlySegment(const GlobalValue *GV); /// target triple \p TT, false otherwise. bool shouldEmitConstantsToTextSection(const Triple &TT); +/// \returns Integer value requested using \p F's \p Name attribute. +/// +/// \returns \p Default if attribute is not present. +/// +/// \returns \p Default and emits error if requested value cannot be converted +/// to integer. +int getIntegerAttribute(const Function &F, StringRef Name, int Default); + /// \returns A pair of integer values requested using \p F's \p Name attribute /// in "first[,second]" format ("second" is optional unless \p OnlyFirstRequired /// is false). @@ -877,6 +888,16 @@ getIntegerPairAttribute(const Function &F, StringRef Name, std::pair<unsigned, unsigned> Default, bool OnlyFirstRequired = false); +/// \returns Generate a vector of integer values requested using \p F's \p Name +/// attribute. +/// +/// \returns true if exactly Size (>2) number of integers are found in the +/// attribute. +/// +/// \returns false if any error occurs. +SmallVector<unsigned> getIntegerVecAttribute(const Function &F, StringRef Name, + unsigned Size); + /// Represents the counter values to wait for in an s_waitcnt instruction. /// /// Large values (including the maximum possible integer) can be used to @@ -1495,6 +1516,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/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/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..2ad576ab1a9caa8e170f614e8043ccad8aa8f645 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> @@ -79,6 +82,7 @@ extern const ARMInstrTable ARMDescs; } // end namespace llvm namespace { +class ARMOperand; enum class ImplicitItModeTy { Always, Never, ARMOnly, ThumbOnly }; @@ -446,13 +450,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 +511,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 +527,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? @@ -635,12 +649,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 +674,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 +736,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, @@ -979,7 +1002,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 +1370,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 +2043,8 @@ public: bool isProcIFlags() const { return Kind == k_ProcIFlags; } // NEON operands. + bool isVectorList() const { return Kind == k_VectorList; } + bool isSingleSpacedVectorList() const { return Kind == k_VectorList && !VectorList.isDoubleSpaced; } @@ -2452,6 +2485,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) @@ -4054,6 +4101,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 +4231,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. @@ -4680,6 +4790,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,7 +4803,7 @@ 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)); break; case AllLanes: Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 1, false, @@ -4712,9 +4824,7 @@ 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)); break; case AllLanes: Reg = MRI->getMatchingSuperReg(Reg, ARM::dsub_0, @@ -4730,7 +4840,8 @@ ParseStatus ARMAsmParser::parseVectorList(OperandVector &Operands) { } return ParseStatus::Success; } - return Error(S, "vector register expected"); + Operands.push_back(ARMOperand::CreateReg(Reg, S, E)); + return ParseStatus::Success; } if (Parser.getTok().isNot(AsmToken::LCurly)) @@ -5060,6 +5171,10 @@ ParseStatus ARMAsmParser::parseProcIFlagsOperand(OperandVector &Operands) { /// 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(); @@ -5157,6 +5272,10 @@ ParseStatus ARMAsmParser::parseMSRMaskOperand(OperandVector &Operands) { /// 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(); @@ -5174,23 +5293,30 @@ ParseStatus ARMAsmParser::parseBankedRegOperand(OperandVector &Operands) { 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; @@ -5240,7 +5366,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 +5374,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. @@ -5441,7 +5567,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; @@ -5600,37 +5726,86 @@ ParseStatus ARMAsmParser::parseAM3Offset(OperandVector &Operands) { 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()); + 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()); + 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; - - case ARM::t2B: - case ARM::t2Bcc: CondOp = 1; ImmOp = 3; break; + unsigned MnemonicOpsEndInd = getMnemonicOpsEndInd(Operands); + unsigned CondI = findCondCodeInd(Operands, MnemonicOpsEndInd); + unsigned Cond = + (CondI == 0 ? ARMCC::AL + : static_cast<ARMOperand &>(*Operands[CondI]).getCondCode()); - 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 +5816,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 +5832,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()); + 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()); + Op.addCondCodeOperands(Inst, 2); + } } /// Parse an ARM memory expression, return false if successful else return true @@ -5948,6 +6140,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 +6168,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"); @@ -6493,18 +6696,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 +6730,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 +6790,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 +6815,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 +6847,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. @@ -6844,14 +6874,15 @@ 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) { + OperandVector &Operands, + unsigned MnemonicOpsEndInd) { if (Mnemonic != "ldrd" && Mnemonic != "strd") return; - if (Operands.size() < 4) + if (Operands.size() < MnemonicOpsEndInd + 2) return; - ARMOperand &Op2 = static_cast<ARMOperand &>(*Operands[2]); - ARMOperand &Op3 = static_cast<ARMOperand &>(*Operands[3]); + ARMOperand &Op2 = static_cast<ARMOperand &>(*Operands[MnemonicOpsEndInd]); + ARMOperand &Op3 = static_cast<ARMOperand &>(*Operands[MnemonicOpsEndInd + 1]); if (!Op2.isReg()) return; @@ -6876,7 +6907,7 @@ void ARMAsmParser::fixupGNULDRDAlias(StringRef Mnemonic, return; Operands.insert( - Operands.begin() + 3, + Operands.begin() + MnemonicOpsEndInd + 1, ARMOperand::CreateReg(PairedReg, Op2.getStartLoc(), Op2.getEndLoc())); } @@ -6886,19 +6917,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 +6962,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] = + Operands.erase(Operands.begin() + MnemonicOpsEndInd + 2); + Operands[MnemonicOpsEndInd + 1] = ARMOperand::CreateReg(RPair, Op2.getStartLoc(), Op2.getEndLoc()); 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) { @@ -7055,14 +7111,14 @@ 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)); } // 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( @@ -7070,14 +7126,9 @@ bool ARMAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, } // 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() + @@ -7123,6 +7174,11 @@ bool ARMAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, } } + // 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 +7197,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 +7209,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 @@ -7193,7 +7233,8 @@ bool ARMAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, Operands.insert(Operands.begin(), ARMOperand::CreateToken(StringRef("vmovlt"), MLoc)); } 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 @@ -7208,36 +7249,33 @@ bool ARMAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, Operands.insert(Operands.begin(), ARMOperand::CreateToken(StringRef("vcvtn"), MLoc)); } 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)) { + } 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()); @@ -7249,24 +7287,21 @@ bool ARMAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, ARMOperand::CreateToken(Mnemonic, MLoc)); } } - 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)); + ++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); } } } @@ -7291,69 +7326,73 @@ bool ARMAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, } } - // 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); + + // 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() > MnemonicOpsEndInd + 1 && + (Mnemonic == "ldrexd" || Mnemonic == "strexd" || Mnemonic == "ldaexd" || + Mnemonic == "stlexd")) { + bool isLoad = (Mnemonic == "ldrexd" || Mnemonic == "ldaexd"); + 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 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); + } } // GNU Assembler extension (compatibility). - fixupGNULDRDAlias(Mnemonic, Operands); + fixupGNULDRDAlias(Mnemonic, Operands, MnemonicOpsEndInd); // 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()) { + 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); - Operands.erase(Operands.begin() + 1); + removeCCOut(Operands, MnemonicOpsEndInd); } return false; } @@ -7398,49 +7437,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 +7499,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 +7523,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 +7532,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 +7574,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 +7590,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 +7660,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 +7697,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 +7764,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 +7777,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 +7808,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 +7836,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 +7859,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 +7881,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 +7925,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 +7969,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 +7985,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 +7999,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 +8039,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 +8056,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 +8069,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 +8077,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 +8086,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 +8096,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 +8107,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 +8126,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 +8137,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 +8160,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 +8191,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 +8207,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 +8215,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 +8242,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 +8292,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 +8324,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 +8333,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 +8354,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 +8371,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 +8824,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 +8842,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 +9172,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 +10599,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 +10610,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 +10731,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 +11033,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 +11063,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 +11140,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 +11306,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 +11317,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 +11330,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 +12671,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 +12781,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 +12990,29 @@ 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())) + // Note: This mutates the operand which could cause issues for future + // matches if this one fails later. + // It would be better to do this in addVecList but as this doesn't have access + // to MRI this isn't possible. + // If trying to match a VecListDPair with a Q register, convert Q to list. + case MCK_VecListDPair: + if (Op.isQReg() && !hasMVE()) { + auto DPair = getDRegFromQReg(Op.getReg()); + DPair = MRI->getMatchingSuperReg( + DPair, ARM::dsub_0, &ARMMCRegisterClasses[ARM::DPairRegClassID]); + Op.setVecListDPair(DPair); return Match_Success; - break; + } + return Match_InvalidOperand; + // Note: This mutates the operand (see above). + // If trying to match a VecListDPair with a D register, convert D singleton + // list. + case MCK_VecListOneD: + if (Op.isDReg() && !hasMVE()) { + Op.setVecListOneD(Op.getReg()); + return Match_Success; + } + return Match_InvalidOperand; } return Match_InvalidOperand; } @@ -12921,3 +13060,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()); +} + +std::unique_ptr<ARMOperand> ARMAsmParser::defaultCCOutOp() { + return ARMOperand::CreateCCOut(0, SMLoc()); +} + +std::unique_ptr<ARMOperand> ARMAsmParser::defaultVPTPredOp() { + return ARMOperand::CreateVPTPred(ARMVCC::None, SMLoc()); +} 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/AVR/AVRInstrInfo.td b/llvm/lib/Target/AVR/AVRInstrInfo.td index 68e14f7dc920314f8538a99c7a791319237c9572..fe0d3b6c8189b73d4913045a51525b6d912024fa 100644 --- a/llvm/lib/Target/AVR/AVRInstrInfo.td +++ b/llvm/lib/Target/AVR/AVRInstrInfo.td @@ -1387,7 +1387,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 0d1eef60c3b55076c826a14a9a7a2a3426daab64..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) @@ -271,6 +272,7 @@ public: .Case("xchg32_32", true) .Case("cmpxchg_64", true) .Case("cmpxchg32_32", true) + .Case("addr_space_cast", true) .Default(false); } }; diff --git a/llvm/lib/Target/BPF/BPF.h b/llvm/lib/Target/BPF/BPF.h index 5c77d183e1ef3d3da8f35cdcad57e700d753c9e3..bbdbdbbde532285c963267fe7dc568909d26e701 100644 --- a/llvm/lib/Target/BPF/BPF.h +++ b/llvm/lib/Target/BPF/BPF.h @@ -66,6 +66,14 @@ public: static bool isRequired() { return true; } }; +class BPFASpaceCastSimplifyPass + : public PassInfoMixin<BPFASpaceCastSimplifyPass> { +public: + PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); + + static bool isRequired() { return true; } +}; + class BPFAdjustOptPass : public PassInfoMixin<BPFAdjustOptPass> { public: PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM); diff --git a/llvm/lib/Target/BPF/BPFASpaceCastSimplifyPass.cpp b/llvm/lib/Target/BPF/BPFASpaceCastSimplifyPass.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f87b299bbba658b14d058e4862ace0eeab5fc3ce --- /dev/null +++ b/llvm/lib/Target/BPF/BPFASpaceCastSimplifyPass.cpp @@ -0,0 +1,92 @@ +//===-- BPFASpaceCastSimplifyPass.cpp - BPF addrspacecast simplications --===// +// +// Part of the LLVM Project, under the Apache 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 "BPF.h" +#include <optional> + +#define DEBUG_TYPE "bpf-aspace-simplify" + +using namespace llvm; + +namespace { + +struct CastGEPCast { + AddrSpaceCastInst *OuterCast; + + // Match chain of instructions: + // %inner = addrspacecast N->M + // %gep = getelementptr %inner, ... + // %outer = addrspacecast M->N %gep + // Where I is %outer. + static std::optional<CastGEPCast> match(Value *I) { + auto *OuterCast = dyn_cast<AddrSpaceCastInst>(I); + if (!OuterCast) + return std::nullopt; + auto *GEP = dyn_cast<GetElementPtrInst>(OuterCast->getPointerOperand()); + if (!GEP) + return std::nullopt; + auto *InnerCast = dyn_cast<AddrSpaceCastInst>(GEP->getPointerOperand()); + if (!InnerCast) + return std::nullopt; + if (InnerCast->getSrcAddressSpace() != OuterCast->getDestAddressSpace()) + return std::nullopt; + if (InnerCast->getDestAddressSpace() != OuterCast->getSrcAddressSpace()) + return std::nullopt; + return CastGEPCast{OuterCast}; + } + + static PointerType *changeAddressSpace(PointerType *Ty, unsigned AS) { + return Ty->get(Ty->getContext(), AS); + } + + // Assuming match(this->OuterCast) is true, convert: + // (addrspacecast M->N (getelementptr (addrspacecast N->M ptr) ...)) + // To: + // (getelementptr ptr ...) + GetElementPtrInst *rewrite() { + auto *GEP = cast<GetElementPtrInst>(OuterCast->getPointerOperand()); + auto *InnerCast = cast<AddrSpaceCastInst>(GEP->getPointerOperand()); + unsigned AS = OuterCast->getDestAddressSpace(); + auto *NewGEP = cast<GetElementPtrInst>(GEP->clone()); + NewGEP->setName(GEP->getName()); + NewGEP->insertAfter(OuterCast); + NewGEP->setOperand(0, InnerCast->getPointerOperand()); + auto *GEPTy = cast<PointerType>(GEP->getType()); + NewGEP->mutateType(changeAddressSpace(GEPTy, AS)); + OuterCast->replaceAllUsesWith(NewGEP); + OuterCast->eraseFromParent(); + if (GEP->use_empty()) + GEP->eraseFromParent(); + if (InnerCast->use_empty()) + InnerCast->eraseFromParent(); + return NewGEP; + } +}; + +} // anonymous namespace + +PreservedAnalyses BPFASpaceCastSimplifyPass::run(Function &F, + FunctionAnalysisManager &AM) { + SmallVector<CastGEPCast, 16> WorkList; + bool Changed = false; + for (BasicBlock &BB : F) { + for (Instruction &I : BB) + if (auto It = CastGEPCast::match(&I)) + WorkList.push_back(It.value()); + Changed |= !WorkList.empty(); + + while (!WorkList.empty()) { + CastGEPCast InsnChain = WorkList.pop_back_val(); + GetElementPtrInst *NewGEP = InsnChain.rewrite(); + for (User *U : NewGEP->users()) + if (auto It = CastGEPCast::match(U)) + WorkList.push_back(It.value()); + } + } + return Changed ? PreservedAnalyses::none() : PreservedAnalyses::all(); +} 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 81effc9b1db46cb2db3ff78fd58f5e296de02da7..2b78ed7134c92f2cf6b9f6c389c26c2bc97d2b96 100644 --- a/llvm/lib/Target/BPF/BPFCheckAndAdjustIR.cpp +++ b/llvm/lib/Target/BPF/BPFCheckAndAdjustIR.cpp @@ -14,6 +14,8 @@ // optimizations are done and those builtins can be removed. // - 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 address spaces). // //===----------------------------------------------------------------------===// @@ -55,6 +57,7 @@ private: bool removeCompareBuiltin(Module &M); bool sinkMinMax(Module &M); bool removeGEPBuiltins(Module &M); + bool insertASpaceCasts(Module &M); }; } // End anonymous namespace @@ -416,11 +419,124 @@ bool BPFCheckAndAdjustIR::removeGEPBuiltins(Module &M) { return Changed; } +// Wrap ToWrap with cast to address space zero: +// - if ToWrap is a getelementptr, +// wrap it's base pointer instead and return a copy; +// - if ToWrap is Instruction, insert address space cast +// immediately after ToWrap; +// - if ToWrap is not an Instruction (function parameter +// or a global value), insert address space cast at the +// beginning of the Function F; +// - use Cache to avoid inserting too many casts; +static Value *aspaceWrapValue(DenseMap<Value *, Value *> &Cache, Function *F, + Value *ToWrap) { + auto It = Cache.find(ToWrap); + if (It != Cache.end()) + return It->getSecond(); + + if (auto *GEP = dyn_cast<GetElementPtrInst>(ToWrap)) { + Value *Ptr = GEP->getPointerOperand(); + Value *WrappedPtr = aspaceWrapValue(Cache, F, Ptr); + auto *GEPTy = cast<PointerType>(GEP->getType()); + auto *NewGEP = GEP->clone(); + NewGEP->insertAfter(GEP); + NewGEP->mutateType(GEPTy->getPointerTo(0)); + NewGEP->setOperand(GEP->getPointerOperandIndex(), WrappedPtr); + NewGEP->setName(GEP->getName()); + Cache[ToWrap] = NewGEP; + return NewGEP; + } + + IRBuilder IB(F->getContext()); + if (Instruction *InsnPtr = dyn_cast<Instruction>(ToWrap)) + IB.SetInsertPoint(*InsnPtr->getInsertionPointAfterDef()); + else + IB.SetInsertPoint(F->getEntryBlock().getFirstInsertionPt()); + auto *PtrTy = cast<PointerType>(ToWrap->getType()); + auto *ASZeroPtrTy = PtrTy->getPointerTo(0); + auto *ACast = IB.CreateAddrSpaceCast(ToWrap, ASZeroPtrTy, ToWrap->getName()); + Cache[ToWrap] = ACast; + return ACast; +} + +// Wrap a pointer operand OpNum of instruction I +// with cast to address space zero +static void aspaceWrapOperand(DenseMap<Value *, Value *> &Cache, Instruction *I, + unsigned OpNum) { + Value *OldOp = I->getOperand(OpNum); + if (OldOp->getType()->getPointerAddressSpace() == 0) + return; + + Value *NewOp = aspaceWrapValue(Cache, I->getFunction(), OldOp); + I->setOperand(OpNum, NewOp); + // Check if there are any remaining users of old GEP, + // delete those w/o users + for (;;) { + auto *OldGEP = dyn_cast<GetElementPtrInst>(OldOp); + if (!OldGEP) + break; + if (!OldGEP->use_empty()) + break; + OldOp = OldGEP->getPointerOperand(); + OldGEP->eraseFromParent(); + } +} + +// 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: +// +// (load (ptr addrspace (N) %p) ...) +// -> (load (addrspacecast ptr addrspace (N) %p to ptr)) +// +// - assign section with name .addr_space.N for globals defined in +// non-zero address space N +bool BPFCheckAndAdjustIR::insertASpaceCasts(Module &M) { + bool Changed = false; + for (Function &F : M) { + DenseMap<Value *, Value *> CastsCache; + for (BasicBlock &BB : F) { + for (Instruction &I : BB) { + unsigned PtrOpNum; + + if (auto *LD = dyn_cast<LoadInst>(&I)) + PtrOpNum = LD->getPointerOperandIndex(); + else if (auto *ST = dyn_cast<StoreInst>(&I)) + PtrOpNum = ST->getPointerOperandIndex(); + else if (auto *CmpXchg = dyn_cast<AtomicCmpXchgInst>(&I)) + PtrOpNum = CmpXchg->getPointerOperandIndex(); + else if (auto *RMW = dyn_cast<AtomicRMWInst>(&I)) + PtrOpNum = RMW->getPointerOperandIndex(); + else + continue; + + aspaceWrapOperand(CastsCache, &I, PtrOpNum); + } + } + Changed |= !CastsCache.empty(); + } + // Merge all globals within same address space into single + // .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 << ".addr_space." << G.getAddressSpace(); + G.setSection(SecName); + // Prevent having separate section for constants + G.setConstant(false); + } + return Changed; +} + bool BPFCheckAndAdjustIR::adjustIR(Module &M) { bool Changed = removePassThroughBuiltin(M); Changed = removeCompareBuiltin(M) || Changed; Changed = sinkMinMax(M) || Changed; Changed = removeGEPBuiltins(M) || Changed; + Changed = insertASpaceCasts(M) || Changed; return Changed; } 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/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 82d347023106685faba9ab5896f567eff9347630..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 @@ -420,6 +433,35 @@ let Predicates = [BPFHasMovsx] in { } } +def ADDR_SPACE_CAST + : ALU_RR<BPF_ALU64, BPF_MOV, 64, + (outs GPR:$dst), + (ins GPR:$src, i64imm:$dst_as, i64imm:$src_as), + "$dst = addr_space_cast($src, $dst_as, $src_as)", + []> { + bits<64> dst_as; + bits<64> src_as; + + let Inst{47-32} = 1; + let Inst{31-16} = dst_as{15-0}; + let Inst{15-0} = src_as{15-0}; +} + +def SrcAddrSpace : SDNodeXForm<addrspacecast, [{ + return CurDAG->getTargetConstant( + cast<AddrSpaceCastSDNode>(N)->getSrcAddressSpace(), + SDLoc(N), MVT::i64); +}]>; + +def DstAddrSpace : SDNodeXForm<addrspacecast, [{ + return CurDAG->getTargetConstant( + cast<AddrSpaceCastSDNode>(N)->getDestAddressSpace(), + SDLoc(N), MVT::i64); +}]>; + +def : Pat<(addrspacecast:$this GPR:$src), + (ADDR_SPACE_CAST $src, (DstAddrSpace $this), (SrcAddrSpace $this))>; + def FI_ri : TYPE_LD_ST<BPF_IMM.Value, BPF_DW.Value, (outs GPR:$dst), 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 08ac4b25540f70bfe6fb1fcdcb29a9f1eab947c0..a7bed69b0f2ab61a25e95c7aa6e3ed3a50560704 100644 --- a/llvm/lib/Target/BPF/BPFTargetMachine.cpp +++ b/llvm/lib/Target/BPF/BPFTargetMachine.cpp @@ -108,21 +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; - } - return false; - }); +#define GET_PASS_REGISTRY "BPFPassRegistry.def" +#include "llvm/Passes/TargetPassRegistry.inc" + PB.registerPipelineStartEPCallback( [=](ModulePassManager &MPM, OptimizationLevel) { FunctionPassManager FPM; @@ -135,6 +130,7 @@ void BPFTargetMachine::registerPassBuilderCallbacks( PB.registerPeepholeEPCallback([=](FunctionPassManager &FPM, OptimizationLevel Level) { FPM.addPass(SimplifyCFGPass(SimplifyCFGOptions().hoistCommonInsts(true))); + FPM.addPass(BPFASpaceCastSimplifyPass()); }); PB.registerScalarOptimizerLateEPCallback( [=](FunctionPassManager &FPM, OptimizationLevel Level) { diff --git a/llvm/lib/Target/BPF/CMakeLists.txt b/llvm/lib/Target/BPF/CMakeLists.txt index d88e7ade40b9a04bbd3736d8842aa3c5c57dbccf..eade4cacb7100e6070aa5907efafe09fc9193c0d 100644 --- a/llvm/lib/Target/BPF/CMakeLists.txt +++ b/llvm/lib/Target/BPF/CMakeLists.txt @@ -24,6 +24,7 @@ add_llvm_target(BPFCodeGen BPFAbstractMemberAccess.cpp BPFAdjustOpt.cpp BPFAsmPrinter.cpp + BPFASpaceCastSimplifyPass.cpp BPFCheckAndAdjustIR.cpp BPFFrameLowering.cpp BPFInstrInfo.cpp @@ -53,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 9536a01e125bb3f873e42cacd58f5a6561915d2d..f7e69ebae15b6cdab2daaef11b4e8535b3106f72 100644 --- a/llvm/lib/Target/DirectX/DXIL.td +++ b/llvm/lib/Target/DirectX/DXIL.td @@ -205,30 +205,98 @@ defset list<DXILOpClass> OpClasses = { def writeSamplerFeedbackBias : DXILOpClass; def writeSamplerFeedbackGrad : DXILOpClass; def writeSamplerFeedbackLevel: DXILOpClass; + + // This is a sentinel definition. Hence placed at the end of the list + // and not as part of the above alphabetically sorted valid definitions. + // Additionally it is capitalized unlike all the others. + def UnknownOpClass: DXILOpClass; +} + +// Several of the overloaded DXIL Operations support for data types +// that are a subset of the overloaded LLVM intrinsics that they map to. +// For e.g., llvm.sin.* intrinsic operates on any floating-point type and +// maps for lowering to DXIL Op Sin. However, valid overloads of DXIL Sin +// operation overloads are half (f16) and float (f32) only. +// +// The following abstracts overload types specific to DXIL operations. + +class DXILType : LLVMType<OtherVT> { + let isAny = 1; + int isI16OrI32 = 0; + int isHalfOrFloat = 0; } +// Concrete records for various overload types supported specifically by +// DXIL Operations. +let isI16OrI32 = 1 in + def llvm_i16ori32_ty : DXILType; + +let isHalfOrFloat = 1 in + def llvm_halforfloat_ty : DXILType; + // Abstraction DXIL Operation to LLVM intrinsic -class DXILOpMapping<int opCode, DXILOpClass opClass, Intrinsic intrinsic, string doc> { +class DXILOpMappingBase { + int OpCode = 0; // Opcode of DXIL Operation + DXILOpClass OpClass = UnknownOpClass;// Class of DXIL Operation. + Intrinsic LLVMIntrinsic = ?; // LLVM Intrinsic DXIL Operation maps to + string Doc = ""; // A short description of the operation + list<LLVMType> OpTypes = ?; // Valid types of DXIL Operation in the + // format [returnTy, param1ty, ...] +} + +class DXILOpMapping<int opCode, DXILOpClass opClass, + Intrinsic intrinsic, string doc, + list<LLVMType> opTys = []> : DXILOpMappingBase { int OpCode = opCode; // Opcode corresponding to DXIL Operation - DXILOpClass OpClass = opClass; // Class of DXIL Operation. + DXILOpClass OpClass = opClass; // Class of DXIL Operation. Intrinsic LLVMIntrinsic = intrinsic; // LLVM Intrinsic the DXIL Operation maps string Doc = doc; // to a short description of the operation + list<LLVMType> OpTypes = !if(!eq(!size(opTys), 0), LLVMIntrinsic.Types, opTys); } // 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.">; + "Returns sine(theta) for theta in radians.", + [llvm_halforfloat_ty, LLVMMatchType<0>]>; def Exp2 : DXILOpMapping<21, unary, int_exp2, "Returns the base 2 exponential, or 2**x, of the specified value." - "exp2(x) = 2**x.">; + "exp2(x) = 2**x.", + [llvm_halforfloat_ty, LLVMMatchType<0>]>; def Frac : DXILOpMapping<22, unary, int_dx_frac, "Returns a fraction from 0 to 1 that represents the " - "decimal part of the input.">; + "decimal part of the input.", + [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_round, "Returns the input rounded to the nearest integer" - "within a floating-point type.">; + "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 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, diff --git a/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp b/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b46564702c7aad517461a686d8ab71c150839a5a --- /dev/null +++ b/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp @@ -0,0 +1,294 @@ +//===- 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::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::log2e)) + : ConstantFP::get(EltTy, numbers::log2e); + 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 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::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 21a20d45b922d9a50f96b9007af6b154d2245567..0841ae95423c7b69331d5f0f9a9c9d66cf0f0937 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,36 +249,33 @@ 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, + llvm::iterator_range<Use *> Args) { + const OpCodeProperty *Prop = getOpCodeProperty(OpCode); OverloadKind Kind = getOverloadKind(OverloadTy); - // FIXME: find the issue and report error in clang instead of check it in - // backend. if ((Prop->OverloadTys & (uint16_t)Kind) == 0) { - llvm_unreachable("invalid overload"); + 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 { - -CallInst *DXILOpBuilder::createDXILOpCall(dxil::OpCode OpCode, Type *OverloadTy, - llvm::iterator_range<Use *> Args) { - auto Fn = getOrCreateDXILOpFunction(OpCode, OverloadTy, M); + 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); + } 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, FullArgs); } Type *DXILOpBuilder::getOverloadTy(dxil::OpCode OpCode, FunctionType *FT) { @@ -323,8 +320,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..f3abcc6e02a4e3ad7e4e5c13113d08965b455195 100644 --- a/llvm/lib/Target/DirectX/DXILOpBuilder.h +++ b/llvm/lib/Target/DirectX/DXILOpBuilder.h @@ -29,7 +29,13 @@ namespace dxil { class DXILOpBuilder { public: DXILOpBuilder(Module &M, IRBuilderBase &B) : M(M), B(B) {} - CallInst *createDXILOpCall(dxil::OpCode OpCode, Type *OverloadTy, + /// 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, llvm::iterator_range<Use *> 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..3e334b0ec298d35c039dc207a8c8a4ab67bcf194 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" @@ -31,7 +32,6 @@ using namespace llvm::dxil; 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())) { @@ -39,11 +39,9 @@ static void lowerIntrinsic(dxil::OpCode DXILOp, Function &F, Module &M) { if (!CI) continue; - SmallVector<Value *> Args; - Args.emplace_back(DXILOpArg); - Args.append(CI->arg_begin(), CI->arg_end()); B.SetInsertPoint(CI); - CallInst *DXILCI = DXILB.createDXILOpCall(DXILOp, OverloadTy, CI->args()); + CallInst *DXILCI = DXILB.createDXILOpCall(DXILOp, F.getReturnType(), + OverloadTy, CI->args()); CI->replaceAllUsesWith(DXILCI); CI->eraseFromParent(); @@ -94,9 +92,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..bbf0c254bb697f3c76d406e84d9c24dc96c5d6c0 --- /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", DXILResourcePrinterPass(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/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/Mips32r6InstrFormats.td b/llvm/lib/Target/Mips/Mips32r6InstrFormats.td index ccb6d1df777aec06162025b192ee92d04389cc62..8536c52028c3e4feeada24280d8cc46030280cfd 100644 --- a/llvm/lib/Target/Mips/Mips32r6InstrFormats.td +++ b/llvm/lib/Target/Mips/Mips32r6InstrFormats.td @@ -86,6 +86,7 @@ def OPCODE5_BC1NEZ : OPCODE5<0b01101>; def OPCODE5_BC2EQZ : OPCODE5<0b01001>; def OPCODE5_BC2NEZ : OPCODE5<0b01101>; def OPCODE5_BGEZAL : OPCODE5<0b10001>; +def OPCODE5_NAL : OPCODE5<0b10000>; def OPCODE5_SIGRIE : OPCODE5<0b10111>; // The next four constants are unnamed in the spec. These names are taken from // the OPGROUP names they are used with. @@ -201,6 +202,16 @@ class BAL_FM : MipsR6Inst { let Inst{15-0} = offset; } +// NAL for Release 6 +class NAL_FM : MipsR6Inst { + bits<32> Inst; + + let Inst{31-26} = OPGROUP_REGIMM.Value; + let Inst{25-21} = 0b00000; + let Inst{20-16} = OPCODE5_NAL.Value; + let Inst{15-0} = 0x00; +} + class COP0_EVP_DVP_FM<bits<1> sc> : MipsR6Inst { bits<5> rt; diff --git a/llvm/lib/Target/Mips/Mips32r6InstrInfo.td b/llvm/lib/Target/Mips/Mips32r6InstrInfo.td index 854563ab32bd8ede2bcadce25ff0bf2026de28d9..9c29acbd0d8a8846147364fd8e333ca9e7947edc 100644 --- a/llvm/lib/Target/Mips/Mips32r6InstrInfo.td +++ b/llvm/lib/Target/Mips/Mips32r6InstrInfo.td @@ -73,6 +73,7 @@ class AUI_ENC : AUI_FM; class AUIPC_ENC : PCREL16_FM<OPCODE5_AUIPC>; class BAL_ENC : BAL_FM; +class NAL_ENC : NAL_FM; class BALC_ENC : BRANCH_OFF26_FM<0b111010>; class BC_ENC : BRANCH_OFF26_FM<0b110010>; class BEQC_ENC : CMP_BRANCH_2R_OFF16_FM<OPGROUP_ADDI>, @@ -381,6 +382,12 @@ class BC_DESC_BASE<string instr_asm, DAGOperand opnd> : BRANCH_DESC_BASE, bit isCTI = 1; } +class NAL_DESC_BASE<string instr_asm> : BRANCH_DESC_BASE, + MipsR6Arch<instr_asm> { + string AsmString = instr_asm; + bit isCTI = 1; +} + class CMP_BC_DESC_BASE<string instr_asm, DAGOperand opnd, RegisterOperand GPROpnd> : BRANCH_DESC_BASE, MipsR6Arch<instr_asm> { @@ -424,6 +431,12 @@ class BAL_DESC : BC_DESC_BASE<"bal", brtarget> { bit isCTI = 1; } +class NAL_DESC : NAL_DESC_BASE<"nal"> { + bit hasDelaySlot = 1; + list<Register> Defs = [RA]; + bit isCTI = 1; +} + class BALC_DESC : BC_DESC_BASE<"balc", brtarget26> { bit isCall = 1; list<Register> Defs = [RA]; @@ -868,6 +881,8 @@ def AUI : R6MMR6Rel, AUI_ENC, AUI_DESC, ISA_MIPS32R6; def AUIPC : R6MMR6Rel, AUIPC_ENC, AUIPC_DESC, ISA_MIPS32R6; def BAL : BAL_ENC, BAL_DESC, ISA_MIPS32R6; def BALC : R6MMR6Rel, BALC_ENC, BALC_DESC, ISA_MIPS32R6; +def NAL : NAL_ENC, NAL_DESC, ISA_MIPS32R6; + let AdditionalPredicates = [NotInMicroMips] in { def BC1EQZ : BC1EQZ_ENC, BC1EQZ_DESC, ISA_MIPS32R6, HARDFLOAT; def BC1NEZ : BC1NEZ_ENC, BC1NEZ_DESC, ISA_MIPS32R6, HARDFLOAT; @@ -948,7 +963,6 @@ let AdditionalPredicates = [NotInMicroMips] in { def MUL_R6 : R6MMR6Rel, MUL_R6_ENC, MUL_R6_DESC, ISA_MIPS32R6; def MULU : R6MMR6Rel, MULU_ENC, MULU_DESC, ISA_MIPS32R6; } -def NAL; // BAL with rd=0 let AdditionalPredicates = [NotInMicroMips] in { def PREF_R6 : R6MMR6Rel, PREF_ENC, PREF_DESC, ISA_MIPS32R6; def RINT_D : RINT_D_ENC, RINT_D_DESC, ISA_MIPS32R6, HARDFLOAT; 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 97e830cec27cad1a6ccc0bb7ad4891d8c11dffc5..0a0d40751fcf0560174e7bf6b6de807dc6d239f3 100644 --- a/llvm/lib/Target/Mips/MipsISelLowering.cpp +++ b/llvm/lib/Target/Mips/MipsISelLowering.cpp @@ -239,6 +239,8 @@ const char *MipsTargetLowering::getTargetNodeName(unsigned Opcode) const { case MipsISD::MAQ_S_W_PHR: return "MipsISD::MAQ_S_W_PHR"; case MipsISD::MAQ_SA_W_PHL: return "MipsISD::MAQ_SA_W_PHL"; case MipsISD::MAQ_SA_W_PHR: return "MipsISD::MAQ_SA_W_PHR"; + case MipsISD::DOUBLE_SELECT_I: return "MipsISD::DOUBLE_SELECT_I"; + case MipsISD::DOUBLE_SELECT_I64: return "MipsISD::DOUBLE_SELECT_I64"; case MipsISD::DPAU_H_QBL: return "MipsISD::DPAU_H_QBL"; case MipsISD::DPAU_H_QBR: return "MipsISD::DPAU_H_QBR"; case MipsISD::DPSU_H_QBL: return "MipsISD::DPSU_H_QBL"; @@ -363,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); @@ -479,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); @@ -2652,8 +2664,8 @@ SDValue MipsTargetLowering::lowerShiftRightParts(SDValue Op, SelectionDAG &DAG, if (!(Subtarget.hasMips4() || Subtarget.hasMips32())) { SDVTList VTList = DAG.getVTList(VT, VT); - return DAG.getNode(Subtarget.isGP64bit() ? Mips::PseudoD_SELECT_I64 - : Mips::PseudoD_SELECT_I, + return DAG.getNode(Subtarget.isGP64bit() ? MipsISD::DOUBLE_SELECT_I64 + : MipsISD::DOUBLE_SELECT_I, DL, VTList, Cond, ShiftRightHi, IsSRA ? Ext : DAG.getConstant(0, DL, VT), Or, ShiftRightHi); diff --git a/llvm/lib/Target/Mips/MipsISelLowering.h b/llvm/lib/Target/Mips/MipsISelLowering.h index 7d243eeca5c6c7833dc43dfffab8af8b2317263f..84ad40d6bbbe26915011cdef4d803a8f09b3be2d 100644 --- a/llvm/lib/Target/Mips/MipsISelLowering.h +++ b/llvm/lib/Target/Mips/MipsISelLowering.h @@ -242,6 +242,10 @@ class TargetRegisterClass; VEXTRACT_SEXT_ELT, VEXTRACT_ZEXT_ELT, + // Double select nodes for machines without conditional-move. + DOUBLE_SELECT_I, + DOUBLE_SELECT_I64, + // Load/Store Left/Right nodes. LWL = ISD::FIRST_TARGET_MEMORY_OPCODE, LWR, diff --git a/llvm/lib/Target/Mips/MipsInstrInfo.td b/llvm/lib/Target/Mips/MipsInstrInfo.td index 4b6f4b22e71b1a03547953204952ad8a928634c2..23e04c442bf6f3e91975b9575f69d8c4f2f315fa 100644 --- a/llvm/lib/Target/Mips/MipsInstrInfo.td +++ b/llvm/lib/Target/Mips/MipsInstrInfo.td @@ -3049,6 +3049,9 @@ def : MipsInstAlias<"divu $rd, $imm", (UDivIMacro GPR32Opnd:$rd, GPR32Opnd:$rd, simm32:$imm), 0>, ISA_MIPS1_NOT_32R6_64R6; + +def : MipsInstAlias<"nal", (BLTZAL ZERO, 0), 1>, ISA_MIPS1_NOT_32R6_64R6; + def SRemMacro : MipsAsmPseudoInst<(outs GPR32Opnd:$rd), (ins GPR32Opnd:$rs, GPR32Opnd:$rt), "rem\t$rd, $rs, $rt">, 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/MipsSEISelDAGToDAG.cpp b/llvm/lib/Target/Mips/MipsSEISelDAGToDAG.cpp index c0e978018919e0dd4500db418ac0d98956825340..ab39d1b661ef9a2d16ccd51f82fd3f0cc9fc3a0e 100644 --- a/llvm/lib/Target/Mips/MipsSEISelDAGToDAG.cpp +++ b/llvm/lib/Target/Mips/MipsSEISelDAGToDAG.cpp @@ -741,8 +741,8 @@ bool MipsSEDAGToDAGISel::trySelect(SDNode *Node) { switch(Opcode) { default: break; - case Mips::PseudoD_SELECT_I: - case Mips::PseudoD_SELECT_I64: { + case MipsISD::DOUBLE_SELECT_I: + case MipsISD::DOUBLE_SELECT_I64: { MVT VT = Subtarget->isGP64bit() ? MVT::i64 : MVT::i32; SDValue cond = Node->getOperand(0); SDValue Hi1 = Node->getOperand(1); 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/MipsScheduleGeneric.td b/llvm/lib/Target/Mips/MipsScheduleGeneric.td index a3df88a93cfb1fd85acf7b64966b0b782fa006e9..6771a897eea78687e21f1e2918887c3bd6f18dcd 100644 --- a/llvm/lib/Target/Mips/MipsScheduleGeneric.td +++ b/llvm/lib/Target/Mips/MipsScheduleGeneric.td @@ -285,7 +285,7 @@ def GenericWriteJumpAndLink : SchedWriteRes<[GenericIssueCTISTD]> { // jalr, jr.hb, jr, jalr.hb, jarlc, jialc def : InstRW<[GenericWriteJump], (instrs B, BAL, BAL_BR, BEQ, BNE, BGTZ, BGEZ, BLEZ, BLTZ, BLTZAL, J, JALX, JR, JR_HB, ERET, - ERet, ERETNC, DERET)>; + ERet, ERETNC, DERET, NAL)>; def : InstRW<[GenericWriteJump], (instrs BEQL, BNEL, BGEZL, BGTZL, BLEZL, BLTZL)>; 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..2783b1e0ec73ebda00c7fa5badd367d503e8616f 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) { 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..dfea9e7709240c60ced756a01f52eed5218389a6 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; } @@ -7741,7 +7726,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 +7747,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 +7774,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() || diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp index aef2d483c6df1e377cec3c3f8f70577d57cd2f0c..cce0efad39c75baa36681fe0590556dba47db258 100644 --- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp @@ -8519,7 +8519,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 +10764,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 +15048,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 +15140,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 +15208,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/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp index d83979a873f2a313c45982096efc005bbd26cc7f..5e594d6cad6bbd4d86a3db87e00c0d60d82b6108 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; @@ -976,9 +977,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 { @@ -1630,7 +1631,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 +1642,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 +1661,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 +1694,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 +2233,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 +2251,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 +2282,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 +2462,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 +2474,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 +2501,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 +2512,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 +2525,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,7 +2576,7 @@ 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)); @@ -2716,7 +2717,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 +2736,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 +2824,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 +2858,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 +3081,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 +3248,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 +3266,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 +3287,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 +3306,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 +3624,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 +3643,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 +3654,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/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..941ad752bfd9d43e25a183b13416471eb95df489 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); @@ -191,8 +219,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 +233,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) 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/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/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/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..c3f8a924a1da703c2564ca375ef7a5c7ed5442fa 100644 --- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -559,11 +559,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 +718,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 @@ -6071,8 +6072,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 +6541,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 +6611,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); @@ -9541,14 +9567,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 +9600,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 +10364,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 +10430,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 +10530,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 +10539,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 +10553,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 +10562,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 +12195,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 +12913,55 @@ 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)) +// +// 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.) +// +// TODO: Extend this to other binary ops +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 +12999,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 +13068,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)) @@ -13654,12 +13760,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; @@ -15285,62 +15387,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); @@ -16445,10 +16498,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 +17093,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 +17223,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 +17233,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 +17258,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 +17269,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 +17790,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); @@ -20923,7 +20981,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()) diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.h b/llvm/lib/Target/RISCV/RISCVISelLowering.h index f90cb4df6047612af291bc22840ccdbff0ad281e..c11b1464757c7f02ef10c94c189a4df5dc3292b1 100644 --- a/llvm/lib/Target/RISCV/RISCVISelLowering.h +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.h @@ -585,6 +585,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. diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp index 37a8079dcbf10d2b25cc41d18a26bb4674c365ee..14c2d41e80f1503a4a7a5bf1a22cc3c5b4714779 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) 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..966cdc433d0fd478fdb84680a6025a07b6a1395e 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfo.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.td @@ -1405,7 +1405,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/RISCVInstrInfoVPseudos.td b/llvm/lib/Target/RISCV/RISCVInstrInfoVPseudos.td index ae93bf694875658b47992547c4f571b288869c07..8be4c7741ca12b77a8349e598a4310aed0e23967 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfoVPseudos.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoVPseudos.td @@ -6698,6 +6698,7 @@ defm PseudoVFWREDOSUM : VPseudoVFWREDO_VS_RM; // 15. Vector Mask Instructions //===----------------------------------------------------------------------===// +let Predicates = [HasVInstructions] in { //===----------------------------------------------------------------------===// // 15.1 Vector Mask-Register Logical Instructions //===----------------------------------------------------------------------===// @@ -6718,7 +6719,6 @@ defm PseudoVMSET : VPseudoNullaryPseudoM<"VMXNOR">; //===----------------------------------------------------------------------===// // 15.2. Vector mask population count vcpop //===----------------------------------------------------------------------===// - let IsSignExtendingOpW = 1 in defm PseudoVCPOP: VPseudoVPOP_M; @@ -6753,6 +6753,7 @@ defm PseudoVIOTA_M: VPseudoVIOTA_M; // 15.9. Vector Element Index Instruction //===----------------------------------------------------------------------===// defm PseudoVID : VPseudoVID_V; +} // Predicates = [HasVInstructions] //===----------------------------------------------------------------------===// // 16. Vector Permutation Instructions @@ -6828,6 +6829,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 +6838,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..a882b208a7688967de50ab6841c69904208e4d87 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfoZb.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoZb.td @@ -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 { 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..74d65324b95d869299bb93876019031a916ae211 100644 --- a/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp +++ b/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp @@ -431,29 +431,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()); } } @@ -742,8 +748,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..9da1f73681c68c6407fdd763c9f31668c0f86d7f 100644 --- a/llvm/lib/Target/RISCV/RISCVRegisterInfo.td +++ b/llvm/lib/Target/RISCV/RISCVRegisterInfo.td @@ -573,7 +573,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..3586d235bdbbb90056c9a5ec5e4882f2b28d203c 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]>; @@ -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..f75b3d3caa62f2b5fcbde0bcc71f7dfed9d43e39 100644 --- a/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp +++ b/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp @@ -1001,6 +1001,51 @@ RISCVTTIImpl::getMinMaxReductionCost(Intrinsic::ID IID, VectorType *Ty, return getArithmeticReductionCost(Instruction::And, Ty, FMF, CostKind); } + 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; + + 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); + } + // IR Reduction is composed by two vmv and one rvv reduction instruction. InstructionCost BaseCost = 2; @@ -1620,3 +1665,13 @@ 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; +} diff --git a/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.h b/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.h index af36e9d5d5e886f0e913e0f923af353303bb6ceb..8daf6845dc8bc9985f16e0792447cdb99485150d 100644 --- a/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.h +++ b/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.h @@ -261,6 +261,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/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..afdca01561b0bc70c48dc9abf09e64e91417ec4c 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,7 +198,7 @@ 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: @@ -173,14 +209,13 @@ static SPIRVType *getArgSPIRVType(const Function &F, unsigned ArgIdx, // spv_assign_ptr_type intrinsic or otherwise use default pointer element // type. Argument *Arg = F.getArg(ArgIdx); - if (Arg->hasByValAttr() || Arg->hasByRefAttr()) { + if (HasPointeeTypeAttr(Arg)) { Type *ByValRefType = Arg->hasByValAttr() ? Arg->getParamByValType() : Arg->getParamByRefType(); SPIRVType *ElementType = GR->getOrCreateSPIRVType(ByValRefType, MIRBuilder); return GR->getOrCreateSPIRVPointerType( ElementType, MIRBuilder, - addressSpaceToStorageClass(Arg->getType()->getPointerAddressSpace(), - ST)); + addressSpaceToStorageClass(getPointerAddressSpace(Arg->getType()), ST)); } for (auto User : Arg->users()) { @@ -240,7 +275,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 +289,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 +319,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 +362,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 +471,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 +485,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 +493,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 +510,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/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..5828db6669ff18a4a7f2335d3d14ce486e7369ff 100644 --- a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp @@ -57,8 +57,14 @@ class SPIRVEmitIntrinsics bool TrackConstants = true; DenseMap<Instruction *, Constant *> AggrConsts; DenseSet<Instruction *> AggrStores; + + // deduce values type + DenseMap<Value *, Type *> DeducedElTys; + Type *deduceElementType(Value *I); + 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 +78,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 +91,10 @@ class SPIRVEmitIntrinsics IRBuilder<> &B); void insertPtrCastOrAssignTypeInstr(Instruction *I, IRBuilder<> &B); void processGlobalValue(GlobalVariable &GV, IRBuilder<> &B); + void processParamTypes(Function *F, IRBuilder<> &B); + Type *deduceFunParamType(Function *F, unsigned OpIdx); + Type *deduceFunParamType(Function *F, unsigned OpIdx, + std::unordered_set<Function *> &FVisited); public: static char ID; @@ -156,6 +167,57 @@ static inline void reportFatalOnTokenType(const Instruction *I) { false); } +// Deduce and return a successfully deduced Type of the Instruction, +// or nullptr otherwise. +static Type *deduceElementTypeHelper(Value *I, + std::unordered_set<Value *> &Visited, + DenseMap<Value *, Type *> &DeducedElTys) { + // allow to pass nullptr as an argument + if (!I) + return nullptr; + + // maybe already known + auto It = DeducedElTys.find(I); + if (It != DeducedElTys.end()) + return It->second; + + // 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 = Ref->getValueType(); + } else if (auto *Ref = dyn_cast<AddrSpaceCastInst>(I)) { + Ty = deduceElementTypeHelper(Ref->getPointerOperand(), Visited, + DeducedElTys); + } 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, DeducedElTys); + } + + // remember the found relationship + if (Ty) + DeducedElTys[I] = Ty; + + return Ty; +} + +Type *SPIRVEmitIntrinsics::deduceElementType(Value *I) { + std::unordered_set<Value *> Visited; + if (Type *Ty = deduceElementTypeHelper(I, Visited, DeducedElTys)) + return Ty; + return IntegerType::getInt8Ty(I->getContext()); +} + void SPIRVEmitIntrinsics::replaceMemInstrUses(Instruction *Old, Instruction *New, IRBuilder<> &B) { @@ -280,7 +342,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 +395,10 @@ 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 + std::unordered_set<Value *> Visited; + Type *PointerElemTy = deduceElementTypeHelper(Pointer, Visited, DeducedElTys); + if (PointerElemTy == ExpectedElementType) return; setInsertPointSkippingPhis(B, I); @@ -356,7 +408,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 +453,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); + DeducedElTys[CI] = ExpectedElementType; + DeducedElTys[Pointer] = ExpectedElementType; return; } @@ -419,7 +473,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, @@ -440,9 +494,34 @@ void SPIRVEmitIntrinsics::insertPtrCastOrAssignTypeInstr(Instruction *I, if (!CI || CI->isIndirectCall() || CI->getCalledFunction()->isIntrinsic()) return; + // collect information about formal parameter types + Function *CalledF = CI->getCalledFunction(); + SmallVector<Type *, 4> CalledArgTys; + bool HaveTypes = false; + for (auto &CalledArg : CalledF->args()) { + if (!isPointerTy(CalledArg.getType())) { + CalledArgTys.push_back(nullptr); + continue; + } + auto It = DeducedElTys.find(&CalledArg); + Type *ParamTy = It != DeducedElTys.end() ? It->second : nullptr; + if (!ParamTy) { + for (User *U : CalledArg.users()) { + if (Instruction *Inst = dyn_cast<Instruction>(U)) { + std::unordered_set<Value *> Visited; + ParamTy = deduceElementTypeHelper(Inst, Visited, DeducedElTys); + if (ParamTy) + break; + } + } + } + HaveTypes |= ParamTy != nullptr; + CalledArgTys.push_back(ParamTy); + } + 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 +534,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; @@ -639,30 +721,25 @@ 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); + DeducedElTys[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)) { @@ -730,6 +807,83 @@ void SPIRVEmitIntrinsics::processInstrAfterVisit(Instruction *I, } } +Type *SPIRVEmitIntrinsics::deduceFunParamType(Function *F, unsigned OpIdx) { + std::unordered_set<Function *> FVisited; + return deduceFunParamType(F, OpIdx, FVisited); +} + +Type *SPIRVEmitIntrinsics::deduceFunParamType( + 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 (auto It = DeducedElTys.find(OpArg); It != DeducedElTys.end()) + return It->second; + // 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, DeducedElTys)) + 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 = deduceFunParamType(Pair.first, Pair.second, FVisited)) + return Ty; + } + + return nullptr; +} + +void SPIRVEmitIntrinsics::processParamTypes(Function *F, IRBuilder<> &B) { + B.SetInsertPointPastAllocas(F); + DenseMap<Argument *, Type *> Args; + for (unsigned OpIdx = 0; OpIdx < F->arg_size(); ++OpIdx) { + Argument *Arg = F->getArg(OpIdx); + if (isUntypedPointerTy(Arg->getType()) && + DeducedElTys.find(Arg) == DeducedElTys.end() && + !HasPointeeTypeAttr(Arg)) { + if (Type *ElemTy = deduceFunParamType(F, OpIdx)) { + CallInst *AssignPtrTyCI = buildIntrWithMD( + Intrinsic::spv_assign_ptr_type, {Arg->getType()}, + Constant::getNullValue(ElemTy), Arg, + {B.getInt32(getPointerAddressSpace(Arg->getType()))}, B); + DeducedElTys[AssignPtrTyCI] = ElemTy; + DeducedElTys[Arg] = ElemTy; + } + } + } +} + bool SPIRVEmitIntrinsics::runOnFunction(Function &Func) { if (Func.isDeclaration()) return false; @@ -775,6 +929,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..ed0f90ff89ce6e7b3d2e98e3447ff4d50981f6ab 100644 --- a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h +++ b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h @@ -56,6 +56,9 @@ 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; + // Add a new OpTypeXXX instruction without checking for duplicates. SPIRVType *createSPIRVType(const Type *Type, MachineIRBuilder &MIRBuilder, SPIRV::AccessQualifier::AccessQualifier AQ = @@ -91,6 +94,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 +119,9 @@ public: DT.buildDepsGraph(Graph, MMI); } + void setBound(unsigned V) { Bound = V; } + unsigned getBound() { return Bound; } + // 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 @@ -166,6 +180,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 +215,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..55b4c47c197dab00210d0a88fad5ed7de49302cc 100644 --- a/llvm/lib/Target/SPIRV/SPIRVISelLowering.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVISelLowering.cpp @@ -104,11 +104,7 @@ static void validatePtrTypes(const SPIRVSubtarget &STI, 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); + MachineIRBuilder MIB(I); SPIRVType *NewPtrType = GR.getOrCreateSPIRVPointerType(ResType, MIB, SC); if (!GR.isBitcastCompatible(NewPtrType, OpType)) report_fatal_error( @@ -149,6 +145,26 @@ void SPIRVTargetLowering::finalizeLowering(MachineFunction &MF) const { validatePtrTypes(STI, MRI, GR, MI, GR.getSPIRVTypeForVReg(MI.getOperand(1).getReg()), 0); 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..505b19a4d66edb9e9d02d53680ffb2e35ccbced6 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; } 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..41807da6afcbc79b9dc108648cabd8eab60d38ea 100644 --- a/llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp @@ -186,7 +186,9 @@ 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 auto *Global = MI->getOperand(1).getGlobal(); + auto *Ty = TypedPointerType::get(Global->getValueType(), + Global->getType()->getAddressSpace()); SpirvTy = GR->getOrCreateSPIRVType(Ty, MIB); break; } @@ -543,6 +545,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..09a029a35a7445447a1145b939e7d0acd5f4a0ac 100644 --- a/llvm/lib/Target/SPIRV/SPIRVSubtarget.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVSubtarget.cpp @@ -27,6 +27,11 @@ using namespace llvm; #define GET_SUBTARGETINFO_CTOR #include "SPIRVGenSubtargetInfo.inc" +static cl::opt<bool> + SPVTranslatorCompat("translator-compatibility-mode", + cl::desc("SPIR-V Translator compatibility mode"), + cl::Optional, cl::init(false)); + cl::list<SPIRV::Extension::Extension> Extensions( "spirv-extensions", cl::desc("SPIR-V extensions"), cl::ZeroOrMore, cl::Hidden, @@ -157,8 +162,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() { 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..eb87349f0941c5aeff08b9cfb5069cffd684c47f 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,35 @@ 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(); +} + } // 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/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..da4bcd7f0c66edadd61555cff6ab7a8836bc7d22 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); @@ -377,6 +372,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 +918,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 +4266,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 +4276,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 +4284,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 +4359,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 +4369,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 +4530,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 +5663,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 +6080,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 +6163,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 +6223,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 +6451,7 @@ const char *SystemZTargetLowering::getTargetNodeName(unsigned Opcode) const { OPCODE(STRV); OPCODE(VLER); OPCODE(VSTER); + OPCODE(STCKF); OPCODE(PREFETCH); OPCODE(ADA_ENTRY); } @@ -6587,6 +6614,27 @@ SDValue SystemZTargetLowering::combineTruncateExtract( return SDValue(); } +// Replace ALoad with a new ATOMIC_LOAD with a result that is extended to VT +// per ETy. +static SDValue extendAtomicLoad(AtomicSDNode *ALoad, EVT VT, SelectionDAG &DAG, + ISD::LoadExtType ETy) { + if (VT.getSizeInBits() > 64) + return SDValue(); + EVT OrigVT = ALoad->getValueType(0); + assert(OrigVT.getSizeInBits() < VT.getSizeInBits() && "VT should be wider."); + EVT MemoryVT = ALoad->getMemoryVT(); + auto *NewALoad = dyn_cast<AtomicSDNode>(DAG.getAtomic( + ISD::ATOMIC_LOAD, SDLoc(ALoad), MemoryVT, VT, ALoad->getChain(), + ALoad->getBasePtr(), ALoad->getMemOperand())); + NewALoad->setExtensionType(ETy); + 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); +} + SDValue SystemZTargetLowering::combineZERO_EXTEND( SDNode *N, DAGCombinerInfo &DCI) const { // Convert (zext (select_ccmask C1, C2)) into (select_ccmask C1', C2') @@ -6611,6 +6659,34 @@ 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)); + } + } + } + + // Fold into ATOMIC_LOAD unless it is already sign extending. + if (auto *ALoad = dyn_cast<AtomicSDNode>(N0)) + if (ALoad->getOpcode() == ISD::ATOMIC_LOAD && + ALoad->getExtensionType() != ISD::SEXTLOAD) + return extendAtomicLoad(ALoad, VT, DAG, ISD::ZEXTLOAD); + return SDValue(); } @@ -6662,6 +6738,13 @@ SDValue SystemZTargetLowering::combineSIGN_EXTEND( } } } + + // Fold into ATOMIC_LOAD unless it is already zero extending. + if (auto *ALoad = dyn_cast<AtomicSDNode>(N0)) + if (ALoad->getOpcode() == ISD::ATOMIC_LOAD && + ALoad->getExtensionType() != ISD::ZEXTLOAD) + return extendAtomicLoad(ALoad, VT, DAG, ISD::SEXTLOAD); + return SDValue(); } @@ -6929,6 +7012,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; diff --git a/llvm/lib/Target/SystemZ/SystemZISelLowering.h b/llvm/lib/Target/SystemZ/SystemZISelLowering.h index baf4ba4165487948ea36f422c34ba8c54872a551..4943c5cb703c331ddb103647731e6dd37ceffec1 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, 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..2a6dce863c28f114c63f8bb5d57dff01fe21fe3a 100644 --- a/llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp +++ b/llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp @@ -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..96ea65b6c3d881e91c2ddf0dc34edce199efc4fc 100644 --- a/llvm/lib/Target/SystemZ/SystemZInstrInfo.td +++ b/llvm/lib/Target/SystemZ/SystemZInstrInfo.td @@ -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/TargetMachine.cpp b/llvm/lib/Target/TargetMachine.cpp index 8b177a89c9192be7972caa084954f8b2c1b75543..a7fe329b064ee165bf1add1d031f20b3f6d3351c 100644 --- a/llvm/lib/Target/TargetMachine.cpp +++ b/llvm/lib/Target/TargetMachine.cpp @@ -92,7 +92,7 @@ bool TargetMachine::isLargeGlobalValue(const GlobalValue *GVal) const { GV->getName().starts_with("__stop_"))) return true; const DataLayout &DL = GV->getParent()->getDataLayout(); - uint64_t Size = DL.getTypeSizeInBits(GV->getValueType()) / 8; + uint64_t Size = DL.getTypeAllocSize(GV->getValueType()); return Size == 0 || Size > LargeDataThreshold; } 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..020c0d6229d22d2378f43f1098e6ff553963ae76 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; } 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..03897b551ecaee9b87b80abad553dbb29fc8d022 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp @@ -264,7 +264,7 @@ 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)); 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..0427fe473f8e16de6eeaa2d46a248da5a7d840d5 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp @@ -1283,9 +1283,9 @@ bool WebAssemblyLowerEmscriptenEHSjLj::runSjLjOnFunction(Function &F) { 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()); + BinaryOperator *SetjmpTableSize = BinaryOperator::Create( + Instruction::Add, IRB.getInt32(4), IRB.getInt32(0), "setjmpTableSize", + Entry->getTerminator()->getIterator()); SetjmpTableSize->setDebugLoc(FirstDL); // setjmpTable = (int *) malloc(40); Type *IntPtrTy = getAddrIntType(&M); 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/WebAssemblyMachineFunctionInfo.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyMachineFunctionInfo.cpp index 1e959111a4dbcb5215c7a2be61433ada005d80af..d17394eede77253a544365fae87deed3a3c2830d 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyMachineFunctionInfo.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyMachineFunctionInfo.cpp @@ -105,7 +105,7 @@ 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)); diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyMachineFunctionInfo.h b/llvm/lib/Target/WebAssembly/WebAssemblyMachineFunctionInfo.h index fe18347ad8c1da3835ef625ccc1d200a962d07ef..37059188a7614e676150bbeb3d7bbaa6d409977f 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyMachineFunctionInfo.h +++ b/llvm/lib/Target/WebAssembly/WebAssemblyMachineFunctionInfo.h @@ -169,8 +169,7 @@ 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, 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 b4d0421c14c0b6b225fc8f236ec3717a01844dcb..9acbe17d0bcad2743c839f0edce22a3bd428f6a7 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -4070,10 +4070,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 +4095,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 +4107,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 @@ -5858,6 +5859,23 @@ static bool getFauxShuffleMask(SDValue N, const APInt &DemandedElts, Ops.push_back(SubBCSrc); return true; } + // Handle CONCAT(SUB0, SUB1). + // Limit this to vXi64 512-bit vector cases to make the most of AVX512 + // cross lane shuffles. + if (Depth > 0 && InsertIdx == NumSubElts && NumElts == (2 * NumSubElts) && + NumBitsPerElt == 64 && NumSizeInBits == 512 && + Src.getOpcode() == ISD::INSERT_SUBVECTOR && + Src.getOperand(0).isUndef() && + Src.getOperand(1).getValueType() == SubVT && + Src.getConstantOperandVal(2) == 0) { + for (int i = 0; i != (int)NumSubElts; ++i) + Mask.push_back(i); + for (int i = 0; i != (int)NumSubElts; ++i) + Mask.push_back(i + NumElts); + Ops.push_back(Src.getOperand(1)); + Ops.push_back(Sub); + return true; + } // Handle INSERT_SUBVECTOR(SRC0, SHUFFLE(SRC1)). SmallVector<int, 64> SubMask; SmallVector<SDValue, 2> SubInputs; @@ -18575,13 +18593,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 }; @@ -18596,7 +18623,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 @@ -20037,7 +20076,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()) @@ -20618,7 +20657,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 @@ -21473,7 +21512,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(); } @@ -21580,7 +21621,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); @@ -21598,7 +21640,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); @@ -21654,7 +21697,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); @@ -21675,7 +21717,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. @@ -24432,7 +24474,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()) @@ -27795,7 +27837,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()) && @@ -27905,11 +27947,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); @@ -27982,16 +28024,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, @@ -28005,7 +28049,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*. @@ -28067,10 +28111,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); @@ -28081,7 +28126,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); @@ -28091,11 +28135,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(); @@ -28104,13 +28148,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(); @@ -28119,13 +28164,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(); @@ -28282,15 +28328,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(); @@ -28333,10 +28379,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); @@ -28559,10 +28605,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()) || @@ -29740,10 +29786,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(); } @@ -29820,7 +29866,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)) @@ -29982,7 +30028,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. @@ -30018,7 +30064,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 || @@ -31098,11 +31144,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) { @@ -31226,7 +31272,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."); @@ -31265,11 +31311,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) { @@ -33409,6 +33455,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) @@ -35189,6 +35236,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); @@ -36189,6 +36237,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: @@ -42624,7 +42674,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. @@ -42632,15 +42681,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( @@ -47334,6 +47396,16 @@ static SDValue combineShiftRightArithmetic(SDNode *N, SelectionDAG &DAG, if (SDValue V = combineShiftToPMULH(N, DAG, Subtarget)) return V; + 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 (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])) @@ -47630,16 +47702,12 @@ static SDValue combineVectorPack(SDNode *N, SelectionDAG &DAG, // PACKSS: Truncate signed value with signed saturation. // Source values less than dst minint are saturated to minint. // Source values greater than dst maxint are saturated to maxint. - if (Val.isSignedIntN(DstBitsPerElt)) - Val = Val.trunc(DstBitsPerElt); - else if (Val.isNegative()) - Val = APInt::getSignedMinValue(DstBitsPerElt); - else - Val = APInt::getSignedMaxValue(DstBitsPerElt); + Val = Val.truncSSat(DstBitsPerElt); } else { // PACKUS: Truncate signed value with unsigned saturation. // Source values less than zero are saturated to zero. // Source values greater than dst maxuint are saturated to maxuint. + // NOTE: This is different from APInt::truncUSat. if (Val.isIntN(DstBitsPerElt)) Val = Val.trunc(DstBitsPerElt); else if (Val.isNegative()) @@ -55920,7 +55988,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/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..eb42a4b2119d5e4e6911fbbdf8d8cc7865e91402 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) @@ -10565,15 +10577,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 +10593,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/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/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..e9bdc6ab5beaeacd05ec82cf5d44f8dcf88225c1 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; 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/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/DylibReader.cpp b/llvm/lib/TextAPI/BinaryReader/DylibReader.cpp index 0694d8f28df6bd816d6d352b9e75fb97b830509f..2e36d4a8b98ce0ccdbf7f57e4360e1a02de48e42 100644 --- a/llvm/lib/TextAPI/BinaryReader/DylibReader.cpp +++ b/llvm/lib/TextAPI/BinaryReader/DylibReader.cpp @@ -293,8 +293,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) { 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/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/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/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..9a8040bc4b064efe93258d4c2de057eb5aace078 100644 --- a/llvm/lib/Transforms/IPO/SampleProfile.cpp +++ b/llvm/lib/Transforms/IPO/SampleProfile.cpp @@ -1167,6 +1167,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; } 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..a978e9a643f5e924a8b27d2665fd1b3e7fe522dc 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); diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp index f5f3716d390d7738b35f097144f2771bd01bba2f..526fe5d080599f8fc7d68b6ac5118516752cd5ab 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) { @@ -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 diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp index 45afa6363ae01f3e09fa03333b7bdf9838b4599e..089a70c6e6cca140d064333fb4018b7f9496faa7 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp @@ -1121,6 +1121,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 +1923,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 +1950,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 e71f3e113b96e8cb2f4047858be71502f583f8e8..db302d7e5268447e73ea7a62eaf000fe88536919 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -4113,9 +4113,12 @@ static bool isMaskOrZero(const Value *V, bool Not, const SimplifyQuery &Q, if (match(V, m_Not(m_Value(X)))) return isMaskOrZero(X, !Not, Q, Depth); + // (X ^ -X) is a ~Mask + if (Not) + return match(V, m_c_Xor(m_Value(X), m_Neg(m_Deferred(X)))); // (X ^ (X - 1)) is a Mask - return !Not && - match(V, m_c_Xor(m_Value(X), m_Add(m_Deferred(X), m_AllOnes()))); + else + return match(V, m_c_Xor(m_Value(X), m_Add(m_Deferred(X), m_AllOnes()))); case Instruction::Select: // c ? Mask0 : Mask1 is a Mask. return isMaskOrZero(I->getOperand(1), Not, Q, Depth) && @@ -4174,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 @@ -4186,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); @@ -4277,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..10a4b1c2060c8d76d82695e71abbe07fecda642f 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp @@ -448,6 +448,14 @@ 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, "", /*HasNUW=*/false, I.hasNoSignedWrap()), + ConstantInt::getNullValue(Op0->getType())); + Constant *ImmC; if (match(Op1, m_ImmConstant(ImmC))) { // (sext bool X) * C --> X ? -C : 0 @@ -571,6 +579,42 @@ 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); + + return nullptr; +} + Instruction *InstCombinerImpl::foldFMulReassoc(BinaryOperator &I) { Value *Op0 = I.getOperand(0); Value *Op1 = I.getOperand(1); @@ -683,6 +727,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 +746,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 +814,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 +1171,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))); } 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..3c95610fa3e80bcaa46a0a4a4ba3903bbf87c0f1 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()); @@ -450,7 +447,7 @@ private: Value *ShadowBase = nullptr; Value *StackBaseTag = nullptr; - Value *CachedSP = nullptr; + Value *CachedFP = nullptr; GlobalValue *ThreadPtrGlobal = nullptr; }; @@ -595,8 +592,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 +609,6 @@ void HWAddressSanitizer::initializeModule() { C = &(M.getContext()); IRBuilder<> IRB(*C); - IntptrTy = IRB.getIntPtrTy(DL); - PtrTy = IRB.getPtrTy(); HwasanCtorFunction = nullptr; @@ -625,19 +618,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 +637,17 @@ 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); if (!CompileKernel) { createHwasanCtorComdat(); - bool InstrumentGlobals = - ClGlobals.getNumOccurrences() ? ClGlobals : NewRuntime; + bool InstrumentGlobals = optOr(ClGlobals, NewRuntime); if (InstrumentGlobals && !UsePageAliases) instrumentGlobals(); bool InstrumentPersonalityFunctions = - ClInstrumentPersonalityFunctions.getNumOccurrences() - ? ClInstrumentPersonalityFunctions - : NewRuntime; + optOr(ClInstrumentPersonalityFunctions, NewRuntime); if (InstrumentPersonalityFunctions) instrumentPersonalityFunctions(); } @@ -1174,10 +1157,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 +1174,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 +1219,31 @@ 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) { + if (TargetTriple.isAArch64() && TargetTriple.isAndroid()) + return memtag::getAndroidSanitizerSlotPtr(IRB); + 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 +1261,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 @@ -1371,38 +1328,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 +1399,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 +1600,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/PGOInstrumentation.cpp b/llvm/lib/Transforms/Instrumentation/PGOInstrumentation.cpp index 55728709cde556768f3a66a3d48eb70b17b1e2c9..50eccc69a38a00127f199b39557eb4aab1b802d2 100644 --- a/llvm/lib/Transforms/Instrumentation/PGOInstrumentation.cpp +++ b/llvm/lib/Transforms/Instrumentation/PGOInstrumentation.cpp @@ -920,7 +920,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. 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/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/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/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/LoopSimplifyCFG.cpp b/llvm/lib/Transforms/Scalar/LoopSimplifyCFG.cpp index 028a487ecdbc2833d1c7b174d034d97d57a47a77..ae9103d0608a11bf275c9b20b3514c1332f36f67 100644 --- a/llvm/lib/Transforms/Scalar/LoopSimplifyCFG.cpp +++ b/llvm/lib/Transforms/Scalar/LoopSimplifyCFG.cpp @@ -16,7 +16,6 @@ #include "llvm/Transforms/Scalar/LoopSimplifyCFG.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/Statistic.h" -#include "llvm/Analysis/DependenceAnalysis.h" #include "llvm/Analysis/DomTreeUpdater.h" #include "llvm/Analysis/LoopInfo.h" #include "llvm/Analysis/LoopIterator.h" diff --git a/llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp b/llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp index 8b078ddc4e747e54b8a051615528c1b38754c7bc..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) @@ -6971,6 +6971,7 @@ static bool ReduceLoopStrength(Loop *L, IVUsers &IU, ScalarEvolution &SE, Rewriter.setDebugType(DEBUG_TYPE); #endif unsigned numFolded = Rewriter.replaceCongruentIVs(L, &DT, DeadInsts, &TTI); + Rewriter.clear(); if (numFolded) { Changed = true; RecursivelyDeleteTriviallyDeadInstructionsPermissive(DeadInsts, &TLI, @@ -6989,6 +6990,7 @@ static bool ReduceLoopStrength(Loop *L, IVUsers &IU, ScalarEvolution &SE, SCEVExpander Rewriter(SE, DL, "lsr", true); int Rewrites = rewriteLoopExitValues(L, &LI, &TLI, &SE, &TTI, Rewriter, &DT, UnusedIndVarInLoop, DeadInsts); + Rewriter.clear(); if (Rewrites) { Changed = true; RecursivelyDeleteTriviallyDeadInstructionsPermissive(DeadInsts, &TLI, 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/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..5efc340da60b39d8c92b107ea02edc3b9201d539 100644 --- a/llvm/lib/Transforms/Scalar/SpeculativeExecution.cpp +++ b/llvm/lib/Transforms/Scalar/SpeculativeExecution.cpp @@ -263,7 +263,8 @@ static InstructionCost ComputeSpeculationCost(const Instruction *I, bool SpeculativeExecutionPass::considerHoistingFromTo( BasicBlock &FromBlock, BasicBlock &ToBlock) { SmallPtrSet<const Instruction *, 8> NotHoisted; - SmallDenseMap<const Instruction *, SmallVector<DPValue *>> DPValuesToHoist; + SmallDenseMap<const Instruction *, SmallVector<DbgVariableRecord *>> + DbgVariableRecordsToHoist; auto HasNoUnhoistedInstr = [&NotHoisted](auto Values) { for (const Value *V : Values) { if (const auto *I = dyn_cast_or_null<Instruction>(V)) @@ -291,11 +292,11 @@ bool SpeculativeExecutionPass::considerHoistingFromTo( InstructionCost TotalSpeculationCost = 0; unsigned NotHoistedInstCount = 0; for (const auto &I : FromBlock) { - // Make note of any DPValues that need hoisting. DPLabels + // Make note of any DbgVariableRecords that need hoisting. DbgLabelRecords // 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); + for (DbgVariableRecord &DVR : filterDbgVars(I.getDbgRecordRange())) { + if (HasNoUnhoistedInstr(DVR.location_ops())) + DbgVariableRecordsToHoist[DVR.getInstruction()].push_back(&DVR); } const InstructionCost Cost = ComputeSpeculationCost(&I, *TTI); if (Cost.isValid() && isSafeToSpeculativelyExecute(&I) && @@ -314,13 +315,13 @@ 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 + // If any DbgVariableRecords 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, + if (DbgVariableRecordsToHoist.contains(&*I)) { + for (auto *DVR : DbgVariableRecordsToHoist[&*I]) { + DVR->removeFromParent(); + ToBlock.insertDbgRecordBefore(DVR, ToBlock.getTerminator()->getIterator()); } } 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..3191751d92e1768d4c5c90057c5879222bd840a3 100644 --- a/llvm/lib/Transforms/Utils/CodeExtractor.cpp +++ b/llvm/lib/Transforms/Utils/CodeExtractor.cpp @@ -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 @@ -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..3d3b97eca92b3dd557620e8cf473d18a2ad3f8b9 100644 --- a/llvm/lib/Transforms/Utils/Local.cpp +++ b/llvm/lib/Transforms/Utils/Local.cpp @@ -609,12 +609,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 +1570,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 +1617,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 +1643,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 +1707,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 +1720,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 +1747,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 +1775,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 +1793,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 +1827,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 +1855,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 +1872,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 +1910,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 +1966,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 +1981,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 +1991,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 +2032,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 +2046,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 +2064,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 +2126,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 +2137,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 +2165,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 +2183,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 +2234,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 +2300,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 +2371,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 +2588,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 +2600,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 +2619,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 +2644,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 +2715,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 +2735,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 +2751,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 +2762,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 +2806,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 +2859,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 +3555,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..bc6711711371997208d9b5f2754fc823aab513d2 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); } } } @@ -552,20 +552,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 +579,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 +629,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 +656,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 +782,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..fd94a120bc66559101092c498fb14869f555ca0e 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 *getAndroidSanitizerSlotPtr(IRBuilder<> &IRB) { + 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), 0x30); +} + } // 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/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..e86705e8988904da3986b5a3c17184e9ede272a9 100644 --- a/llvm/lib/Transforms/Vectorize/LoopVectorizationPlanner.h +++ b/llvm/lib/Transforms/Vectorize/LoopVectorizationPlanner.h @@ -79,6 +79,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 +138,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 +148,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); } diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp index edaad4d033bdf06261a6272c4ec1fb841c8382a0..28748142ae9255c85a73954aa10a28216d9d9b10 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.getVPValueOrAddLiveIn(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) @@ -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"); @@ -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 @@ -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.getVPValueOrAddLiveIn(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.getVPValueOrAddLiveIn(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); - - // Always record recipes for header phis. Later first-order recurrence phis - // can have earlier phis as incoming values. - recordRecipeOf(Phi); + return tryToBlend(Phi, Operands); - 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, @@ -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. @@ -8662,7 +8644,7 @@ LoopVectorizationPlanner::tryToBuildVPlanWithVPRecipes(VFRange &Range) { Operands.push_back(Plan->getVPValueOrAddLiveIn( 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() && @@ -8780,10 +8758,6 @@ LoopVectorizationPlanner::tryToBuildVPlanWithVPRecipes(VFRange &Range) { Plan->getVPValueOrAddLiveIn(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); }); diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp index 7b99c3ac8c55a5f65e5fe6853671e8ef6be1471d..f98d15c285a693e4365b39caadd1e69f4a0e8829 100644 --- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp +++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp @@ -1001,8 +1001,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 +1086,9 @@ public: BS->clear(); } MinBWs.clear(); + ReductionBitWidth = 0; + CastMaxMinBWSizes.reset(); + TruncNodes.clear(); InstrElementSize.clear(); UserIgnoreList = nullptr; PostponedGathers.clear(); @@ -2235,7 +2239,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 +2291,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 +2312,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 +2382,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, @@ -2925,11 +2936,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 +3072,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 +3643,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 +3651,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 +4329,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 +4350,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)) || @@ -6539,6 +6577,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"); @@ -7400,7 +7458,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); @@ -7673,9 +7731,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; } @@ -7690,16 +7752,22 @@ class BoUpSLP::ShuffleCostEstimator : public BaseShuffleAnalysis { bool NeedShuffle = count(VL, *It) > 1 && (VL.front() != *It || !all_of(VL.drop_front(), UndefValue::classof)); + 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) @@ -8362,6 +8430,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 +8468,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 +8526,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 +8579,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 +8595,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,7 +8642,7 @@ 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(); @@ -8740,13 +8810,7 @@ BoUpSLP::getEntryCost(const TreeEntry *E, ArrayRef<Value *> VectorizedVals, } } 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 +8853,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 +8908,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 +8916,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 +8927,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 +8972,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); @@ -9211,11 +9275,18 @@ 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) && + (IsAllowedSingleBVNode && + !V->hasNUsesOrMore(UsesLimit) && any_of(V->users(), [](User *U) { return isa<InsertElementInst>(U); })); @@ -9772,6 +9843,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 +10162,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()) @@ -10374,7 +10478,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,27 +10487,34 @@ 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; } @@ -10614,8 +10725,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 +10748,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 +10789,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 +10854,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 +10941,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); } @@ -11656,7 +11808,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 +11827,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 +11854,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 +11892,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 +11926,10 @@ 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((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 +11944,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 +11954,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 +12140,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()) @@ -12003,7 +12163,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 +12184,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 +12207,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 +12231,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 +12267,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,12 +12304,17 @@ 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( @@ -12143,7 +12324,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; @@ -12214,7 +12395,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 +12406,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 +12451,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 +12475,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 +12493,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 +12523,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 +12555,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; @@ -12421,9 +12631,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 +12726,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 +12755,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 +12786,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 +12815,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 +12832,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 +12895,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 +13154,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() { @@ -13748,36 +13988,116 @@ 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; break; case Instruction::ZExt: case Instruction::SExt: - if (isa<ExtractElementInst, InsertElementInst>(I->getOperand(0))) - return false; + if (!IsTruncRoot) + MaxDepthLevel = 1; + IsProfitableToDemote = true; break; // We can demote certain binary operations if we can demote both of their @@ -13787,22 +14107,86 @@ 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; + } // 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 +14195,267 @@ 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; + if (NodeIdx != 0 && + VectorizableTree[NodeIdx]->State == TreeEntry::Vectorize && + (VectorizableTree[NodeIdx]->getOpcode() == Instruction::ZExt || + VectorizableTree[NodeIdx]->getOpcode() == Instruction::SExt || + VectorizableTree[NodeIdx]->getOpcode() == Instruction::Trunc)) { + assert(IsStoreOrInsertElt && "Expected store/insertelement seeded graph."); + IsTruncRoot = VectorizableTree[NodeIdx]->getOpcode() == Instruction::Trunc; + 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) { + ++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); + IsTopRoot = false; + IsProfitableToDemoteRoot = true; + + if (TruncNodes.empty()) { + NodeIdx = VectorizableTree.size(); + } else { + NodeIdx = *TruncNodes.begin() + 1; + TruncNodes.erase(TruncNodes.begin()); + 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, Constant::classof)) + MinBWs.try_emplace(CTE, MaxBitWidth, IsSigned); } } } @@ -14658,10 +15137,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 +15161,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,7 +15199,7 @@ 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 = @@ -15119,7 +15581,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 +15607,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. @@ -15495,7 +15959,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 +16290,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 +16705,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) { @@ -16614,36 +17078,11 @@ bool SLPVectorizerPass::vectorizeChainsInBlock(BasicBlock *BB, BoUpSLP &R) { if (Opcodes1.size() > Opcodes2.size()) return false; for (int I = 0, E = Opcodes1.size(); I < E; ++I) { - // Undefs are compatible with any other value. - if (isa<UndefValue>(Opcodes1[I]) || isa<UndefValue>(Opcodes2[I])) { - if (isa<UndefValue>(Opcodes1[I]) && isa<UndefValue>(Opcodes2[I])) - continue; - if (isa<Instruction>(Opcodes1[I])) { - assert(isa<UndefValue>(Opcodes2[I]) && "Expected 2nd undef value"); - return true; - } - if (isa<Instruction>(Opcodes2[I])) { - assert(isa<UndefValue>(Opcodes1[I]) && "Expected 1st undef value"); - return false; - } - if (isa<Constant>(Opcodes1[I]) && !isa<UndefValue>(Opcodes1[I])) { - assert(isa<UndefValue>(Opcodes2[I]) && "Expected 2nd undef value"); - return true; - } - if (isa<Constant>(Opcodes2[I]) && !isa<UndefValue>(Opcodes2[I])) { - assert(isa<UndefValue>(Opcodes1[I]) && "Expected 1st undef value"); - return false; - } - if (!isa<UndefValue>(Opcodes2[I])) { - assert(isa<UndefValue>(Opcodes1[I]) && "Expected 1st undef value"); - return false; - } - assert(!isa<UndefValue>(Opcodes1[I]) && isa<UndefValue>(Opcodes2[I]) && - "Expected 1st non-undef and 2nd undef value"); - return true; - } - if (auto *I1 = dyn_cast<Instruction>(Opcodes1[I])) - if (auto *I2 = dyn_cast<Instruction>(Opcodes2[I])) { + { + // Instructions come first. + auto *I1 = dyn_cast<Instruction>(Opcodes1[I]); + auto *I2 = dyn_cast<Instruction>(Opcodes2[I]); + if (I1 && I2) { DomTreeNodeBase<BasicBlock> *NodeI1 = DT->getNode(I1->getParent()); DomTreeNodeBase<BasicBlock> *NodeI2 = DT->getNode(I2->getParent()); if (!NodeI1) @@ -16660,20 +17099,44 @@ bool SLPVectorizerPass::vectorizeChainsInBlock(BasicBlock *BB, BoUpSLP &R) { continue; return I1->getOpcode() < I2->getOpcode(); } - if (isa<Constant>(Opcodes1[I]) && isa<Constant>(Opcodes2[I])) - continue; - if (isa<Instruction>(Opcodes1[I]) && !isa<Instruction>(Opcodes2[I])) - return true; - if (!isa<Instruction>(Opcodes1[I]) && isa<Instruction>(Opcodes2[I])) - return false; - if (isa<Constant>(Opcodes1[I]) && !isa<Constant>(Opcodes2[I])) - return true; - if (!isa<Constant>(Opcodes1[I]) && isa<Constant>(Opcodes2[I])) - return false; - if (Opcodes1[I]->getValueID() < Opcodes2[I]->getValueID()) - return true; - if (Opcodes1[I]->getValueID() > Opcodes2[I]->getValueID()) - return false; + if (I1) + return true; + if (I2) + return false; + } + { + // Non-undef constants come next. + bool C1 = isa<Constant>(Opcodes1[I]) && !isa<UndefValue>(Opcodes1[I]); + bool C2 = isa<Constant>(Opcodes2[I]) && !isa<UndefValue>(Opcodes2[I]); + if (C1 && C2) + continue; + if (C1) + return true; + if (C2) + return false; + } + bool U1 = isa<UndefValue>(Opcodes1[I]); + bool U2 = isa<UndefValue>(Opcodes2[I]); + { + // Non-constant non-instructions come next. + if (!U1 && !U2) { + auto ValID1 = Opcodes1[I]->getValueID(); + auto ValID2 = Opcodes2[I]->getValueID(); + if (ValID1 == ValID2) + continue; + if (ValID1 < ValID2) + return true; + if (ValID1 > ValID2) + return false; + } + if (!U1) + return true; + if (!U2) + return false; + } + // Undefs come last. + assert(U1 && U2 && "The only thing left should be undef & undef."); + continue; } return false; }; diff --git a/llvm/lib/Transforms/Vectorize/VPRecipeBuilder.h b/llvm/lib/Transforms/Vectorize/VPRecipeBuilder.h index b1498026adadfef30852a5ccaa959b7fdbea7e13..fbb70f333685d70bfd755c728cec3572f69c65c9 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.getVPValueOrAddLiveIn(V); + } }; } // end namespace llvm diff --git a/llvm/lib/Transforms/Vectorize/VPlan.h b/llvm/lib/Transforms/Vectorize/VPlan.h index af6d0081bffebc4c59d0543725b0455e1747d79e..ba4992a7dcc966f559e1b3b0eafb34e8bc3c0e37 100644 --- a/llvm/lib/Transforms/Vectorize/VPlan.h +++ b/llvm/lib/Transforms/Vectorize/VPlan.h @@ -1265,6 +1265,7 @@ public: default: return false; case VPInstruction::BranchOnCount: + case VPInstruction::CanonicalIVIncrementForPart: return true; }; llvm_unreachable("switch should return"); @@ -2136,6 +2137,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. @@ -2870,10 +2873,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 +2951,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) { @@ -2985,8 +2980,7 @@ 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(VPV->isLiveIn() && "VPV must be a live-in."); assert(V && "Trying to add a null Value to VPlan"); assert(!Value2VPValue.count(V) && "Value already exists in VPlan"); Value2VPValue[V] = VPV; @@ -2996,8 +2990,8 @@ public: 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!"); + assert(Value2VPValue[V]->isLiveIn() && + "Only live-ins should be in mapping"); return Value2VPValue[V]; } @@ -3028,16 +3022,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/VPlanHCFGBuilder.cpp b/llvm/lib/Transforms/Vectorize/VPlanHCFGBuilder.cpp index 6474a9697dce893df68d5c11e3c5936aeb44d7e7..877b5d438115de891e268c7753e7450f4e39ea1c 100644 --- a/llvm/lib/Transforms/Vectorize/VPlanHCFGBuilder.cpp +++ b/llvm/lib/Transforms/Vectorize/VPlanHCFGBuilder.cpp @@ -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. diff --git a/llvm/lib/Transforms/Vectorize/VPlanPatternMatch.h b/llvm/lib/Transforms/Vectorize/VPlanPatternMatch.h index b90c588b6075642daa4cf3124f92633beaf80fa1..aa253590694514ac95f8b65b4747233726b2e626 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,47 @@ 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); +} + } // namespace VPlanPatternMatch } // namespace llvm diff --git a/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp b/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp index d75e322a74cfa639bc16319fecb03c5fbf801150..f91997a37993d14952c388e6e72f6eb6c55b2e67 100644 --- a/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp +++ b/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp @@ -345,6 +345,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); diff --git a/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp b/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp index f6b564ad931ca9e66e1ded64630a76691ffbf179..00cec114852818cffdcff167eef806f8a958a68e 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->getVPValueOrAddLiveIn(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"); @@ -156,8 +155,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. @@ -815,27 +813,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 +826,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 +837,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 +868,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. @@ -1192,10 +1158,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 diff --git a/llvm/lib/Transforms/Vectorize/VectorCombine.cpp b/llvm/lib/Transforms/Vectorize/VectorCombine.cpp index dc669e314a0d9ac9162fa8959843a54aeddfe58b..7e86137f23f3c8973fbb99dcb9cf295779ab9ba3 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. @@ -181,7 +182,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 +189,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 +215,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 +227,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 +298,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 +683,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 +695,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 +723,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(V0, NewShuffleTy); + Value *CastV1 = Builder.CreateBitCast(V1, NewShuffleTy); + Value *Shuf = Builder.CreateShuffleVector(CastV0, CastV1, NewMask); replaceValue(I, *Shuf); return true; } @@ -786,9 +801,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 +853,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 +865,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 +1244,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 +1267,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 +1285,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 +1363,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 +2038,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..678d6d246e639ccc5e3fa0aee88c3ce422c7eaed 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: 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/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/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/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/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/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-4.0.ll b/llvm/test/Bitcode/compatibility-4.0.ll index da5ea0e19639c1b2285d88b92bd8e20d2fb359fb..06cb842059a4fa217592ea9acadf5056c83c790f 100644 --- a/llvm/test/Bitcode/compatibility-4.0.ll +++ b/llvm/test/Bitcode/compatibility-4.0.ll @@ -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) } diff --git a/llvm/test/Bitcode/compatibility-5.0.ll b/llvm/test/Bitcode/compatibility-5.0.ll index 7a39ae6256b80598eb150557c777879483f133cb..f9ae558917cddcc0fc5349434aa4ec1695393608 100644 --- a/llvm/test/Bitcode/compatibility-5.0.ll +++ b/llvm/test/Bitcode/compatibility-5.0.ll @@ -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) } diff --git a/llvm/test/Bitcode/compatibility-6.0.ll b/llvm/test/Bitcode/compatibility-6.0.ll index 4cb1f3bd123cb10bb815d068ca03f74e70d4bbb9..1458e1b639ad44bf3a1dabcb9e62d82592a721fc 100644 --- a/llvm/test/Bitcode/compatibility-6.0.ll +++ b/llvm/test/Bitcode/compatibility-6.0.ll @@ -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) } diff --git a/llvm/test/Bitcode/compatibility.ll b/llvm/test/Bitcode/compatibility.ll index ce6a6571ec144cca799d5759e9eda0330d519ceb..fa8b0520567a6f966cd633123ae53b1e2a0cdeb5 100644 --- a/llvm/test/Bitcode/compatibility.ll +++ b/llvm/test/Bitcode/compatibility.ll @@ -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 { 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/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/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/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-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-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-xtn.mir b/llvm/test/CodeGen/AArch64/GlobalISel/legalize-xtn.mir index 661265173ae82b6bdfb0a6ced20cfc74607690ac..ed40a2ff7ea70f2832e74723f97d7a85e77574da 100644 --- a/llvm/test/CodeGen/AArch64/GlobalISel/legalize-xtn.mir +++ b/llvm/test/CodeGen/AArch64/GlobalISel/legalize-xtn.mir @@ -540,9 +540,17 @@ 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: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY]](<2 x s32>) + ; CHECK-NEXT: [[DEF:%[0-9]+]]:_(s32) = G_IMPLICIT_DEF + ; CHECK-NEXT: [[BUILD_VECTOR:%[0-9]+]]:_(<4 x s32>) = G_BUILD_VECTOR [[UV]](s32), [[UV1]](s32), [[DEF]](s32), [[DEF]](s32) + ; CHECK-NEXT: [[BUILD_VECTOR1:%[0-9]+]]:_(<4 x s32>) = G_BUILD_VECTOR [[DEF]](s32), [[DEF]](s32), [[DEF]](s32), [[DEF]](s32) + ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(<4 x s16>) = G_TRUNC [[BUILD_VECTOR]](<4 x s32>) + ; CHECK-NEXT: [[TRUNC1:%[0-9]+]]:_(<4 x s16>) = G_TRUNC [[BUILD_VECTOR1]](<4 x s32>) + ; CHECK-NEXT: [[CONCAT_VECTORS:%[0-9]+]]:_(<8 x s16>) = G_CONCAT_VECTORS [[TRUNC]](<4 x s16>), [[TRUNC1]](<4 x s16>) + ; CHECK-NEXT: [[TRUNC2:%[0-9]+]]:_(<8 x s8>) = G_TRUNC [[CONCAT_VECTORS]](<8 x s16>) + ; CHECK-NEXT: [[UV2:%[0-9]+]]:_(<2 x s8>), [[UV3:%[0-9]+]]:_(<2 x s8>), [[UV4:%[0-9]+]]:_(<2 x s8>), [[UV5:%[0-9]+]]:_(<2 x s8>) = G_UNMERGE_VALUES [[TRUNC2]](<8 x s8>) + ; CHECK-NEXT: [[CONCAT_VECTORS1:%[0-9]+]]:_(<4 x s8>) = G_CONCAT_VECTORS [[UV2]](<2 x s8>), [[UV2]](<2 x s8>) + ; CHECK-NEXT: [[ANYEXT:%[0-9]+]]:_(<4 x s16>) = G_ANYEXT [[CONCAT_VECTORS1]](<4 x s8>) ; CHECK-NEXT: $d0 = COPY [[ANYEXT]](<4 x s16>) ; CHECK-NEXT: RET_ReallyLR implicit $d0 %0:_(<2 x s32>) = COPY $d0 diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir b/llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir index ac330918b430a0ca4b6f1ea66abfc178cd06a747..ac3c47c8001d4a4764c1ea78200828d173b9c848 100644 --- a/llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir +++ b/llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir @@ -616,6 +616,9 @@ # DEBUG-NEXT: G_BRJT (opcode {{[0-9]+}}): 2 type indices # DEBUG-NEXT: .. the first uncovered type index: 2, OK # DEBUG-NEXT: .. the first uncovered imm index: 0, OK +# DEBUG-NEXT: G_VSCALE (opcode {{[0-9]+}}): 1 type index, 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_INSERT_SUBVECTOR (opcode {{[0-9]+}}): 2 type indices, 1 imm index # DEBUG-NEXT: .. type index coverage check SKIPPED: no rules defined # DEBUG-NEXT: .. imm index coverage check SKIPPED: no rules defined @@ -749,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/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/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/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/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-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-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..b7c02d6855a9e9ed3830249272d4a6d7ad974511 100644 --- a/llvm/test/CodeGen/AArch64/bitcast.ll +++ b/llvm/test/CodeGen/AArch64/bitcast.ll @@ -4,12 +4,10 @@ ; 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 +; CHECK-GI: warning: Instruction selection used fallback path for bitcast_i32_v4i8 +; 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: @@ -54,15 +52,28 @@ 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 @@ -81,18 +92,27 @@ define <4 x i8> @bitcast_i32_v4i8(i32 %a, i32 %b){ } 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 @@ -388,7 +408,7 @@ define <2 x i16> @bitcast_v4i8_v2i16(<4 x i8> %a, <4 x i8> %b){ ; 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: uzp1 v0.8b, v0.8b, v0.8b ; CHECK-NEXT: str s0, [sp, #12] ; CHECK-NEXT: ld1 { v0.h }[0], [x8] ; CHECK-NEXT: orr x8, x8, #0x2 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/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..c5c525a15ad9bef2efd44303067f8264527baa64 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/extract-vector-elt.ll @@ -0,0 +1,1126 @@ +; 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-SD-LABEL: extract_v2i64_undef_vector: +; CHECK-SD: // %bb.0: // %entry +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: extract_v2i64_undef_vector: +; 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: 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> 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 v0.d[0], x0 +; 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/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..79502121f3689b3de848051a94343f47a8c8c72a 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) { + %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) { + %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) { + %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) { + %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) { + %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) { + %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) { + %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) { + %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..7af01b53dae7e8e44fc2c86c13dd684645e28e0f 100644 --- a/llvm/test/CodeGen/AArch64/fptoi.ll +++ b/llvm/test/CodeGen/AArch64/fptoi.ll @@ -1096,30 +1096,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 +1121,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 +1146,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 +1167,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 +1584,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 +1621,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 +1654,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 +1675,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 +1698,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 +1727,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 +1760,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 +1803,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 +1858,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 +1939,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 +2952,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 +2973,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 +2996,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 +3054,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: 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..ceac37f91238a89e01f782442ef09ae883845d0d 100644 --- a/llvm/test/CodeGen/AArch64/itofp.ll +++ b/llvm/test/CodeGen/AArch64/itofp.ll @@ -5521,7 +5521,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,12 +5581,13 @@ 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: movi d1, #0x0000ff000000ff -; 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] -; CHECK-GI-FP16-NEXT: ucvtf v0.4h, v0.4h -; CHECK-GI-FP16-NEXT: mov h1, v0.h[1] +; CHECK-GI-FP16-NEXT: // kill: def $d0 killed $d0 def $q0 +; CHECK-GI-FP16-NEXT: mov w8, v0.s[1] +; CHECK-GI-FP16-NEXT: fmov w9, s0 +; CHECK-GI-FP16-NEXT: and w9, w9, #0xff +; CHECK-GI-FP16-NEXT: and w8, w8, #0xff +; CHECK-GI-FP16-NEXT: ucvtf h0, w9 +; CHECK-GI-FP16-NEXT: ucvtf h1, w8 ; CHECK-GI-FP16-NEXT: mov v0.h[1], v1.h[0] ; CHECK-GI-FP16-NEXT: // kill: def $d0 killed $d0 killed $q0 ; CHECK-GI-FP16-NEXT: ret 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/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-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/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..6a337bf02e09b91112b118836a0116b9ce94a097 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,20 @@ 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 x8, x8, #6 +; CHECK-GI-NEXT: cmp x8, #1 +; CHECK-GI-NEXT: cset w0, eq +; 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 +79,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/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-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-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/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/irtranslator-call-non-fixed.ll b/llvm/test/CodeGen/AMDGPU/GlobalISel/irtranslator-call-non-fixed.ll index 5effd24a752088d696d4849ea90e6847419b05c0..fad833c0a6ad5e8b2c6b46af06b67d72aff977e3 100644 --- a/llvm/test/CodeGen/AMDGPU/GlobalISel/irtranslator-call-non-fixed.ll +++ b/llvm/test/CodeGen/AMDGPU/GlobalISel/irtranslator-call-non-fixed.ll @@ -50,10 +50,10 @@ define amdgpu_gfx void @test_gfx_call_external_void_func_i32_imm_inreg(i32 inreg ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 42 ; CHECK-NEXT: ADJCALLSTACKUP 0, 0, implicit-def $scc ; CHECK-NEXT: [[GV:%[0-9]+]]:_(p0) = G_GLOBAL_VALUE @external_gfx_void_func_i32_inreg - ; CHECK-NEXT: $sgpr4 = COPY [[C]](s32) + ; CHECK-NEXT: $sgpr0 = COPY [[C]](s32) ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(<4 x s32>) = COPY $sgpr0_sgpr1_sgpr2_sgpr3 ; CHECK-NEXT: $sgpr0_sgpr1_sgpr2_sgpr3 = COPY [[COPY1]](<4 x s32>) - ; CHECK-NEXT: $sgpr30_sgpr31 = noconvergent G_SI_CALL [[GV]](p0), @external_gfx_void_func_i32_inreg, csr_amdgpu_si_gfx, implicit $sgpr4, implicit $sgpr0_sgpr1_sgpr2_sgpr3 + ; CHECK-NEXT: $sgpr30_sgpr31 = noconvergent G_SI_CALL [[GV]](p0), @external_gfx_void_func_i32_inreg, csr_amdgpu_si_gfx, implicit $sgpr0, implicit $sgpr0_sgpr1_sgpr2_sgpr3 ; CHECK-NEXT: ADJCALLSTACKDOWN 0, 0, implicit-def $scc ; CHECK-NEXT: SI_RETURN call amdgpu_gfx void @external_gfx_void_func_i32_inreg(i32 inreg 42) @@ -99,11 +99,11 @@ define amdgpu_gfx void @test_gfx_call_external_void_func_struct_i8_i32_inreg() # ; CHECK-NEXT: [[GV:%[0-9]+]]:_(p0) = G_GLOBAL_VALUE @external_gfx_void_func_struct_i8_i32_inreg ; CHECK-NEXT: [[ANYEXT:%[0-9]+]]:_(s16) = G_ANYEXT [[LOAD1]](s8) ; CHECK-NEXT: [[ANYEXT1:%[0-9]+]]:_(s32) = G_ANYEXT [[ANYEXT]](s16) - ; CHECK-NEXT: $sgpr4 = COPY [[ANYEXT1]](s32) - ; CHECK-NEXT: $sgpr5 = COPY [[LOAD2]](s32) + ; CHECK-NEXT: $sgpr0 = COPY [[ANYEXT1]](s32) + ; CHECK-NEXT: $sgpr1 = COPY [[LOAD2]](s32) ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(<4 x s32>) = COPY $sgpr0_sgpr1_sgpr2_sgpr3 ; CHECK-NEXT: $sgpr0_sgpr1_sgpr2_sgpr3 = COPY [[COPY]](<4 x s32>) - ; CHECK-NEXT: $sgpr30_sgpr31 = noconvergent G_SI_CALL [[GV]](p0), @external_gfx_void_func_struct_i8_i32_inreg, csr_amdgpu_si_gfx, implicit $sgpr4, implicit $sgpr5, implicit $sgpr0_sgpr1_sgpr2_sgpr3 + ; CHECK-NEXT: $sgpr30_sgpr31 = noconvergent G_SI_CALL [[GV]](p0), @external_gfx_void_func_struct_i8_i32_inreg, csr_amdgpu_si_gfx, implicit $sgpr0, implicit $sgpr1, implicit $sgpr0_sgpr1_sgpr2_sgpr3 ; CHECK-NEXT: ADJCALLSTACKDOWN 0, 0, implicit-def $scc ; CHECK-NEXT: SI_RETURN %ptr0 = load ptr addrspace(1), ptr addrspace(4) undef diff --git a/llvm/test/CodeGen/AMDGPU/GlobalISel/irtranslator-call.ll b/llvm/test/CodeGen/AMDGPU/GlobalISel/irtranslator-call.ll index 392b0ae6823e4495ef965ad52f7a92801e2cd88c..75670604baa1ac187893ae19c54f1902be5ef480 100644 --- a/llvm/test/CodeGen/AMDGPU/GlobalISel/irtranslator-call.ll +++ b/llvm/test/CodeGen/AMDGPU/GlobalISel/irtranslator-call.ll @@ -942,10 +942,10 @@ define amdgpu_gfx void @test_gfx_call_external_void_func_i32_imm_inreg(i32 inreg ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 42 ; CHECK-NEXT: ADJCALLSTACKUP 0, 0, implicit-def $scc ; CHECK-NEXT: [[GV:%[0-9]+]]:_(p0) = G_GLOBAL_VALUE @external_gfx_void_func_i32_inreg - ; CHECK-NEXT: $sgpr4 = COPY [[C]](s32) + ; CHECK-NEXT: $sgpr0 = COPY [[C]](s32) ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(<4 x s32>) = COPY $sgpr0_sgpr1_sgpr2_sgpr3 ; CHECK-NEXT: $sgpr0_sgpr1_sgpr2_sgpr3 = COPY [[COPY1]](<4 x s32>) - ; CHECK-NEXT: $sgpr30_sgpr31 = noconvergent G_SI_CALL [[GV]](p0), @external_gfx_void_func_i32_inreg, csr_amdgpu_si_gfx, implicit $sgpr4, implicit $sgpr0_sgpr1_sgpr2_sgpr3 + ; CHECK-NEXT: $sgpr30_sgpr31 = noconvergent G_SI_CALL [[GV]](p0), @external_gfx_void_func_i32_inreg, csr_amdgpu_si_gfx, implicit $sgpr0, implicit $sgpr0_sgpr1_sgpr2_sgpr3 ; CHECK-NEXT: ADJCALLSTACKDOWN 0, 0, implicit-def $scc ; CHECK-NEXT: SI_RETURN call amdgpu_gfx void @external_gfx_void_func_i32_inreg(i32 inreg 42) @@ -3984,11 +3984,11 @@ define amdgpu_gfx void @test_gfx_call_external_void_func_struct_i8_i32_inreg() # ; CHECK-NEXT: [[GV:%[0-9]+]]:_(p0) = G_GLOBAL_VALUE @external_gfx_void_func_struct_i8_i32_inreg ; CHECK-NEXT: [[ANYEXT:%[0-9]+]]:_(s16) = G_ANYEXT [[LOAD1]](s8) ; CHECK-NEXT: [[ANYEXT1:%[0-9]+]]:_(s32) = G_ANYEXT [[ANYEXT]](s16) - ; CHECK-NEXT: $sgpr4 = COPY [[ANYEXT1]](s32) - ; CHECK-NEXT: $sgpr5 = COPY [[LOAD2]](s32) + ; CHECK-NEXT: $sgpr0 = COPY [[ANYEXT1]](s32) + ; CHECK-NEXT: $sgpr1 = COPY [[LOAD2]](s32) ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(<4 x s32>) = COPY $sgpr0_sgpr1_sgpr2_sgpr3 ; CHECK-NEXT: $sgpr0_sgpr1_sgpr2_sgpr3 = COPY [[COPY]](<4 x s32>) - ; CHECK-NEXT: $sgpr30_sgpr31 = noconvergent G_SI_CALL [[GV]](p0), @external_gfx_void_func_struct_i8_i32_inreg, csr_amdgpu_si_gfx, implicit $sgpr4, implicit $sgpr5, implicit $sgpr0_sgpr1_sgpr2_sgpr3 + ; CHECK-NEXT: $sgpr30_sgpr31 = noconvergent G_SI_CALL [[GV]](p0), @external_gfx_void_func_struct_i8_i32_inreg, csr_amdgpu_si_gfx, implicit $sgpr0, implicit $sgpr1, implicit $sgpr0_sgpr1_sgpr2_sgpr3 ; CHECK-NEXT: ADJCALLSTACKDOWN 0, 0, implicit-def $scc ; CHECK-NEXT: SI_RETURN %ptr0 = load ptr addrspace(1), ptr addrspace(4) undef 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.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.i64.ll b/llvm/test/CodeGen/AMDGPU/GlobalISel/sdiv.i64.ll index 0a6b7af2f78d4c44a81e3adb279fb03837ece1cd..84906c01a4698a0b50fa62bfece165cf3c6ed825 100644 --- a/llvm/test/CodeGen/AMDGPU/GlobalISel/sdiv.i64.ll +++ b/llvm/test/CodeGen/AMDGPU/GlobalISel/sdiv.i64.ll @@ -3091,253 +3091,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] 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/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/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/attr-amdgpu-num-workgroups.ll b/llvm/test/CodeGen/AMDGPU/attr-amdgpu-num-workgroups.ll new file mode 100644 index 0000000000000000000000000000000000000000..bc58222076ac0e9c30bd27b7a010eeea40976293 --- /dev/null +++ b/llvm/test/CodeGen/AMDGPU/attr-amdgpu-num-workgroups.ll @@ -0,0 +1,84 @@ +; RUN: llc -mtriple=amdgcn-amd-amdhsa -mcpu=gfx900 < %s | FileCheck %s + +; Attribute not specified. +; CHECK-LABEL: {{^}}empty_no_attribute: +define amdgpu_kernel void @empty_no_attribute() { +entry: + ret void +} + +; Ignore if number of work groups for x dimension is 0. +; CHECK-LABEL: {{^}}empty_max_num_workgroups_x0: +define amdgpu_kernel void @empty_max_num_workgroups_x0() #0 { +entry: + ret void +} +attributes #0 = {"amdgpu-max-num-workgroups"="0,2,3"} + +; Ignore if number of work groups for y dimension is 0. +; CHECK-LABEL: {{^}}empty_max_num_workgroups_y0: +define amdgpu_kernel void @empty_max_num_workgroups_y0() #1 { +entry: + ret void +} +attributes #1 = {"amdgpu-max-num-workgroups"="1,0,3"} + +; Ignore if number of work groups for z dimension is 0. +; CHECK-LABEL: {{^}}empty_max_num_workgroups_z0: +define amdgpu_kernel void @empty_max_num_workgroups_z0() #2 { +entry: + ret void +} +attributes #2 = {"amdgpu-max-num-workgroups"="1,2,0"} + +; CHECK-LABEL: {{^}}empty_max_num_workgroups_1_2_3: +define amdgpu_kernel void @empty_max_num_workgroups_1_2_3() #3 { +entry: + ret void +} +attributes #3 = {"amdgpu-max-num-workgroups"="1,2,3"} + +; CHECK-LABEL: {{^}}empty_max_num_workgroups_1024_1024_1024: +define amdgpu_kernel void @empty_max_num_workgroups_1024_1024_1024() #4 { +entry: + ret void +} +attributes #4 = {"amdgpu-max-num-workgroups"="1024,1024,1024"} + + +; CHECK: .amdgpu_metadata +; CHECK: - .args: +; CHECK: .max_flat_workgroup_size: 1024 +; CHECK-NEXT: .name: empty_no_attribute +; CHECK-NEXT: .private_segment_fixed_size: 0 + +; CHECK: - .args: +; CHECK: .max_flat_workgroup_size: 1024 +; CHECK-NEXT: .name: empty_max_num_workgroups_x0 +; CHECK-NEXT: .private_segment_fixed_size: 0 + +; CHECK: - .args: +; CHECK: .max_flat_workgroup_size: 1024 +; CHECK-NEXT: .name: empty_max_num_workgroups_y0 +; CHECK-NEXT: .private_segment_fixed_size: 0 + +; CHECK: - .args: +; CHECK: .max_flat_workgroup_size: 1024 +; CHECK-NEXT: .name: empty_max_num_workgroups_z0 +; CHECK-NEXT: .private_segment_fixed_size: 0 + +; CHECK: - .args: +; CHECK: .max_flat_workgroup_size: 1024 +; CHECK-NEXT: .max_num_workgroups_x: 1 +; CHECK-NEXT: .max_num_workgroups_y: 2 +; CHECK-NEXT: .max_num_workgroups_z: 3 +; CHECK-NEXT: .name: empty_max_num_workgroups_1_2_3 +; CHECK-NEXT: .private_segment_fixed_size: 0 + +; CHECK: - .args: +; CHECK: .max_flat_workgroup_size: 1024 +; CHECK-NEXT: .max_num_workgroups_x: 1024 +; CHECK-NEXT: .max_num_workgroups_y: 1024 +; CHECK-NEXT: .max_num_workgroups_z: 1024 +; CHECK-NEXT: .name: empty_max_num_workgroups_1024_1024_1024 +; CHECK-NEXT: .private_segment_fixed_size: 0 diff --git a/llvm/test/CodeGen/AMDGPU/attr-amdgpu-num-workgroups_error_check.ll b/llvm/test/CodeGen/AMDGPU/attr-amdgpu-num-workgroups_error_check.ll new file mode 100644 index 0000000000000000000000000000000000000000..6d86d2d7c1a343615778de23068184d07f3e34fc --- /dev/null +++ b/llvm/test/CodeGen/AMDGPU/attr-amdgpu-num-workgroups_error_check.ll @@ -0,0 +1,71 @@ +; RUN: not llc -mtriple=amdgcn-amd-amdhsa -mcpu=gfx900 < %s 2>&1 | FileCheck --check-prefix=ERROR %s + +; ERROR: error: can't parse integer attribute -1 in amdgpu-max-num-workgroups +define amdgpu_kernel void @empty_max_num_workgroups_neg_num1() #21 { +entry: + ret void +} +attributes #21 = {"amdgpu-max-num-workgroups"="-1,2,3"} + +; ERROR: error: can't parse integer attribute -2 in amdgpu-max-num-workgroups +define amdgpu_kernel void @empty_max_num_workgroups_neg_num2() #22 { +entry: + ret void +} +attributes #22 = {"amdgpu-max-num-workgroups"="1,-2,3"} + +; ERROR: error: can't parse integer attribute -3 in amdgpu-max-num-workgroups +define amdgpu_kernel void @empty_max_num_workgroups_neg_num3() #23 { +entry: + ret void +} +attributes #23 = {"amdgpu-max-num-workgroups"="1,2,-3"} + +; ERROR: error: can't parse integer attribute 1.0 in amdgpu-max-num-workgroups +define amdgpu_kernel void @empty_max_num_workgroups_non_int1() #31 { +entry: + ret void +} +attributes #31 = {"amdgpu-max-num-workgroups"="1.0,2,3"} + +; ERROR: error: can't parse integer attribute 2.0 in amdgpu-max-num-workgroups +define amdgpu_kernel void @empty_max_num_workgroups_non_int2() #32 { +entry: + ret void +} +attributes #32 = {"amdgpu-max-num-workgroups"="1,2.0,3"} + +; ERROR: error: can't parse integer attribute 3.0 in amdgpu-max-num-workgroups +define amdgpu_kernel void @empty_max_num_workgroups_non_int3() #33 { +entry: + ret void +} +attributes #33 = {"amdgpu-max-num-workgroups"="1,2,3.0"} + +; ERROR: error: can't parse integer attribute 10000000000 in amdgpu-max-num-workgroups +define amdgpu_kernel void @empty_max_num_workgroups_too_large() #41 { +entry: + ret void +} +attributes #41 = {"amdgpu-max-num-workgroups"="10000000000,2,3"} + +; ERROR: error: attribute amdgpu-max-num-workgroups has incorrect number of integers; expected 3 +define amdgpu_kernel void @empty_max_num_workgroups_1_arg() #51 { +entry: + ret void +} +attributes #51 = {"amdgpu-max-num-workgroups"="1"} + +; ERROR: error: attribute amdgpu-max-num-workgroups has incorrect number of integers; expected 3 +define amdgpu_kernel void @empty_max_num_workgroups_2_args() #52 { +entry: + ret void +} +attributes #52 = {"amdgpu-max-num-workgroups"="1,2"} + +; ERROR: error: attribute amdgpu-max-num-workgroups has incorrect number of integers; expected 3 +define amdgpu_kernel void @empty_max_num_workgroups_4_args() #53 { +entry: + ret void +} +attributes #53 = {"amdgpu-max-num-workgroups"="1,2,3,4"} 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..e369f7e3b9a5ad71e60a07dd1f36e1a0d17fca98 100644 --- a/llvm/test/CodeGen/AMDGPU/bf16.ll +++ b/llvm/test/CodeGen/AMDGPU/bf16.ll @@ -3337,7 +3337,7 @@ define amdgpu_gfx void @test_inreg_arg_store(bfloat inreg %in, ptr addrspace(1) ; GFX11-LABEL: test_inreg_arg_store: ; GFX11: ; %bb.0: ; GFX11-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GFX11-NEXT: v_mov_b32_e32 v2, s4 +; GFX11-NEXT: v_mov_b32_e32 v2, s0 ; GFX11-NEXT: global_store_b16 v[0:1], v2, off ; GFX11-NEXT: s_setpc_b64 s[30:31] store bfloat %in, ptr addrspace(1) %out @@ -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/combine_andor_with_cmps.ll b/llvm/test/CodeGen/AMDGPU/combine_andor_with_cmps.ll index 10d71a315fbf9845872ea51b82118ca5e1cdb462..e1e3220cc27554a57f91be245048d4010860d185 100644 --- a/llvm/test/CodeGen/AMDGPU/combine_andor_with_cmps.ll +++ b/llvm/test/CodeGen/AMDGPU/combine_andor_with_cmps.ll @@ -472,7 +472,7 @@ define amdgpu_gfx void @test34(i32 inreg %arg1, i32 inreg %arg2) { ; GCN-LABEL: test34: ; GCN: ; %bb.0: ; GCN-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN-NEXT: s_min_i32 s0, s4, s5 +; GCN-NEXT: s_min_i32 s0, s0, s1 ; GCN-NEXT: v_mov_b32_e32 v0, 0 ; GCN-NEXT: s_cmpk_lt_i32 s0, 0x3e9 ; GCN-NEXT: v_mov_b32_e32 v1, 0 @@ -492,7 +492,7 @@ define amdgpu_gfx void @test35(i32 inreg %arg1, i32 inreg %arg2) { ; GCN-LABEL: test35: ; GCN: ; %bb.0: ; GCN-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN-NEXT: s_max_i32 s0, s4, s5 +; GCN-NEXT: s_max_i32 s0, s0, s1 ; GCN-NEXT: v_mov_b32_e32 v0, 0 ; GCN-NEXT: s_cmpk_gt_i32 s0, 0x3e8 ; GCN-NEXT: v_mov_b32_e32 v1, 0 @@ -512,9 +512,9 @@ define amdgpu_gfx void @test36(i32 inreg %arg1, i32 inreg %arg2, i32 inreg %arg3 ; GCN-LABEL: test36: ; GCN: ; %bb.0: ; GCN-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN-NEXT: s_min_u32 s0, s4, s5 +; GCN-NEXT: s_min_u32 s0, s0, s1 ; GCN-NEXT: v_mov_b32_e32 v0, 0 -; GCN-NEXT: s_cmp_lt_u32 s0, s6 +; GCN-NEXT: s_cmp_lt_u32 s0, s2 ; GCN-NEXT: v_mov_b32_e32 v1, 0 ; GCN-NEXT: s_cselect_b32 s0, -1, 0 ; GCN-NEXT: v_cndmask_b32_e64 v2, 0, 1, s0 @@ -532,9 +532,9 @@ define amdgpu_gfx void @test37(i32 inreg %arg1, i32 inreg %arg2, i32 inreg %arg3 ; GCN-LABEL: test37: ; GCN: ; %bb.0: ; GCN-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN-NEXT: s_max_i32 s0, s4, s5 +; GCN-NEXT: s_max_i32 s0, s0, s1 ; GCN-NEXT: v_mov_b32_e32 v0, 0 -; GCN-NEXT: s_cmp_ge_i32 s0, s6 +; GCN-NEXT: s_cmp_ge_i32 s0, s2 ; GCN-NEXT: v_mov_b32_e32 v1, 0 ; GCN-NEXT: s_cselect_b32 s0, -1, 0 ; GCN-NEXT: v_cndmask_b32_e64 v2, 0, 1, s0 @@ -552,7 +552,7 @@ define amdgpu_gfx void @test38(i32 inreg %arg1, i32 inreg %arg2) { ; GCN-LABEL: test38: ; GCN: ; %bb.0: ; GCN-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN-NEXT: s_max_u32 s0, s4, s5 +; GCN-NEXT: s_max_u32 s0, s0, s1 ; GCN-NEXT: v_mov_b32_e32 v0, 0 ; GCN-NEXT: s_cmpk_lt_u32 s0, 0x3e9 ; GCN-NEXT: v_mov_b32_e32 v1, 0 @@ -572,7 +572,7 @@ define amdgpu_gfx void @test39(i32 inreg %arg1, i32 inreg %arg2) { ; GCN-LABEL: test39: ; GCN: ; %bb.0: ; GCN-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN-NEXT: s_min_i32 s0, s4, s5 +; GCN-NEXT: s_min_i32 s0, s0, s1 ; GCN-NEXT: v_mov_b32_e32 v0, 0 ; GCN-NEXT: s_cmpk_gt_i32 s0, 0x3e7 ; GCN-NEXT: v_mov_b32_e32 v1, 0 @@ -592,9 +592,9 @@ define amdgpu_gfx void @test40(i32 inreg %arg1, i32 inreg %arg2, i32 inreg %arg3 ; GCN-LABEL: test40: ; GCN: ; %bb.0: ; GCN-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN-NEXT: s_max_i32 s0, s4, s5 +; GCN-NEXT: s_max_i32 s0, s0, s1 ; GCN-NEXT: v_mov_b32_e32 v0, 0 -; GCN-NEXT: s_cmp_le_i32 s0, s6 +; GCN-NEXT: s_cmp_le_i32 s0, s2 ; GCN-NEXT: v_mov_b32_e32 v1, 0 ; GCN-NEXT: s_cselect_b32 s0, -1, 0 ; GCN-NEXT: v_cndmask_b32_e64 v2, 0, 1, s0 @@ -612,9 +612,9 @@ define amdgpu_gfx void @test41(i32 inreg %arg1, i32 inreg %arg2, i32 inreg %arg3 ; GCN-LABEL: test41: ; GCN: ; %bb.0: ; GCN-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN-NEXT: s_min_u32 s0, s4, s5 +; GCN-NEXT: s_min_u32 s0, s0, s1 ; GCN-NEXT: v_mov_b32_e32 v0, 0 -; GCN-NEXT: s_cmp_ge_u32 s0, s6 +; GCN-NEXT: s_cmp_ge_u32 s0, s2 ; GCN-NEXT: v_mov_b32_e32 v1, 0 ; GCN-NEXT: s_cselect_b32 s0, -1, 0 ; GCN-NEXT: v_cndmask_b32_e64 v2, 0, 1, s0 diff --git a/llvm/test/CodeGen/AMDGPU/convergence-tokens.ll b/llvm/test/CodeGen/AMDGPU/convergence-tokens.ll index 2ed6d7fd0f598d22ce841074fac57a42d111ae27..6beccce9400e58f2778a4c443073762aab116b03 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 +; CHECK: [[TOKEN:%[0-9]+]]{{[^ ]*}} = CONVERGENCECTRL_ENTRY ; ISEL: {{.*}} SI_CALL_ISEL {{.*}}, @foo, [[TOKEN]], csr_amdgpu, {{.*}} ; 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,38 @@ 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 +} + +; COM: FIXME: Tokens on tail-call have not been implemented for SelectionDAG +; COM: yet; the corresponding checks have been commented out. +; +; CHECK-LABEL: name: tail_call_void_func_void +; GISEL: [[TOKEN:%[0-9]+]]{{[^ ]*}} = CONVERGENCECTRL_ENTRY +; COM: CHECK: [[TOKEN:%[0-9]+]]{{[^ ]*}} = CONVERGENCECTRL_ENTRY +; COM: ISEL: {{.*}} SI_CALL_ISEL {{.*}}, @external_void_func_void, [[TOKEN]], csr_amdgpu, {{.*}} +; COM: DEADMI: {{.*}} SI_CALL {{.*}}, @external_void_func_void, csr_amdgpu, {{.*}}, implicit [[TOKEN]] +; GISEL: {{.*}} 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/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..a69418d43641915c0173de019e905c7c77dfc12b --- /dev/null +++ b/llvm/test/CodeGen/AMDGPU/fptoi.i128.ll @@ -0,0 +1,1510 @@ +; 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: v_addc_co_u32_e32 v3, vcc, -1, v7, vcc +; SDAG-NEXT: s_mov_b64 s[6:7], 0xffffff7f +; SDAG-NEXT: v_cmp_lt_u64_e32 vcc, s[6:7], v[0:1] +; SDAG-NEXT: v_cmp_lt_i64_e64 s[4:5], -1, v[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v0, 0, 1, vcc +; SDAG-NEXT: v_cmp_ne_u64_e32 vcc, 0, v[2:3] +; SDAG-NEXT: v_cndmask_b32_e64 v1, 0, 1, vcc +; SDAG-NEXT: v_cmp_eq_u64_e32 vcc, 0, v[2:3] +; SDAG-NEXT: ; implicit-def: $vgpr2_vgpr3 +; SDAG-NEXT: v_cndmask_b32_e32 v0, v1, v0, vcc +; SDAG-NEXT: v_and_b32_e32 v0, 1, v0 +; SDAG-NEXT: v_cmp_eq_u32_e32 vcc, 1, v0 +; SDAG-NEXT: ; implicit-def: $vgpr0_vgpr1 +; SDAG-NEXT: s_and_saveexec_b64 s[6:7], vcc +; 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, s[4:5] +; SDAG-NEXT: v_add_co_u32_e32 v9, vcc, -1, v0 +; SDAG-NEXT: v_addc_co_u32_e64 v10, s[6:7], 0, -1, vcc +; SDAG-NEXT: s_mov_b64 s[6:7], 0x432 +; SDAG-NEXT: v_and_b32_e32 v0, 0xfffff, v5 +; SDAG-NEXT: v_cmp_lt_u64_e32 vcc, s[6:7], v[6:7] +; SDAG-NEXT: v_cndmask_b32_e64 v8, -1, 0, s[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v11, -1, 1, s[4:5] +; 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], vcc +; 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_e32 vcc, 64, v7 +; SDAG-NEXT: v_cndmask_b32_e32 v1, v3, v1, vcc +; 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_e32 v2, v2, v0, vcc +; 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_e32 v12, 0, v0, vcc +; SDAG-NEXT: v_cndmask_b32_e32 v7, 0, v1, vcc +; SDAG-NEXT: v_mad_u64_u32 v[0:1], s[6:7], 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[6:7], 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[6:7], 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[6:7], v12, v8, v[1:2] +; SDAG-NEXT: v_mad_u64_u32 v[3:4], s[6:7], v9, v12, v[4:5] +; SDAG-NEXT: v_add_co_u32_e32 v5, vcc, v6, v2 +; SDAG-NEXT: v_addc_co_u32_e64 v6, s[6:7], 0, 0, vcc +; SDAG-NEXT: v_mul_lo_u32 v9, v9, v7 +; SDAG-NEXT: v_mad_u64_u32 v[5:6], s[6:7], 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_e32 v2, vcc, v5, v3 +; SDAG-NEXT: v_addc_co_u32_e32 v3, vcc, v6, v4, vcc +; 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_e32 vcc, 64, v2 +; SDAG-NEXT: v_cmp_eq_u32_e64 s[6:7], 0, v2 +; SDAG-NEXT: v_cndmask_b32_e32 v0, 0, v0, vcc +; SDAG-NEXT: v_cndmask_b32_e32 v1, 0, v1, vcc +; 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[6:7], v6, v11, 0 +; SDAG-NEXT: v_mov_b32_e32 v2, 0 +; SDAG-NEXT: v_mad_u64_u32 v[3:4], s[6:7], 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[6:7], v6, v8, v[3:4] +; SDAG-NEXT: v_add_co_u32_e32 v2, vcc, v7, v2 +; SDAG-NEXT: v_addc_co_u32_e64 v3, s[6:7], 0, 0, vcc +; SDAG-NEXT: v_mad_u64_u32 v[2:3], s[6:7], v5, v8, v[2:3] +; SDAG-NEXT: v_mad_u64_u32 v[2:3], s[6:7], v9, v6, v[2:3] +; SDAG-NEXT: v_mad_u64_u32 v[3:4], s[6:7], 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[6:7], 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, s[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v3, v0, v1, s[4:5] +; 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[6:7] +; 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, 0 +; 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_eq_u64_e32 vcc, 0, v[8:9] +; GISEL-NEXT: v_cmp_lt_i64_e64 s[4:5], -1, v[4:5] +; GISEL-NEXT: v_cndmask_b32_e32 v0, 1, 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: v_addc_co_u32_e32 v3, vcc, -1, v7, vcc +; SDAG-NEXT: s_mov_b64 s[6:7], 0xffffff7f +; SDAG-NEXT: v_cmp_lt_u64_e32 vcc, s[6:7], v[0:1] +; SDAG-NEXT: v_cmp_lt_i64_e64 s[4:5], -1, v[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v0, 0, 1, vcc +; SDAG-NEXT: v_cmp_ne_u64_e32 vcc, 0, v[2:3] +; SDAG-NEXT: v_cndmask_b32_e64 v1, 0, 1, vcc +; SDAG-NEXT: v_cmp_eq_u64_e32 vcc, 0, v[2:3] +; SDAG-NEXT: ; implicit-def: $vgpr2_vgpr3 +; SDAG-NEXT: v_cndmask_b32_e32 v0, v1, v0, vcc +; SDAG-NEXT: v_and_b32_e32 v0, 1, v0 +; SDAG-NEXT: v_cmp_eq_u32_e32 vcc, 1, v0 +; SDAG-NEXT: ; implicit-def: $vgpr0_vgpr1 +; SDAG-NEXT: s_and_saveexec_b64 s[6:7], vcc +; 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, s[4:5] +; SDAG-NEXT: v_add_co_u32_e32 v9, vcc, -1, v0 +; SDAG-NEXT: v_addc_co_u32_e64 v10, s[6:7], 0, -1, vcc +; SDAG-NEXT: s_mov_b64 s[6:7], 0x432 +; SDAG-NEXT: v_and_b32_e32 v0, 0xfffff, v5 +; SDAG-NEXT: v_cmp_lt_u64_e32 vcc, s[6:7], v[6:7] +; SDAG-NEXT: v_cndmask_b32_e64 v8, -1, 0, s[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v11, -1, 1, s[4:5] +; 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], vcc +; 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_e32 vcc, 64, v7 +; SDAG-NEXT: v_cndmask_b32_e32 v1, v3, v1, vcc +; 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_e32 v2, v2, v0, vcc +; 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_e32 v12, 0, v0, vcc +; SDAG-NEXT: v_cndmask_b32_e32 v7, 0, v1, vcc +; SDAG-NEXT: v_mad_u64_u32 v[0:1], s[6:7], 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[6:7], 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[6:7], 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[6:7], v12, v8, v[1:2] +; SDAG-NEXT: v_mad_u64_u32 v[3:4], s[6:7], v9, v12, v[4:5] +; SDAG-NEXT: v_add_co_u32_e32 v5, vcc, v6, v2 +; SDAG-NEXT: v_addc_co_u32_e64 v6, s[6:7], 0, 0, vcc +; SDAG-NEXT: v_mul_lo_u32 v9, v9, v7 +; SDAG-NEXT: v_mad_u64_u32 v[5:6], s[6:7], 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_e32 v2, vcc, v5, v3 +; SDAG-NEXT: v_addc_co_u32_e32 v3, vcc, v6, v4, vcc +; 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_e32 vcc, 64, v2 +; SDAG-NEXT: v_cmp_eq_u32_e64 s[6:7], 0, v2 +; SDAG-NEXT: v_cndmask_b32_e32 v0, 0, v0, vcc +; SDAG-NEXT: v_cndmask_b32_e32 v1, 0, v1, vcc +; 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[6:7], v6, v11, 0 +; SDAG-NEXT: v_mov_b32_e32 v2, 0 +; SDAG-NEXT: v_mad_u64_u32 v[3:4], s[6:7], 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[6:7], v6, v8, v[3:4] +; SDAG-NEXT: v_add_co_u32_e32 v2, vcc, v7, v2 +; SDAG-NEXT: v_addc_co_u32_e64 v3, s[6:7], 0, 0, vcc +; SDAG-NEXT: v_mad_u64_u32 v[2:3], s[6:7], v5, v8, v[2:3] +; SDAG-NEXT: v_mad_u64_u32 v[2:3], s[6:7], v9, v6, v[2:3] +; SDAG-NEXT: v_mad_u64_u32 v[3:4], s[6:7], 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[6:7], 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, s[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v3, v0, v1, s[4:5] +; 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[6:7] +; 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, 0 +; 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_eq_u64_e32 vcc, 0, v[8:9] +; GISEL-NEXT: v_cmp_lt_i64_e64 s[4:5], -1, v[4:5] +; GISEL-NEXT: v_cndmask_b32_e32 v0, 1, 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: v_addc_co_u32_e32 v3, vcc, -1, v6, vcc +; SDAG-NEXT: s_mov_b64 s[6:7], 0xffffff7f +; SDAG-NEXT: v_cmp_lt_u64_e32 vcc, s[6:7], v[0:1] +; SDAG-NEXT: v_cmp_lt_i32_e64 s[4:5], -1, v4 +; SDAG-NEXT: v_cndmask_b32_e64 v0, 0, 1, vcc +; SDAG-NEXT: v_cmp_ne_u64_e32 vcc, 0, v[2:3] +; SDAG-NEXT: v_cndmask_b32_e64 v1, 0, 1, vcc +; SDAG-NEXT: v_cmp_eq_u64_e32 vcc, 0, v[2:3] +; SDAG-NEXT: ; implicit-def: $vgpr2_vgpr3 +; SDAG-NEXT: v_cndmask_b32_e32 v0, v1, v0, vcc +; SDAG-NEXT: v_and_b32_e32 v0, 1, v0 +; SDAG-NEXT: v_cmp_eq_u32_e32 vcc, 1, v0 +; SDAG-NEXT: ; implicit-def: $vgpr0_vgpr1 +; SDAG-NEXT: s_and_saveexec_b64 s[6:7], vcc +; 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, s[4:5] +; SDAG-NEXT: v_add_co_u32_e32 v9, vcc, -1, v0 +; SDAG-NEXT: v_addc_co_u32_e64 v11, s[6:7], 0, -1, vcc +; SDAG-NEXT: s_mov_b64 s[6:7], 0x95 +; SDAG-NEXT: v_and_b32_e32 v0, 0x7fffff, v4 +; SDAG-NEXT: v_cmp_lt_u64_e32 vcc, s[6:7], v[5:6] +; SDAG-NEXT: v_mov_b32_e32 v7, 0 +; SDAG-NEXT: v_cndmask_b32_e64 v8, -1, 0, s[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v10, -1, 1, s[4:5] +; 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], vcc +; 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_e32 vcc, 64, v4 +; SDAG-NEXT: v_cndmask_b32_e32 v1, v3, v1, vcc +; 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_e32 v2, v2, v0, vcc +; 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_e32 v13, 0, v0, vcc +; SDAG-NEXT: v_cndmask_b32_e32 v12, 0, v1, vcc +; SDAG-NEXT: v_mad_u64_u32 v[0:1], s[6:7], 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[6:7], v12, v10, v[6:7] +; SDAG-NEXT: v_mad_u64_u32 v[2:3], s[6:7], 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[6:7], v13, v8, v[4:5] +; SDAG-NEXT: v_add3_u32 v3, v3, v15, v14 +; SDAG-NEXT: v_mad_u64_u32 v[1:2], s[6:7], v9, v13, v[2:3] +; SDAG-NEXT: v_add_co_u32_e32 v5, vcc, v6, v5 +; SDAG-NEXT: v_addc_co_u32_e64 v6, s[6:7], 0, 0, vcc +; 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[6:7], 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_e32 v2, vcc, v5, v1 +; SDAG-NEXT: v_addc_co_u32_e32 v3, vcc, v6, v3, vcc +; 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_e32 vcc, 64, v2 +; SDAG-NEXT: v_cndmask_b32_e32 v0, 0, v0, vcc +; SDAG-NEXT: v_cmp_eq_u32_e32 vcc, 0, v2 +; SDAG-NEXT: v_cndmask_b32_e32 v3, v0, v6, vcc +; SDAG-NEXT: v_mad_u64_u32 v[0:1], s[12:13], v3, v10, 0 +; SDAG-NEXT: v_mov_b32_e32 v2, 0 +; SDAG-NEXT: v_mad_u64_u32 v[4:5], s[12:13], v3, v8, v[1:2] +; SDAG-NEXT: v_mov_b32_e32 v1, v5 +; SDAG-NEXT: v_mad_i64_i32 v[2:3], s[12:13], 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[6:7], 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, s[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v3, v0, v1, s[4:5] +; 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[6:7] +; 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, 0 +; 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_eq_u64_e32 vcc, 0, v[8:9] +; GISEL-NEXT: v_cmp_lt_i32_e64 s[4:5], -1, v4 +; GISEL-NEXT: v_cndmask_b32_e32 v0, 1, 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: v_addc_co_u32_e32 v3, vcc, -1, v6, vcc +; SDAG-NEXT: s_mov_b64 s[6:7], 0xffffff7f +; SDAG-NEXT: v_cmp_lt_u64_e32 vcc, s[6:7], v[0:1] +; SDAG-NEXT: v_cmp_lt_i32_e64 s[4:5], -1, v4 +; SDAG-NEXT: v_cndmask_b32_e64 v0, 0, 1, vcc +; SDAG-NEXT: v_cmp_ne_u64_e32 vcc, 0, v[2:3] +; SDAG-NEXT: v_cndmask_b32_e64 v1, 0, 1, vcc +; SDAG-NEXT: v_cmp_eq_u64_e32 vcc, 0, v[2:3] +; SDAG-NEXT: ; implicit-def: $vgpr2_vgpr3 +; SDAG-NEXT: v_cndmask_b32_e32 v0, v1, v0, vcc +; SDAG-NEXT: v_and_b32_e32 v0, 1, v0 +; SDAG-NEXT: v_cmp_eq_u32_e32 vcc, 1, v0 +; SDAG-NEXT: ; implicit-def: $vgpr0_vgpr1 +; SDAG-NEXT: s_and_saveexec_b64 s[6:7], vcc +; 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, s[4:5] +; SDAG-NEXT: v_add_co_u32_e32 v9, vcc, -1, v0 +; SDAG-NEXT: v_addc_co_u32_e64 v11, s[6:7], 0, -1, vcc +; SDAG-NEXT: s_mov_b64 s[6:7], 0x95 +; SDAG-NEXT: v_and_b32_e32 v0, 0x7fffff, v4 +; SDAG-NEXT: v_cmp_lt_u64_e32 vcc, s[6:7], v[5:6] +; SDAG-NEXT: v_mov_b32_e32 v7, 0 +; SDAG-NEXT: v_cndmask_b32_e64 v8, -1, 0, s[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v10, -1, 1, s[4:5] +; 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], vcc +; 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_e32 vcc, 64, v4 +; SDAG-NEXT: v_cndmask_b32_e32 v1, v3, v1, vcc +; 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_e32 v2, v2, v0, vcc +; 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_e32 v13, 0, v0, vcc +; SDAG-NEXT: v_cndmask_b32_e32 v12, 0, v1, vcc +; SDAG-NEXT: v_mad_u64_u32 v[0:1], s[6:7], 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[6:7], v12, v10, v[6:7] +; SDAG-NEXT: v_mad_u64_u32 v[2:3], s[6:7], 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[6:7], v13, v8, v[4:5] +; SDAG-NEXT: v_add3_u32 v3, v3, v15, v14 +; SDAG-NEXT: v_mad_u64_u32 v[1:2], s[6:7], v9, v13, v[2:3] +; SDAG-NEXT: v_add_co_u32_e32 v5, vcc, v6, v5 +; SDAG-NEXT: v_addc_co_u32_e64 v6, s[6:7], 0, 0, vcc +; 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[6:7], 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_e32 v2, vcc, v5, v1 +; SDAG-NEXT: v_addc_co_u32_e32 v3, vcc, v6, v3, vcc +; 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_e32 vcc, 64, v2 +; SDAG-NEXT: v_cndmask_b32_e32 v0, 0, v0, vcc +; SDAG-NEXT: v_cmp_eq_u32_e32 vcc, 0, v2 +; SDAG-NEXT: v_cndmask_b32_e32 v3, v0, v6, vcc +; SDAG-NEXT: v_mad_u64_u32 v[0:1], s[12:13], v3, v10, 0 +; SDAG-NEXT: v_mov_b32_e32 v2, 0 +; SDAG-NEXT: v_mad_u64_u32 v[4:5], s[12:13], v3, v8, v[1:2] +; SDAG-NEXT: v_mov_b32_e32 v1, v5 +; SDAG-NEXT: v_mad_i64_i32 v[2:3], s[12:13], 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[6:7], 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, s[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v3, v0, v1, s[4:5] +; 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[6:7] +; 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, 0 +; 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_eq_u64_e32 vcc, 0, v[8:9] +; GISEL-NEXT: v_cmp_lt_i32_e64 s[4:5], -1, v4 +; GISEL-NEXT: v_cndmask_b32_e32 v0, 1, 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/function-args-inreg.ll b/llvm/test/CodeGen/AMDGPU/function-args-inreg.ll index 44a9127b4bd09c2922676d81fd493b8cb81cd6ec..27845b6b5b2fee2a91ace5c45975e0d4fb7d4ead 100644 --- a/llvm/test/CodeGen/AMDGPU/function-args-inreg.ll +++ b/llvm/test/CodeGen/AMDGPU/function-args-inreg.ll @@ -2176,6 +2176,93 @@ define void @void_func_a5i32_inreg([5 x i32] inreg %arg0, ptr addrspace(1) %ptr) declare void @extern() define void @void_func_a13i32_inreg([13 x i32] inreg %arg0, ptr addrspace(1) %ptr) { +; GFX9-LABEL: void_func_a13i32_inreg: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: s_mov_b32 s27, s33 +; GFX9-NEXT: s_mov_b32 s33, s32 +; GFX9-NEXT: s_or_saveexec_b64 s[28:29], -1 +; GFX9-NEXT: buffer_store_dword v40, off, s[0:3], s33 ; 4-byte Folded Spill +; GFX9-NEXT: s_mov_b64 exec, s[28:29] +; GFX9-NEXT: v_mov_b32_e32 v2, s26 +; GFX9-NEXT: global_store_dword v[0:1], v2, off offset:48 +; GFX9-NEXT: v_mov_b32_e32 v5, s25 +; GFX9-NEXT: v_mov_b32_e32 v4, s24 +; GFX9-NEXT: v_mov_b32_e32 v3, s23 +; GFX9-NEXT: v_mov_b32_e32 v2, s22 +; GFX9-NEXT: s_addk_i32 s32, 0x400 +; GFX9-NEXT: global_store_dwordx4 v[0:1], v[2:5], off offset:32 +; GFX9-NEXT: v_writelane_b32 v40, s27, 2 +; GFX9-NEXT: v_mov_b32_e32 v5, s21 +; GFX9-NEXT: v_mov_b32_e32 v4, s20 +; GFX9-NEXT: v_mov_b32_e32 v3, s19 +; GFX9-NEXT: v_mov_b32_e32 v2, s18 +; GFX9-NEXT: global_store_dwordx4 v[0:1], v[2:5], off offset:16 +; GFX9-NEXT: v_writelane_b32 v40, s30, 0 +; GFX9-NEXT: v_mov_b32_e32 v5, s17 +; GFX9-NEXT: v_mov_b32_e32 v4, s16 +; GFX9-NEXT: s_getpc_b64 s[16:17] +; GFX9-NEXT: s_add_u32 s16, s16, extern@gotpcrel32@lo+4 +; GFX9-NEXT: s_addc_u32 s17, s17, extern@gotpcrel32@hi+12 +; GFX9-NEXT: s_load_dwordx2 s[16:17], s[16:17], 0x0 +; GFX9-NEXT: v_mov_b32_e32 v3, s7 +; GFX9-NEXT: v_mov_b32_e32 v2, s6 +; GFX9-NEXT: v_writelane_b32 v40, s31, 1 +; GFX9-NEXT: global_store_dwordx4 v[0:1], v[2:5], off +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: s_swappc_b64 s[30:31], s[16:17] +; GFX9-NEXT: v_readlane_b32 s31, v40, 1 +; GFX9-NEXT: v_readlane_b32 s30, v40, 0 +; GFX9-NEXT: v_readlane_b32 s4, v40, 2 +; GFX9-NEXT: s_or_saveexec_b64 s[6:7], -1 +; GFX9-NEXT: buffer_load_dword v40, off, s[0:3], s33 ; 4-byte Folded Reload +; GFX9-NEXT: s_mov_b64 exec, s[6:7] +; GFX9-NEXT: s_addk_i32 s32, 0xfc00 +; GFX9-NEXT: s_mov_b32 s33, s4 +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: s_setpc_b64 s[30:31] +; +; GFX11-LABEL: void_func_a13i32_inreg: +; GFX11: ; %bb.0: +; GFX11-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX11-NEXT: s_mov_b32 s23, s33 +; GFX11-NEXT: s_mov_b32 s33, s32 +; GFX11-NEXT: s_or_saveexec_b32 s24, -1 +; GFX11-NEXT: scratch_store_b32 off, v40, s33 ; 4-byte Folded Spill +; GFX11-NEXT: s_mov_b32 exec_lo, s24 +; GFX11-NEXT: s_add_i32 s32, s32, 16 +; GFX11-NEXT: v_dual_mov_b32 v4, s20 :: v_dual_mov_b32 v3, s19 +; GFX11-NEXT: v_dual_mov_b32 v2, s18 :: v_dual_mov_b32 v9, s17 +; GFX11-NEXT: s_getpc_b64 s[18:19] +; GFX11-NEXT: s_add_u32 s18, s18, extern@gotpcrel32@lo+4 +; GFX11-NEXT: s_addc_u32 s19, s19, extern@gotpcrel32@hi+12 +; GFX11-NEXT: v_dual_mov_b32 v8, s16 :: v_dual_mov_b32 v7, s7 +; GFX11-NEXT: s_load_b64 s[16:17], s[18:19], 0x0 +; GFX11-NEXT: v_writelane_b32 v40, s23, 2 +; GFX11-NEXT: v_dual_mov_b32 v14, s22 :: v_dual_mov_b32 v5, s21 +; GFX11-NEXT: v_dual_mov_b32 v6, s6 :: v_dual_mov_b32 v13, s3 +; GFX11-NEXT: v_writelane_b32 v40, s30, 0 +; GFX11-NEXT: v_dual_mov_b32 v12, s2 :: v_dual_mov_b32 v11, s1 +; GFX11-NEXT: v_mov_b32_e32 v10, s0 +; GFX11-NEXT: s_clause 0x3 +; GFX11-NEXT: global_store_b32 v[0:1], v14, off offset:48 +; GFX11-NEXT: global_store_b128 v[0:1], v[2:5], off offset:32 +; GFX11-NEXT: global_store_b128 v[0:1], v[6:9], off offset:16 +; GFX11-NEXT: global_store_b128 v[0:1], v[10:13], off +; GFX11-NEXT: v_writelane_b32 v40, s31, 1 +; GFX11-NEXT: s_waitcnt lgkmcnt(0) +; GFX11-NEXT: s_swappc_b64 s[30:31], s[16:17] +; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX11-NEXT: v_readlane_b32 s31, v40, 1 +; GFX11-NEXT: v_readlane_b32 s30, v40, 0 +; GFX11-NEXT: v_readlane_b32 s0, v40, 2 +; GFX11-NEXT: s_or_saveexec_b32 s1, -1 +; GFX11-NEXT: scratch_load_b32 v40, off, s33 ; 4-byte Folded Reload +; GFX11-NEXT: s_mov_b32 exec_lo, s1 +; GFX11-NEXT: s_add_i32 s32, s32, -16 +; GFX11-NEXT: s_mov_b32 s33, s0 +; GFX11-NEXT: s_waitcnt vmcnt(0) +; GFX11-NEXT: s_setpc_b64 s[30:31] store [13 x i32] %arg0, ptr addrspace(1) %ptr call void @extern() ret void @@ -2203,6 +2290,52 @@ define void @void_func_a13i32_inreg([13 x i32] inreg %arg0, ptr addrspace(1) %p ; FIXME: Should still fail define void @void_func_a16i32_inreg__noimplicit([16 x i32] inreg %arg0, ptr addrspace(1) %ptr) { +; GFX9-LABEL: void_func_a16i32_inreg__noimplicit: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: v_mov_b32_e32 v5, s19 +; GFX9-NEXT: v_mov_b32_e32 v4, s18 +; GFX9-NEXT: v_mov_b32_e32 v3, s17 +; GFX9-NEXT: v_mov_b32_e32 v2, s16 +; GFX9-NEXT: global_store_dwordx4 v[0:1], v[2:5], off offset:48 +; GFX9-NEXT: s_nop 0 +; GFX9-NEXT: v_mov_b32_e32 v5, s15 +; GFX9-NEXT: v_mov_b32_e32 v4, s14 +; GFX9-NEXT: v_mov_b32_e32 v3, s13 +; GFX9-NEXT: v_mov_b32_e32 v2, s12 +; GFX9-NEXT: global_store_dwordx4 v[0:1], v[2:5], off offset:32 +; GFX9-NEXT: s_nop 0 +; GFX9-NEXT: v_mov_b32_e32 v5, s11 +; GFX9-NEXT: v_mov_b32_e32 v4, s10 +; GFX9-NEXT: v_mov_b32_e32 v3, s9 +; GFX9-NEXT: v_mov_b32_e32 v2, s8 +; GFX9-NEXT: global_store_dwordx4 v[0:1], v[2:5], off offset:16 +; GFX9-NEXT: s_nop 0 +; GFX9-NEXT: v_mov_b32_e32 v5, s7 +; GFX9-NEXT: v_mov_b32_e32 v4, s6 +; GFX9-NEXT: v_mov_b32_e32 v3, s5 +; GFX9-NEXT: v_mov_b32_e32 v2, s4 +; GFX9-NEXT: global_store_dwordx4 v[0:1], v[2:5], off +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: s_setpc_b64 s[30:31] +; +; GFX11-LABEL: void_func_a16i32_inreg__noimplicit: +; GFX11: ; %bb.0: +; GFX11-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX11-NEXT: v_dual_mov_b32 v5, s15 :: v_dual_mov_b32 v4, s14 +; GFX11-NEXT: v_dual_mov_b32 v3, s13 :: v_dual_mov_b32 v2, s12 +; GFX11-NEXT: v_dual_mov_b32 v9, s11 :: v_dual_mov_b32 v8, s10 +; GFX11-NEXT: v_dual_mov_b32 v7, s9 :: v_dual_mov_b32 v6, s8 +; GFX11-NEXT: v_dual_mov_b32 v13, s7 :: v_dual_mov_b32 v12, s6 +; GFX11-NEXT: v_dual_mov_b32 v11, s5 :: v_dual_mov_b32 v10, s4 +; GFX11-NEXT: v_dual_mov_b32 v17, s3 :: v_dual_mov_b32 v16, s2 +; GFX11-NEXT: v_dual_mov_b32 v15, s1 :: v_dual_mov_b32 v14, s0 +; GFX11-NEXT: s_clause 0x3 +; GFX11-NEXT: global_store_b128 v[0:1], v[2:5], off offset:48 +; GFX11-NEXT: global_store_b128 v[0:1], v[6:9], off offset:32 +; GFX11-NEXT: global_store_b128 v[0:1], v[10:13], off offset:16 +; GFX11-NEXT: global_store_b128 v[0:1], v[14:17], off +; GFX11-NEXT: s_setpc_b64 s[30:31] store [16 x i32] %arg0, ptr addrspace(1) %ptr ret void } diff --git a/llvm/test/CodeGen/AMDGPU/gfx-callable-argument-types.ll b/llvm/test/CodeGen/AMDGPU/gfx-callable-argument-types.ll index a118fa388f86d9c93865ad89e577102878cdf124..3e1db5fb4e1dc86a9013254ea358aa89128d44f6 100644 --- a/llvm/test/CodeGen/AMDGPU/gfx-callable-argument-types.ll +++ b/llvm/test/CodeGen/AMDGPU/gfx-callable-argument-types.ll @@ -9567,19 +9567,17 @@ define amdgpu_gfx void @test_call_external_void_func_i8_imm_inreg(i32) #0 { ; GFX9-NEXT: s_or_saveexec_b64 s[36:37], -1 ; GFX9-NEXT: buffer_store_dword v40, off, s[0:3], s33 ; 4-byte Folded Spill ; GFX9-NEXT: s_mov_b64 exec, s[36:37] -; GFX9-NEXT: v_writelane_b32 v40, s34, 3 -; GFX9-NEXT: v_writelane_b32 v40, s4, 0 -; GFX9-NEXT: v_writelane_b32 v40, s30, 1 +; GFX9-NEXT: v_writelane_b32 v40, s34, 2 +; GFX9-NEXT: v_writelane_b32 v40, s30, 0 ; GFX9-NEXT: s_mov_b32 s35, external_void_func_i8_inreg@abs32@hi ; GFX9-NEXT: s_mov_b32 s34, external_void_func_i8_inreg@abs32@lo -; GFX9-NEXT: s_movk_i32 s4, 0x7b +; GFX9-NEXT: s_movk_i32 s0, 0x7b ; GFX9-NEXT: s_addk_i32 s32, 0x400 -; GFX9-NEXT: v_writelane_b32 v40, s31, 2 +; GFX9-NEXT: v_writelane_b32 v40, s31, 1 ; GFX9-NEXT: s_swappc_b64 s[30:31], s[34:35] -; GFX9-NEXT: v_readlane_b32 s31, v40, 2 -; GFX9-NEXT: v_readlane_b32 s30, v40, 1 -; GFX9-NEXT: v_readlane_b32 s4, v40, 0 -; GFX9-NEXT: v_readlane_b32 s34, v40, 3 +; GFX9-NEXT: v_readlane_b32 s31, v40, 1 +; GFX9-NEXT: v_readlane_b32 s30, v40, 0 +; GFX9-NEXT: v_readlane_b32 s34, v40, 2 ; GFX9-NEXT: s_or_saveexec_b64 s[36:37], -1 ; GFX9-NEXT: buffer_load_dword v40, off, s[0:3], s33 ; 4-byte Folded Reload ; GFX9-NEXT: s_mov_b64 exec, s[36:37] @@ -9597,19 +9595,17 @@ define amdgpu_gfx void @test_call_external_void_func_i8_imm_inreg(i32) #0 { ; GFX10-NEXT: buffer_store_dword v40, off, s[0:3], s33 ; 4-byte Folded Spill ; GFX10-NEXT: s_waitcnt_depctr 0xffe3 ; GFX10-NEXT: s_mov_b32 exec_lo, s35 -; GFX10-NEXT: v_writelane_b32 v40, s34, 3 +; GFX10-NEXT: v_writelane_b32 v40, s34, 2 ; GFX10-NEXT: s_mov_b32 s35, external_void_func_i8_inreg@abs32@hi ; GFX10-NEXT: s_mov_b32 s34, external_void_func_i8_inreg@abs32@lo +; GFX10-NEXT: s_movk_i32 s0, 0x7b ; GFX10-NEXT: s_addk_i32 s32, 0x200 -; GFX10-NEXT: v_writelane_b32 v40, s4, 0 -; GFX10-NEXT: s_movk_i32 s4, 0x7b -; GFX10-NEXT: v_writelane_b32 v40, s30, 1 -; GFX10-NEXT: v_writelane_b32 v40, s31, 2 +; GFX10-NEXT: v_writelane_b32 v40, s30, 0 +; GFX10-NEXT: v_writelane_b32 v40, s31, 1 ; GFX10-NEXT: s_swappc_b64 s[30:31], s[34:35] -; GFX10-NEXT: v_readlane_b32 s31, v40, 2 -; GFX10-NEXT: v_readlane_b32 s30, v40, 1 -; GFX10-NEXT: v_readlane_b32 s4, v40, 0 -; GFX10-NEXT: v_readlane_b32 s34, v40, 3 +; GFX10-NEXT: v_readlane_b32 s31, v40, 1 +; GFX10-NEXT: v_readlane_b32 s30, v40, 0 +; GFX10-NEXT: v_readlane_b32 s34, v40, 2 ; GFX10-NEXT: s_or_saveexec_b32 s35, -1 ; GFX10-NEXT: buffer_load_dword v40, off, s[0:3], s33 ; 4-byte Folded Reload ; GFX10-NEXT: s_waitcnt_depctr 0xffe3 @@ -9627,20 +9623,18 @@ define amdgpu_gfx void @test_call_external_void_func_i8_imm_inreg(i32) #0 { ; GFX11-NEXT: s_or_saveexec_b32 s1, -1 ; GFX11-NEXT: scratch_store_b32 off, v40, s33 ; 4-byte Folded Spill ; GFX11-NEXT: s_mov_b32 exec_lo, s1 -; GFX11-NEXT: v_writelane_b32 v40, s0, 3 -; GFX11-NEXT: s_mov_b32 s1, external_void_func_i8_inreg@abs32@hi -; GFX11-NEXT: s_mov_b32 s0, external_void_func_i8_inreg@abs32@lo +; GFX11-NEXT: v_writelane_b32 v40, s0, 2 +; GFX11-NEXT: s_mov_b32 s3, external_void_func_i8_inreg@abs32@hi +; GFX11-NEXT: s_mov_b32 s2, external_void_func_i8_inreg@abs32@lo +; GFX11-NEXT: s_movk_i32 s0, 0x7b ; GFX11-NEXT: s_add_i32 s32, s32, 16 -; GFX11-NEXT: v_writelane_b32 v40, s4, 0 -; GFX11-NEXT: s_movk_i32 s4, 0x7b -; GFX11-NEXT: v_writelane_b32 v40, s30, 1 -; GFX11-NEXT: v_writelane_b32 v40, s31, 2 -; GFX11-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX11-NEXT: v_writelane_b32 v40, s30, 0 +; GFX11-NEXT: v_writelane_b32 v40, s31, 1 +; GFX11-NEXT: s_swappc_b64 s[30:31], s[2:3] ; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_1) -; GFX11-NEXT: v_readlane_b32 s31, v40, 2 -; GFX11-NEXT: v_readlane_b32 s30, v40, 1 -; GFX11-NEXT: v_readlane_b32 s4, v40, 0 -; GFX11-NEXT: v_readlane_b32 s0, v40, 3 +; GFX11-NEXT: v_readlane_b32 s31, v40, 1 +; GFX11-NEXT: v_readlane_b32 s30, v40, 0 +; GFX11-NEXT: v_readlane_b32 s0, v40, 2 ; GFX11-NEXT: s_or_saveexec_b32 s1, -1 ; GFX11-NEXT: scratch_load_b32 v40, off, s33 ; 4-byte Folded Reload ; GFX11-NEXT: s_mov_b32 exec_lo, s1 @@ -9658,19 +9652,17 @@ define amdgpu_gfx void @test_call_external_void_func_i8_imm_inreg(i32) #0 { ; GFX10-SCRATCH-NEXT: scratch_store_dword off, v40, s33 ; 4-byte Folded Spill ; GFX10-SCRATCH-NEXT: s_waitcnt_depctr 0xffe3 ; GFX10-SCRATCH-NEXT: s_mov_b32 exec_lo, s1 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s0, 3 -; GFX10-SCRATCH-NEXT: s_mov_b32 s1, external_void_func_i8_inreg@abs32@hi -; GFX10-SCRATCH-NEXT: s_mov_b32 s0, external_void_func_i8_inreg@abs32@lo +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s0, 2 +; GFX10-SCRATCH-NEXT: s_mov_b32 s3, external_void_func_i8_inreg@abs32@hi +; GFX10-SCRATCH-NEXT: s_mov_b32 s2, external_void_func_i8_inreg@abs32@lo +; GFX10-SCRATCH-NEXT: s_movk_i32 s0, 0x7b ; GFX10-SCRATCH-NEXT: s_add_i32 s32, s32, 16 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s4, 0 -; GFX10-SCRATCH-NEXT: s_movk_i32 s4, 0x7b -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s30, 1 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s31, 2 -; GFX10-SCRATCH-NEXT: s_swappc_b64 s[30:31], s[0:1] -; GFX10-SCRATCH-NEXT: v_readlane_b32 s31, v40, 2 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s30, v40, 1 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s4, v40, 0 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s0, v40, 3 +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s30, 0 +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s31, 1 +; GFX10-SCRATCH-NEXT: s_swappc_b64 s[30:31], s[2:3] +; GFX10-SCRATCH-NEXT: v_readlane_b32 s31, v40, 1 +; GFX10-SCRATCH-NEXT: v_readlane_b32 s30, v40, 0 +; GFX10-SCRATCH-NEXT: v_readlane_b32 s0, v40, 2 ; GFX10-SCRATCH-NEXT: s_or_saveexec_b32 s1, -1 ; GFX10-SCRATCH-NEXT: scratch_load_dword v40, off, s33 ; 4-byte Folded Reload ; GFX10-SCRATCH-NEXT: s_waitcnt_depctr 0xffe3 @@ -9692,19 +9684,17 @@ define amdgpu_gfx void @test_call_external_void_func_i16_imm_inreg() #0 { ; GFX9-NEXT: s_or_saveexec_b64 s[36:37], -1 ; GFX9-NEXT: buffer_store_dword v40, off, s[0:3], s33 ; 4-byte Folded Spill ; GFX9-NEXT: s_mov_b64 exec, s[36:37] -; GFX9-NEXT: v_writelane_b32 v40, s34, 3 -; GFX9-NEXT: v_writelane_b32 v40, s4, 0 -; GFX9-NEXT: v_writelane_b32 v40, s30, 1 +; GFX9-NEXT: v_writelane_b32 v40, s34, 2 +; GFX9-NEXT: v_writelane_b32 v40, s30, 0 ; GFX9-NEXT: s_mov_b32 s35, external_void_func_i16_inreg@abs32@hi ; GFX9-NEXT: s_mov_b32 s34, external_void_func_i16_inreg@abs32@lo -; GFX9-NEXT: s_movk_i32 s4, 0x7b +; GFX9-NEXT: s_movk_i32 s0, 0x7b ; GFX9-NEXT: s_addk_i32 s32, 0x400 -; GFX9-NEXT: v_writelane_b32 v40, s31, 2 +; GFX9-NEXT: v_writelane_b32 v40, s31, 1 ; GFX9-NEXT: s_swappc_b64 s[30:31], s[34:35] -; GFX9-NEXT: v_readlane_b32 s31, v40, 2 -; GFX9-NEXT: v_readlane_b32 s30, v40, 1 -; GFX9-NEXT: v_readlane_b32 s4, v40, 0 -; GFX9-NEXT: v_readlane_b32 s34, v40, 3 +; GFX9-NEXT: v_readlane_b32 s31, v40, 1 +; GFX9-NEXT: v_readlane_b32 s30, v40, 0 +; GFX9-NEXT: v_readlane_b32 s34, v40, 2 ; GFX9-NEXT: s_or_saveexec_b64 s[36:37], -1 ; GFX9-NEXT: buffer_load_dword v40, off, s[0:3], s33 ; 4-byte Folded Reload ; GFX9-NEXT: s_mov_b64 exec, s[36:37] @@ -9722,19 +9712,17 @@ define amdgpu_gfx void @test_call_external_void_func_i16_imm_inreg() #0 { ; GFX10-NEXT: buffer_store_dword v40, off, s[0:3], s33 ; 4-byte Folded Spill ; GFX10-NEXT: s_waitcnt_depctr 0xffe3 ; GFX10-NEXT: s_mov_b32 exec_lo, s35 -; GFX10-NEXT: v_writelane_b32 v40, s34, 3 +; GFX10-NEXT: v_writelane_b32 v40, s34, 2 ; GFX10-NEXT: s_mov_b32 s35, external_void_func_i16_inreg@abs32@hi ; GFX10-NEXT: s_mov_b32 s34, external_void_func_i16_inreg@abs32@lo +; GFX10-NEXT: s_movk_i32 s0, 0x7b ; GFX10-NEXT: s_addk_i32 s32, 0x200 -; GFX10-NEXT: v_writelane_b32 v40, s4, 0 -; GFX10-NEXT: s_movk_i32 s4, 0x7b -; GFX10-NEXT: v_writelane_b32 v40, s30, 1 -; GFX10-NEXT: v_writelane_b32 v40, s31, 2 +; GFX10-NEXT: v_writelane_b32 v40, s30, 0 +; GFX10-NEXT: v_writelane_b32 v40, s31, 1 ; GFX10-NEXT: s_swappc_b64 s[30:31], s[34:35] -; GFX10-NEXT: v_readlane_b32 s31, v40, 2 -; GFX10-NEXT: v_readlane_b32 s30, v40, 1 -; GFX10-NEXT: v_readlane_b32 s4, v40, 0 -; GFX10-NEXT: v_readlane_b32 s34, v40, 3 +; GFX10-NEXT: v_readlane_b32 s31, v40, 1 +; GFX10-NEXT: v_readlane_b32 s30, v40, 0 +; GFX10-NEXT: v_readlane_b32 s34, v40, 2 ; GFX10-NEXT: s_or_saveexec_b32 s35, -1 ; GFX10-NEXT: buffer_load_dword v40, off, s[0:3], s33 ; 4-byte Folded Reload ; GFX10-NEXT: s_waitcnt_depctr 0xffe3 @@ -9752,20 +9740,18 @@ define amdgpu_gfx void @test_call_external_void_func_i16_imm_inreg() #0 { ; GFX11-NEXT: s_or_saveexec_b32 s1, -1 ; GFX11-NEXT: scratch_store_b32 off, v40, s33 ; 4-byte Folded Spill ; GFX11-NEXT: s_mov_b32 exec_lo, s1 -; GFX11-NEXT: v_writelane_b32 v40, s0, 3 -; GFX11-NEXT: s_mov_b32 s1, external_void_func_i16_inreg@abs32@hi -; GFX11-NEXT: s_mov_b32 s0, external_void_func_i16_inreg@abs32@lo +; GFX11-NEXT: v_writelane_b32 v40, s0, 2 +; GFX11-NEXT: s_mov_b32 s3, external_void_func_i16_inreg@abs32@hi +; GFX11-NEXT: s_mov_b32 s2, external_void_func_i16_inreg@abs32@lo +; GFX11-NEXT: s_movk_i32 s0, 0x7b ; GFX11-NEXT: s_add_i32 s32, s32, 16 -; GFX11-NEXT: v_writelane_b32 v40, s4, 0 -; GFX11-NEXT: s_movk_i32 s4, 0x7b -; GFX11-NEXT: v_writelane_b32 v40, s30, 1 -; GFX11-NEXT: v_writelane_b32 v40, s31, 2 -; GFX11-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX11-NEXT: v_writelane_b32 v40, s30, 0 +; GFX11-NEXT: v_writelane_b32 v40, s31, 1 +; GFX11-NEXT: s_swappc_b64 s[30:31], s[2:3] ; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_1) -; GFX11-NEXT: v_readlane_b32 s31, v40, 2 -; GFX11-NEXT: v_readlane_b32 s30, v40, 1 -; GFX11-NEXT: v_readlane_b32 s4, v40, 0 -; GFX11-NEXT: v_readlane_b32 s0, v40, 3 +; GFX11-NEXT: v_readlane_b32 s31, v40, 1 +; GFX11-NEXT: v_readlane_b32 s30, v40, 0 +; GFX11-NEXT: v_readlane_b32 s0, v40, 2 ; GFX11-NEXT: s_or_saveexec_b32 s1, -1 ; GFX11-NEXT: scratch_load_b32 v40, off, s33 ; 4-byte Folded Reload ; GFX11-NEXT: s_mov_b32 exec_lo, s1 @@ -9783,19 +9769,17 @@ define amdgpu_gfx void @test_call_external_void_func_i16_imm_inreg() #0 { ; GFX10-SCRATCH-NEXT: scratch_store_dword off, v40, s33 ; 4-byte Folded Spill ; GFX10-SCRATCH-NEXT: s_waitcnt_depctr 0xffe3 ; GFX10-SCRATCH-NEXT: s_mov_b32 exec_lo, s1 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s0, 3 -; GFX10-SCRATCH-NEXT: s_mov_b32 s1, external_void_func_i16_inreg@abs32@hi -; GFX10-SCRATCH-NEXT: s_mov_b32 s0, external_void_func_i16_inreg@abs32@lo +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s0, 2 +; GFX10-SCRATCH-NEXT: s_mov_b32 s3, external_void_func_i16_inreg@abs32@hi +; GFX10-SCRATCH-NEXT: s_mov_b32 s2, external_void_func_i16_inreg@abs32@lo +; GFX10-SCRATCH-NEXT: s_movk_i32 s0, 0x7b ; GFX10-SCRATCH-NEXT: s_add_i32 s32, s32, 16 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s4, 0 -; GFX10-SCRATCH-NEXT: s_movk_i32 s4, 0x7b -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s30, 1 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s31, 2 -; GFX10-SCRATCH-NEXT: s_swappc_b64 s[30:31], s[0:1] -; GFX10-SCRATCH-NEXT: v_readlane_b32 s31, v40, 2 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s30, v40, 1 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s4, v40, 0 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s0, v40, 3 +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s30, 0 +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s31, 1 +; GFX10-SCRATCH-NEXT: s_swappc_b64 s[30:31], s[2:3] +; GFX10-SCRATCH-NEXT: v_readlane_b32 s31, v40, 1 +; GFX10-SCRATCH-NEXT: v_readlane_b32 s30, v40, 0 +; GFX10-SCRATCH-NEXT: v_readlane_b32 s0, v40, 2 ; GFX10-SCRATCH-NEXT: s_or_saveexec_b32 s1, -1 ; GFX10-SCRATCH-NEXT: scratch_load_dword v40, off, s33 ; 4-byte Folded Reload ; GFX10-SCRATCH-NEXT: s_waitcnt_depctr 0xffe3 @@ -9817,19 +9801,17 @@ define amdgpu_gfx void @test_call_external_void_func_i32_imm_inreg(i32) #0 { ; GFX9-NEXT: s_or_saveexec_b64 s[36:37], -1 ; GFX9-NEXT: buffer_store_dword v40, off, s[0:3], s33 ; 4-byte Folded Spill ; GFX9-NEXT: s_mov_b64 exec, s[36:37] -; GFX9-NEXT: v_writelane_b32 v40, s34, 3 -; GFX9-NEXT: v_writelane_b32 v40, s4, 0 -; GFX9-NEXT: v_writelane_b32 v40, s30, 1 +; GFX9-NEXT: v_writelane_b32 v40, s34, 2 +; GFX9-NEXT: v_writelane_b32 v40, s30, 0 ; GFX9-NEXT: s_mov_b32 s35, external_void_func_i32_inreg@abs32@hi ; GFX9-NEXT: s_mov_b32 s34, external_void_func_i32_inreg@abs32@lo -; GFX9-NEXT: s_mov_b32 s4, 42 +; GFX9-NEXT: s_mov_b32 s0, 42 ; GFX9-NEXT: s_addk_i32 s32, 0x400 -; GFX9-NEXT: v_writelane_b32 v40, s31, 2 +; GFX9-NEXT: v_writelane_b32 v40, s31, 1 ; GFX9-NEXT: s_swappc_b64 s[30:31], s[34:35] -; GFX9-NEXT: v_readlane_b32 s31, v40, 2 -; GFX9-NEXT: v_readlane_b32 s30, v40, 1 -; GFX9-NEXT: v_readlane_b32 s4, v40, 0 -; GFX9-NEXT: v_readlane_b32 s34, v40, 3 +; GFX9-NEXT: v_readlane_b32 s31, v40, 1 +; GFX9-NEXT: v_readlane_b32 s30, v40, 0 +; GFX9-NEXT: v_readlane_b32 s34, v40, 2 ; GFX9-NEXT: s_or_saveexec_b64 s[36:37], -1 ; GFX9-NEXT: buffer_load_dword v40, off, s[0:3], s33 ; 4-byte Folded Reload ; GFX9-NEXT: s_mov_b64 exec, s[36:37] @@ -9847,19 +9829,17 @@ define amdgpu_gfx void @test_call_external_void_func_i32_imm_inreg(i32) #0 { ; GFX10-NEXT: buffer_store_dword v40, off, s[0:3], s33 ; 4-byte Folded Spill ; GFX10-NEXT: s_waitcnt_depctr 0xffe3 ; GFX10-NEXT: s_mov_b32 exec_lo, s35 -; GFX10-NEXT: v_writelane_b32 v40, s34, 3 +; GFX10-NEXT: v_writelane_b32 v40, s34, 2 ; GFX10-NEXT: s_mov_b32 s35, external_void_func_i32_inreg@abs32@hi ; GFX10-NEXT: s_mov_b32 s34, external_void_func_i32_inreg@abs32@lo +; GFX10-NEXT: s_mov_b32 s0, 42 ; GFX10-NEXT: s_addk_i32 s32, 0x200 -; GFX10-NEXT: v_writelane_b32 v40, s4, 0 -; GFX10-NEXT: s_mov_b32 s4, 42 -; GFX10-NEXT: v_writelane_b32 v40, s30, 1 -; GFX10-NEXT: v_writelane_b32 v40, s31, 2 +; GFX10-NEXT: v_writelane_b32 v40, s30, 0 +; GFX10-NEXT: v_writelane_b32 v40, s31, 1 ; GFX10-NEXT: s_swappc_b64 s[30:31], s[34:35] -; GFX10-NEXT: v_readlane_b32 s31, v40, 2 -; GFX10-NEXT: v_readlane_b32 s30, v40, 1 -; GFX10-NEXT: v_readlane_b32 s4, v40, 0 -; GFX10-NEXT: v_readlane_b32 s34, v40, 3 +; GFX10-NEXT: v_readlane_b32 s31, v40, 1 +; GFX10-NEXT: v_readlane_b32 s30, v40, 0 +; GFX10-NEXT: v_readlane_b32 s34, v40, 2 ; GFX10-NEXT: s_or_saveexec_b32 s35, -1 ; GFX10-NEXT: buffer_load_dword v40, off, s[0:3], s33 ; 4-byte Folded Reload ; GFX10-NEXT: s_waitcnt_depctr 0xffe3 @@ -9877,20 +9857,18 @@ define amdgpu_gfx void @test_call_external_void_func_i32_imm_inreg(i32) #0 { ; GFX11-NEXT: s_or_saveexec_b32 s1, -1 ; GFX11-NEXT: scratch_store_b32 off, v40, s33 ; 4-byte Folded Spill ; GFX11-NEXT: s_mov_b32 exec_lo, s1 -; GFX11-NEXT: v_writelane_b32 v40, s0, 3 -; GFX11-NEXT: s_mov_b32 s1, external_void_func_i32_inreg@abs32@hi -; GFX11-NEXT: s_mov_b32 s0, external_void_func_i32_inreg@abs32@lo +; GFX11-NEXT: v_writelane_b32 v40, s0, 2 +; GFX11-NEXT: s_mov_b32 s3, external_void_func_i32_inreg@abs32@hi +; GFX11-NEXT: s_mov_b32 s2, external_void_func_i32_inreg@abs32@lo +; GFX11-NEXT: s_mov_b32 s0, 42 ; GFX11-NEXT: s_add_i32 s32, s32, 16 -; GFX11-NEXT: v_writelane_b32 v40, s4, 0 -; GFX11-NEXT: s_mov_b32 s4, 42 -; GFX11-NEXT: v_writelane_b32 v40, s30, 1 -; GFX11-NEXT: v_writelane_b32 v40, s31, 2 -; GFX11-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX11-NEXT: v_writelane_b32 v40, s30, 0 +; GFX11-NEXT: v_writelane_b32 v40, s31, 1 +; GFX11-NEXT: s_swappc_b64 s[30:31], s[2:3] ; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_1) -; GFX11-NEXT: v_readlane_b32 s31, v40, 2 -; GFX11-NEXT: v_readlane_b32 s30, v40, 1 -; GFX11-NEXT: v_readlane_b32 s4, v40, 0 -; GFX11-NEXT: v_readlane_b32 s0, v40, 3 +; GFX11-NEXT: v_readlane_b32 s31, v40, 1 +; GFX11-NEXT: v_readlane_b32 s30, v40, 0 +; GFX11-NEXT: v_readlane_b32 s0, v40, 2 ; GFX11-NEXT: s_or_saveexec_b32 s1, -1 ; GFX11-NEXT: scratch_load_b32 v40, off, s33 ; 4-byte Folded Reload ; GFX11-NEXT: s_mov_b32 exec_lo, s1 @@ -9908,19 +9886,17 @@ define amdgpu_gfx void @test_call_external_void_func_i32_imm_inreg(i32) #0 { ; GFX10-SCRATCH-NEXT: scratch_store_dword off, v40, s33 ; 4-byte Folded Spill ; GFX10-SCRATCH-NEXT: s_waitcnt_depctr 0xffe3 ; GFX10-SCRATCH-NEXT: s_mov_b32 exec_lo, s1 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s0, 3 -; GFX10-SCRATCH-NEXT: s_mov_b32 s1, external_void_func_i32_inreg@abs32@hi -; GFX10-SCRATCH-NEXT: s_mov_b32 s0, external_void_func_i32_inreg@abs32@lo +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s0, 2 +; GFX10-SCRATCH-NEXT: s_mov_b32 s3, external_void_func_i32_inreg@abs32@hi +; GFX10-SCRATCH-NEXT: s_mov_b32 s2, external_void_func_i32_inreg@abs32@lo +; GFX10-SCRATCH-NEXT: s_mov_b32 s0, 42 ; GFX10-SCRATCH-NEXT: s_add_i32 s32, s32, 16 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s4, 0 -; GFX10-SCRATCH-NEXT: s_mov_b32 s4, 42 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s30, 1 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s31, 2 -; GFX10-SCRATCH-NEXT: s_swappc_b64 s[30:31], s[0:1] -; GFX10-SCRATCH-NEXT: v_readlane_b32 s31, v40, 2 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s30, v40, 1 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s4, v40, 0 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s0, v40, 3 +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s30, 0 +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s31, 1 +; GFX10-SCRATCH-NEXT: s_swappc_b64 s[30:31], s[2:3] +; GFX10-SCRATCH-NEXT: v_readlane_b32 s31, v40, 1 +; GFX10-SCRATCH-NEXT: v_readlane_b32 s30, v40, 0 +; GFX10-SCRATCH-NEXT: v_readlane_b32 s0, v40, 2 ; GFX10-SCRATCH-NEXT: s_or_saveexec_b32 s1, -1 ; GFX10-SCRATCH-NEXT: scratch_load_dword v40, off, s33 ; 4-byte Folded Reload ; GFX10-SCRATCH-NEXT: s_waitcnt_depctr 0xffe3 @@ -9942,22 +9918,18 @@ define amdgpu_gfx void @test_call_external_void_func_i64_imm_inreg() #0 { ; GFX9-NEXT: s_or_saveexec_b64 s[36:37], -1 ; GFX9-NEXT: buffer_store_dword v40, off, s[0:3], s33 ; 4-byte Folded Spill ; GFX9-NEXT: s_mov_b64 exec, s[36:37] -; GFX9-NEXT: v_writelane_b32 v40, s34, 4 -; GFX9-NEXT: v_writelane_b32 v40, s4, 0 -; GFX9-NEXT: v_writelane_b32 v40, s5, 1 -; GFX9-NEXT: v_writelane_b32 v40, s30, 2 +; GFX9-NEXT: v_writelane_b32 v40, s34, 2 +; GFX9-NEXT: v_writelane_b32 v40, s30, 0 ; GFX9-NEXT: s_mov_b32 s35, external_void_func_i64_inreg@abs32@hi ; GFX9-NEXT: s_mov_b32 s34, external_void_func_i64_inreg@abs32@lo -; GFX9-NEXT: s_movk_i32 s4, 0x7b -; GFX9-NEXT: s_mov_b32 s5, 0 +; GFX9-NEXT: s_movk_i32 s0, 0x7b +; GFX9-NEXT: s_mov_b32 s1, 0 ; GFX9-NEXT: s_addk_i32 s32, 0x400 -; GFX9-NEXT: v_writelane_b32 v40, s31, 3 +; GFX9-NEXT: v_writelane_b32 v40, s31, 1 ; GFX9-NEXT: s_swappc_b64 s[30:31], s[34:35] -; GFX9-NEXT: v_readlane_b32 s31, v40, 3 -; GFX9-NEXT: v_readlane_b32 s30, v40, 2 -; GFX9-NEXT: v_readlane_b32 s5, v40, 1 -; GFX9-NEXT: v_readlane_b32 s4, v40, 0 -; GFX9-NEXT: v_readlane_b32 s34, v40, 4 +; GFX9-NEXT: v_readlane_b32 s31, v40, 1 +; GFX9-NEXT: v_readlane_b32 s30, v40, 0 +; GFX9-NEXT: v_readlane_b32 s34, v40, 2 ; GFX9-NEXT: s_or_saveexec_b64 s[36:37], -1 ; GFX9-NEXT: buffer_load_dword v40, off, s[0:3], s33 ; 4-byte Folded Reload ; GFX9-NEXT: s_mov_b64 exec, s[36:37] @@ -9975,22 +9947,18 @@ define amdgpu_gfx void @test_call_external_void_func_i64_imm_inreg() #0 { ; GFX10-NEXT: buffer_store_dword v40, off, s[0:3], s33 ; 4-byte Folded Spill ; GFX10-NEXT: s_waitcnt_depctr 0xffe3 ; GFX10-NEXT: s_mov_b32 exec_lo, s35 -; GFX10-NEXT: v_writelane_b32 v40, s34, 4 +; GFX10-NEXT: v_writelane_b32 v40, s34, 2 ; GFX10-NEXT: s_mov_b32 s35, external_void_func_i64_inreg@abs32@hi ; GFX10-NEXT: s_mov_b32 s34, external_void_func_i64_inreg@abs32@lo +; GFX10-NEXT: s_movk_i32 s0, 0x7b +; GFX10-NEXT: s_mov_b32 s1, 0 +; GFX10-NEXT: v_writelane_b32 v40, s30, 0 ; GFX10-NEXT: s_addk_i32 s32, 0x200 -; GFX10-NEXT: v_writelane_b32 v40, s4, 0 -; GFX10-NEXT: s_movk_i32 s4, 0x7b -; GFX10-NEXT: v_writelane_b32 v40, s5, 1 -; GFX10-NEXT: s_mov_b32 s5, 0 -; GFX10-NEXT: v_writelane_b32 v40, s30, 2 -; GFX10-NEXT: v_writelane_b32 v40, s31, 3 +; GFX10-NEXT: v_writelane_b32 v40, s31, 1 ; GFX10-NEXT: s_swappc_b64 s[30:31], s[34:35] -; GFX10-NEXT: v_readlane_b32 s31, v40, 3 -; GFX10-NEXT: v_readlane_b32 s30, v40, 2 -; GFX10-NEXT: v_readlane_b32 s5, v40, 1 -; GFX10-NEXT: v_readlane_b32 s4, v40, 0 -; GFX10-NEXT: v_readlane_b32 s34, v40, 4 +; GFX10-NEXT: v_readlane_b32 s31, v40, 1 +; GFX10-NEXT: v_readlane_b32 s30, v40, 0 +; GFX10-NEXT: v_readlane_b32 s34, v40, 2 ; GFX10-NEXT: s_or_saveexec_b32 s35, -1 ; GFX10-NEXT: buffer_load_dword v40, off, s[0:3], s33 ; 4-byte Folded Reload ; GFX10-NEXT: s_waitcnt_depctr 0xffe3 @@ -10008,23 +9976,19 @@ define amdgpu_gfx void @test_call_external_void_func_i64_imm_inreg() #0 { ; GFX11-NEXT: s_or_saveexec_b32 s1, -1 ; GFX11-NEXT: scratch_store_b32 off, v40, s33 ; 4-byte Folded Spill ; GFX11-NEXT: s_mov_b32 exec_lo, s1 -; GFX11-NEXT: v_writelane_b32 v40, s0, 4 -; GFX11-NEXT: s_mov_b32 s1, external_void_func_i64_inreg@abs32@hi -; GFX11-NEXT: s_mov_b32 s0, external_void_func_i64_inreg@abs32@lo +; GFX11-NEXT: v_writelane_b32 v40, s0, 2 +; GFX11-NEXT: s_mov_b32 s3, external_void_func_i64_inreg@abs32@hi +; GFX11-NEXT: s_mov_b32 s2, external_void_func_i64_inreg@abs32@lo +; GFX11-NEXT: s_movk_i32 s0, 0x7b +; GFX11-NEXT: s_mov_b32 s1, 0 +; GFX11-NEXT: v_writelane_b32 v40, s30, 0 ; GFX11-NEXT: s_add_i32 s32, s32, 16 -; GFX11-NEXT: v_writelane_b32 v40, s4, 0 -; GFX11-NEXT: s_movk_i32 s4, 0x7b -; GFX11-NEXT: v_writelane_b32 v40, s5, 1 -; GFX11-NEXT: s_mov_b32 s5, 0 -; GFX11-NEXT: v_writelane_b32 v40, s30, 2 -; GFX11-NEXT: v_writelane_b32 v40, s31, 3 -; GFX11-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX11-NEXT: v_writelane_b32 v40, s31, 1 +; GFX11-NEXT: s_swappc_b64 s[30:31], s[2:3] ; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_1) -; GFX11-NEXT: v_readlane_b32 s31, v40, 3 -; GFX11-NEXT: v_readlane_b32 s30, v40, 2 -; GFX11-NEXT: v_readlane_b32 s5, v40, 1 -; GFX11-NEXT: v_readlane_b32 s4, v40, 0 -; GFX11-NEXT: v_readlane_b32 s0, v40, 4 +; GFX11-NEXT: v_readlane_b32 s31, v40, 1 +; GFX11-NEXT: v_readlane_b32 s30, v40, 0 +; GFX11-NEXT: v_readlane_b32 s0, v40, 2 ; GFX11-NEXT: s_or_saveexec_b32 s1, -1 ; GFX11-NEXT: scratch_load_b32 v40, off, s33 ; 4-byte Folded Reload ; GFX11-NEXT: s_mov_b32 exec_lo, s1 @@ -10042,22 +10006,18 @@ define amdgpu_gfx void @test_call_external_void_func_i64_imm_inreg() #0 { ; GFX10-SCRATCH-NEXT: scratch_store_dword off, v40, s33 ; 4-byte Folded Spill ; GFX10-SCRATCH-NEXT: s_waitcnt_depctr 0xffe3 ; GFX10-SCRATCH-NEXT: s_mov_b32 exec_lo, s1 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s0, 4 -; GFX10-SCRATCH-NEXT: s_mov_b32 s1, external_void_func_i64_inreg@abs32@hi -; GFX10-SCRATCH-NEXT: s_mov_b32 s0, external_void_func_i64_inreg@abs32@lo +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s0, 2 +; GFX10-SCRATCH-NEXT: s_mov_b32 s3, external_void_func_i64_inreg@abs32@hi +; GFX10-SCRATCH-NEXT: s_mov_b32 s2, external_void_func_i64_inreg@abs32@lo +; GFX10-SCRATCH-NEXT: s_movk_i32 s0, 0x7b +; GFX10-SCRATCH-NEXT: s_mov_b32 s1, 0 +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s30, 0 ; GFX10-SCRATCH-NEXT: s_add_i32 s32, s32, 16 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s4, 0 -; GFX10-SCRATCH-NEXT: s_movk_i32 s4, 0x7b -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s5, 1 -; GFX10-SCRATCH-NEXT: s_mov_b32 s5, 0 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s30, 2 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s31, 3 -; GFX10-SCRATCH-NEXT: s_swappc_b64 s[30:31], s[0:1] -; GFX10-SCRATCH-NEXT: v_readlane_b32 s31, v40, 3 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s30, v40, 2 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s5, v40, 1 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s4, v40, 0 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s0, v40, 4 +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s31, 1 +; GFX10-SCRATCH-NEXT: s_swappc_b64 s[30:31], s[2:3] +; GFX10-SCRATCH-NEXT: v_readlane_b32 s31, v40, 1 +; GFX10-SCRATCH-NEXT: v_readlane_b32 s30, v40, 0 +; GFX10-SCRATCH-NEXT: v_readlane_b32 s0, v40, 2 ; GFX10-SCRATCH-NEXT: s_or_saveexec_b32 s1, -1 ; GFX10-SCRATCH-NEXT: scratch_load_dword v40, off, s33 ; 4-byte Folded Reload ; GFX10-SCRATCH-NEXT: s_waitcnt_depctr 0xffe3 @@ -10079,26 +10039,23 @@ define amdgpu_gfx void @test_call_external_void_func_v2i64_inreg() #0 { ; GFX9-NEXT: s_or_saveexec_b64 s[36:37], -1 ; GFX9-NEXT: buffer_store_dword v40, off, s[0:3], s33 ; 4-byte Folded Spill ; GFX9-NEXT: s_mov_b64 exec, s[36:37] -; GFX9-NEXT: v_writelane_b32 v40, s34, 6 -; GFX9-NEXT: v_writelane_b32 v40, s4, 0 -; GFX9-NEXT: v_writelane_b32 v40, s5, 1 -; GFX9-NEXT: v_writelane_b32 v40, s6, 2 +; GFX9-NEXT: v_writelane_b32 v40, s34, 2 ; GFX9-NEXT: s_mov_b64 s[34:35], 0 -; GFX9-NEXT: v_writelane_b32 v40, s7, 3 -; GFX9-NEXT: s_load_dwordx4 s[4:7], s[34:35], 0x0 -; GFX9-NEXT: v_writelane_b32 v40, s30, 4 +; GFX9-NEXT: s_load_dwordx4 s[36:39], s[34:35], 0x0 +; GFX9-NEXT: v_writelane_b32 v40, s30, 0 ; GFX9-NEXT: s_mov_b32 s35, external_void_func_v2i64_inreg@abs32@hi ; GFX9-NEXT: s_mov_b32 s34, external_void_func_v2i64_inreg@abs32@lo ; GFX9-NEXT: s_addk_i32 s32, 0x400 -; GFX9-NEXT: v_writelane_b32 v40, s31, 5 +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: s_mov_b32 s0, s36 +; GFX9-NEXT: s_mov_b32 s1, s37 +; GFX9-NEXT: s_mov_b32 s2, s38 +; GFX9-NEXT: s_mov_b32 s3, s39 +; GFX9-NEXT: v_writelane_b32 v40, s31, 1 ; GFX9-NEXT: s_swappc_b64 s[30:31], s[34:35] -; GFX9-NEXT: v_readlane_b32 s31, v40, 5 -; GFX9-NEXT: v_readlane_b32 s30, v40, 4 -; GFX9-NEXT: v_readlane_b32 s7, v40, 3 -; GFX9-NEXT: v_readlane_b32 s6, v40, 2 -; GFX9-NEXT: v_readlane_b32 s5, v40, 1 -; GFX9-NEXT: v_readlane_b32 s4, v40, 0 -; GFX9-NEXT: v_readlane_b32 s34, v40, 6 +; GFX9-NEXT: v_readlane_b32 s31, v40, 1 +; GFX9-NEXT: v_readlane_b32 s30, v40, 0 +; GFX9-NEXT: v_readlane_b32 s34, v40, 2 ; GFX9-NEXT: s_or_saveexec_b64 s[36:37], -1 ; GFX9-NEXT: buffer_load_dword v40, off, s[0:3], s33 ; 4-byte Folded Reload ; GFX9-NEXT: s_mov_b64 exec, s[36:37] @@ -10116,26 +10073,23 @@ define amdgpu_gfx void @test_call_external_void_func_v2i64_inreg() #0 { ; GFX10-NEXT: buffer_store_dword v40, off, s[0:3], s33 ; 4-byte Folded Spill ; GFX10-NEXT: s_waitcnt_depctr 0xffe3 ; GFX10-NEXT: s_mov_b32 exec_lo, s35 -; GFX10-NEXT: v_writelane_b32 v40, s34, 6 +; GFX10-NEXT: v_writelane_b32 v40, s34, 2 ; GFX10-NEXT: s_mov_b64 s[34:35], 0 ; GFX10-NEXT: s_addk_i32 s32, 0x200 -; GFX10-NEXT: v_writelane_b32 v40, s4, 0 -; GFX10-NEXT: v_writelane_b32 v40, s5, 1 -; GFX10-NEXT: v_writelane_b32 v40, s6, 2 -; GFX10-NEXT: v_writelane_b32 v40, s7, 3 -; GFX10-NEXT: s_load_dwordx4 s[4:7], s[34:35], 0x0 +; GFX10-NEXT: s_load_dwordx4 s[36:39], s[34:35], 0x0 ; GFX10-NEXT: s_mov_b32 s35, external_void_func_v2i64_inreg@abs32@hi +; GFX10-NEXT: v_writelane_b32 v40, s30, 0 ; GFX10-NEXT: s_mov_b32 s34, external_void_func_v2i64_inreg@abs32@lo -; GFX10-NEXT: v_writelane_b32 v40, s30, 4 -; GFX10-NEXT: v_writelane_b32 v40, s31, 5 +; GFX10-NEXT: v_writelane_b32 v40, s31, 1 +; GFX10-NEXT: s_waitcnt lgkmcnt(0) +; GFX10-NEXT: s_mov_b32 s0, s36 +; GFX10-NEXT: s_mov_b32 s1, s37 +; GFX10-NEXT: s_mov_b32 s2, s38 +; GFX10-NEXT: s_mov_b32 s3, s39 ; GFX10-NEXT: s_swappc_b64 s[30:31], s[34:35] -; GFX10-NEXT: v_readlane_b32 s31, v40, 5 -; GFX10-NEXT: v_readlane_b32 s30, v40, 4 -; GFX10-NEXT: v_readlane_b32 s7, v40, 3 -; GFX10-NEXT: v_readlane_b32 s6, v40, 2 -; GFX10-NEXT: v_readlane_b32 s5, v40, 1 -; GFX10-NEXT: v_readlane_b32 s4, v40, 0 -; GFX10-NEXT: v_readlane_b32 s34, v40, 6 +; GFX10-NEXT: v_readlane_b32 s31, v40, 1 +; GFX10-NEXT: v_readlane_b32 s30, v40, 0 +; GFX10-NEXT: v_readlane_b32 s34, v40, 2 ; GFX10-NEXT: s_or_saveexec_b32 s35, -1 ; GFX10-NEXT: buffer_load_dword v40, off, s[0:3], s33 ; 4-byte Folded Reload ; GFX10-NEXT: s_waitcnt_depctr 0xffe3 @@ -10153,27 +10107,19 @@ define amdgpu_gfx void @test_call_external_void_func_v2i64_inreg() #0 { ; GFX11-NEXT: s_or_saveexec_b32 s1, -1 ; GFX11-NEXT: scratch_store_b32 off, v40, s33 ; 4-byte Folded Spill ; GFX11-NEXT: s_mov_b32 exec_lo, s1 -; GFX11-NEXT: v_writelane_b32 v40, s0, 6 +; GFX11-NEXT: v_writelane_b32 v40, s0, 2 ; GFX11-NEXT: s_mov_b64 s[0:1], 0 +; GFX11-NEXT: s_mov_b32 s35, external_void_func_v2i64_inreg@abs32@hi +; GFX11-NEXT: s_load_b128 s[0:3], s[0:1], 0x0 +; GFX11-NEXT: s_mov_b32 s34, external_void_func_v2i64_inreg@abs32@lo +; GFX11-NEXT: v_writelane_b32 v40, s30, 0 ; GFX11-NEXT: s_add_i32 s32, s32, 16 -; GFX11-NEXT: v_writelane_b32 v40, s4, 0 -; GFX11-NEXT: v_writelane_b32 v40, s5, 1 -; GFX11-NEXT: v_writelane_b32 v40, s6, 2 -; GFX11-NEXT: v_writelane_b32 v40, s7, 3 -; GFX11-NEXT: s_load_b128 s[4:7], s[0:1], 0x0 -; GFX11-NEXT: s_mov_b32 s1, external_void_func_v2i64_inreg@abs32@hi -; GFX11-NEXT: s_mov_b32 s0, external_void_func_v2i64_inreg@abs32@lo -; GFX11-NEXT: v_writelane_b32 v40, s30, 4 -; GFX11-NEXT: v_writelane_b32 v40, s31, 5 -; GFX11-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX11-NEXT: v_writelane_b32 v40, s31, 1 +; GFX11-NEXT: s_swappc_b64 s[30:31], s[34:35] ; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_1) -; GFX11-NEXT: v_readlane_b32 s31, v40, 5 -; GFX11-NEXT: v_readlane_b32 s30, v40, 4 -; GFX11-NEXT: v_readlane_b32 s7, v40, 3 -; GFX11-NEXT: v_readlane_b32 s6, v40, 2 -; GFX11-NEXT: v_readlane_b32 s5, v40, 1 -; GFX11-NEXT: v_readlane_b32 s4, v40, 0 -; GFX11-NEXT: v_readlane_b32 s0, v40, 6 +; GFX11-NEXT: v_readlane_b32 s31, v40, 1 +; GFX11-NEXT: v_readlane_b32 s30, v40, 0 +; GFX11-NEXT: v_readlane_b32 s0, v40, 2 ; GFX11-NEXT: s_or_saveexec_b32 s1, -1 ; GFX11-NEXT: scratch_load_b32 v40, off, s33 ; 4-byte Folded Reload ; GFX11-NEXT: s_mov_b32 exec_lo, s1 @@ -10191,26 +10137,18 @@ define amdgpu_gfx void @test_call_external_void_func_v2i64_inreg() #0 { ; GFX10-SCRATCH-NEXT: scratch_store_dword off, v40, s33 ; 4-byte Folded Spill ; GFX10-SCRATCH-NEXT: s_waitcnt_depctr 0xffe3 ; GFX10-SCRATCH-NEXT: s_mov_b32 exec_lo, s1 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s0, 6 +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s0, 2 ; GFX10-SCRATCH-NEXT: s_mov_b64 s[0:1], 0 +; GFX10-SCRATCH-NEXT: s_mov_b32 s35, external_void_func_v2i64_inreg@abs32@hi +; GFX10-SCRATCH-NEXT: s_load_dwordx4 s[0:3], s[0:1], 0x0 +; GFX10-SCRATCH-NEXT: s_mov_b32 s34, external_void_func_v2i64_inreg@abs32@lo +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s30, 0 ; GFX10-SCRATCH-NEXT: s_add_i32 s32, s32, 16 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s4, 0 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s5, 1 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s6, 2 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s7, 3 -; GFX10-SCRATCH-NEXT: s_load_dwordx4 s[4:7], s[0:1], 0x0 -; GFX10-SCRATCH-NEXT: s_mov_b32 s1, external_void_func_v2i64_inreg@abs32@hi -; GFX10-SCRATCH-NEXT: s_mov_b32 s0, external_void_func_v2i64_inreg@abs32@lo -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s30, 4 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s31, 5 -; GFX10-SCRATCH-NEXT: s_swappc_b64 s[30:31], s[0:1] -; GFX10-SCRATCH-NEXT: v_readlane_b32 s31, v40, 5 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s30, v40, 4 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s7, v40, 3 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s6, v40, 2 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s5, v40, 1 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s4, v40, 0 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s0, v40, 6 +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s31, 1 +; GFX10-SCRATCH-NEXT: s_swappc_b64 s[30:31], s[34:35] +; GFX10-SCRATCH-NEXT: v_readlane_b32 s31, v40, 1 +; GFX10-SCRATCH-NEXT: v_readlane_b32 s30, v40, 0 +; GFX10-SCRATCH-NEXT: v_readlane_b32 s0, v40, 2 ; GFX10-SCRATCH-NEXT: s_or_saveexec_b32 s1, -1 ; GFX10-SCRATCH-NEXT: scratch_load_dword v40, off, s33 ; 4-byte Folded Reload ; GFX10-SCRATCH-NEXT: s_waitcnt_depctr 0xffe3 @@ -10233,28 +10171,20 @@ define amdgpu_gfx void @test_call_external_void_func_v2i64_imm_inreg() #0 { ; GFX9-NEXT: s_or_saveexec_b64 s[36:37], -1 ; GFX9-NEXT: buffer_store_dword v40, off, s[0:3], s33 ; 4-byte Folded Spill ; GFX9-NEXT: s_mov_b64 exec, s[36:37] -; GFX9-NEXT: v_writelane_b32 v40, s34, 6 -; GFX9-NEXT: v_writelane_b32 v40, s4, 0 -; GFX9-NEXT: v_writelane_b32 v40, s5, 1 -; GFX9-NEXT: v_writelane_b32 v40, s6, 2 -; GFX9-NEXT: v_writelane_b32 v40, s7, 3 -; GFX9-NEXT: v_writelane_b32 v40, s30, 4 +; GFX9-NEXT: v_writelane_b32 v40, s34, 2 +; GFX9-NEXT: v_writelane_b32 v40, s30, 0 ; GFX9-NEXT: s_mov_b32 s35, external_void_func_v2i64_inreg@abs32@hi ; GFX9-NEXT: s_mov_b32 s34, external_void_func_v2i64_inreg@abs32@lo -; GFX9-NEXT: s_mov_b32 s4, 1 -; GFX9-NEXT: s_mov_b32 s5, 2 -; GFX9-NEXT: s_mov_b32 s6, 3 -; GFX9-NEXT: s_mov_b32 s7, 4 +; GFX9-NEXT: s_mov_b32 s0, 1 +; GFX9-NEXT: s_mov_b32 s1, 2 +; GFX9-NEXT: s_mov_b32 s2, 3 +; GFX9-NEXT: s_mov_b32 s3, 4 ; GFX9-NEXT: s_addk_i32 s32, 0x400 -; GFX9-NEXT: v_writelane_b32 v40, s31, 5 +; GFX9-NEXT: v_writelane_b32 v40, s31, 1 ; GFX9-NEXT: s_swappc_b64 s[30:31], s[34:35] -; GFX9-NEXT: v_readlane_b32 s31, v40, 5 -; GFX9-NEXT: v_readlane_b32 s30, v40, 4 -; GFX9-NEXT: v_readlane_b32 s7, v40, 3 -; GFX9-NEXT: v_readlane_b32 s6, v40, 2 -; GFX9-NEXT: v_readlane_b32 s5, v40, 1 -; GFX9-NEXT: v_readlane_b32 s4, v40, 0 -; GFX9-NEXT: v_readlane_b32 s34, v40, 6 +; GFX9-NEXT: v_readlane_b32 s31, v40, 1 +; GFX9-NEXT: v_readlane_b32 s30, v40, 0 +; GFX9-NEXT: v_readlane_b32 s34, v40, 2 ; GFX9-NEXT: s_or_saveexec_b64 s[36:37], -1 ; GFX9-NEXT: buffer_load_dword v40, off, s[0:3], s33 ; 4-byte Folded Reload ; GFX9-NEXT: s_mov_b64 exec, s[36:37] @@ -10272,28 +10202,20 @@ define amdgpu_gfx void @test_call_external_void_func_v2i64_imm_inreg() #0 { ; GFX10-NEXT: buffer_store_dword v40, off, s[0:3], s33 ; 4-byte Folded Spill ; GFX10-NEXT: s_waitcnt_depctr 0xffe3 ; GFX10-NEXT: s_mov_b32 exec_lo, s35 -; GFX10-NEXT: v_writelane_b32 v40, s34, 6 +; GFX10-NEXT: v_writelane_b32 v40, s34, 2 ; GFX10-NEXT: s_mov_b32 s35, external_void_func_v2i64_inreg@abs32@hi ; GFX10-NEXT: s_mov_b32 s34, external_void_func_v2i64_inreg@abs32@lo +; GFX10-NEXT: s_mov_b32 s0, 1 +; GFX10-NEXT: s_mov_b32 s1, 2 +; GFX10-NEXT: v_writelane_b32 v40, s30, 0 +; GFX10-NEXT: s_mov_b32 s2, 3 +; GFX10-NEXT: s_mov_b32 s3, 4 ; GFX10-NEXT: s_addk_i32 s32, 0x200 -; GFX10-NEXT: v_writelane_b32 v40, s4, 0 -; GFX10-NEXT: s_mov_b32 s4, 1 -; GFX10-NEXT: v_writelane_b32 v40, s5, 1 -; GFX10-NEXT: s_mov_b32 s5, 2 -; GFX10-NEXT: v_writelane_b32 v40, s6, 2 -; GFX10-NEXT: s_mov_b32 s6, 3 -; GFX10-NEXT: v_writelane_b32 v40, s7, 3 -; GFX10-NEXT: s_mov_b32 s7, 4 -; GFX10-NEXT: v_writelane_b32 v40, s30, 4 -; GFX10-NEXT: v_writelane_b32 v40, s31, 5 +; GFX10-NEXT: v_writelane_b32 v40, s31, 1 ; GFX10-NEXT: s_swappc_b64 s[30:31], s[34:35] -; GFX10-NEXT: v_readlane_b32 s31, v40, 5 -; GFX10-NEXT: v_readlane_b32 s30, v40, 4 -; GFX10-NEXT: v_readlane_b32 s7, v40, 3 -; GFX10-NEXT: v_readlane_b32 s6, v40, 2 -; GFX10-NEXT: v_readlane_b32 s5, v40, 1 -; GFX10-NEXT: v_readlane_b32 s4, v40, 0 -; GFX10-NEXT: v_readlane_b32 s34, v40, 6 +; GFX10-NEXT: v_readlane_b32 s31, v40, 1 +; GFX10-NEXT: v_readlane_b32 s30, v40, 0 +; GFX10-NEXT: v_readlane_b32 s34, v40, 2 ; GFX10-NEXT: s_or_saveexec_b32 s35, -1 ; GFX10-NEXT: buffer_load_dword v40, off, s[0:3], s33 ; 4-byte Folded Reload ; GFX10-NEXT: s_waitcnt_depctr 0xffe3 @@ -10311,29 +10233,21 @@ define amdgpu_gfx void @test_call_external_void_func_v2i64_imm_inreg() #0 { ; GFX11-NEXT: s_or_saveexec_b32 s1, -1 ; GFX11-NEXT: scratch_store_b32 off, v40, s33 ; 4-byte Folded Spill ; GFX11-NEXT: s_mov_b32 exec_lo, s1 -; GFX11-NEXT: v_writelane_b32 v40, s0, 6 -; GFX11-NEXT: s_mov_b32 s1, external_void_func_v2i64_inreg@abs32@hi -; GFX11-NEXT: s_mov_b32 s0, external_void_func_v2i64_inreg@abs32@lo +; GFX11-NEXT: v_writelane_b32 v40, s0, 2 +; GFX11-NEXT: s_mov_b32 s35, external_void_func_v2i64_inreg@abs32@hi +; GFX11-NEXT: s_mov_b32 s34, external_void_func_v2i64_inreg@abs32@lo +; GFX11-NEXT: s_mov_b32 s0, 1 +; GFX11-NEXT: s_mov_b32 s1, 2 +; GFX11-NEXT: v_writelane_b32 v40, s30, 0 +; GFX11-NEXT: s_mov_b32 s2, 3 +; GFX11-NEXT: s_mov_b32 s3, 4 ; GFX11-NEXT: s_add_i32 s32, s32, 16 -; GFX11-NEXT: v_writelane_b32 v40, s4, 0 -; GFX11-NEXT: s_mov_b32 s4, 1 -; GFX11-NEXT: v_writelane_b32 v40, s5, 1 -; GFX11-NEXT: s_mov_b32 s5, 2 -; GFX11-NEXT: v_writelane_b32 v40, s6, 2 -; GFX11-NEXT: s_mov_b32 s6, 3 -; GFX11-NEXT: v_writelane_b32 v40, s7, 3 -; GFX11-NEXT: s_mov_b32 s7, 4 -; GFX11-NEXT: v_writelane_b32 v40, s30, 4 -; GFX11-NEXT: v_writelane_b32 v40, s31, 5 -; GFX11-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX11-NEXT: v_writelane_b32 v40, s31, 1 +; GFX11-NEXT: s_swappc_b64 s[30:31], s[34:35] ; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_1) -; GFX11-NEXT: v_readlane_b32 s31, v40, 5 -; GFX11-NEXT: v_readlane_b32 s30, v40, 4 -; GFX11-NEXT: v_readlane_b32 s7, v40, 3 -; GFX11-NEXT: v_readlane_b32 s6, v40, 2 -; GFX11-NEXT: v_readlane_b32 s5, v40, 1 -; GFX11-NEXT: v_readlane_b32 s4, v40, 0 -; GFX11-NEXT: v_readlane_b32 s0, v40, 6 +; GFX11-NEXT: v_readlane_b32 s31, v40, 1 +; GFX11-NEXT: v_readlane_b32 s30, v40, 0 +; GFX11-NEXT: v_readlane_b32 s0, v40, 2 ; GFX11-NEXT: s_or_saveexec_b32 s1, -1 ; GFX11-NEXT: scratch_load_b32 v40, off, s33 ; 4-byte Folded Reload ; GFX11-NEXT: s_mov_b32 exec_lo, s1 @@ -10351,28 +10265,20 @@ define amdgpu_gfx void @test_call_external_void_func_v2i64_imm_inreg() #0 { ; GFX10-SCRATCH-NEXT: scratch_store_dword off, v40, s33 ; 4-byte Folded Spill ; GFX10-SCRATCH-NEXT: s_waitcnt_depctr 0xffe3 ; GFX10-SCRATCH-NEXT: s_mov_b32 exec_lo, s1 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s0, 6 -; GFX10-SCRATCH-NEXT: s_mov_b32 s1, external_void_func_v2i64_inreg@abs32@hi -; GFX10-SCRATCH-NEXT: s_mov_b32 s0, external_void_func_v2i64_inreg@abs32@lo +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s0, 2 +; GFX10-SCRATCH-NEXT: s_mov_b32 s35, external_void_func_v2i64_inreg@abs32@hi +; GFX10-SCRATCH-NEXT: s_mov_b32 s34, external_void_func_v2i64_inreg@abs32@lo +; GFX10-SCRATCH-NEXT: s_mov_b32 s0, 1 +; GFX10-SCRATCH-NEXT: s_mov_b32 s1, 2 +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s30, 0 +; GFX10-SCRATCH-NEXT: s_mov_b32 s2, 3 +; GFX10-SCRATCH-NEXT: s_mov_b32 s3, 4 ; GFX10-SCRATCH-NEXT: s_add_i32 s32, s32, 16 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s4, 0 -; GFX10-SCRATCH-NEXT: s_mov_b32 s4, 1 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s5, 1 -; GFX10-SCRATCH-NEXT: s_mov_b32 s5, 2 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s6, 2 -; GFX10-SCRATCH-NEXT: s_mov_b32 s6, 3 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s7, 3 -; GFX10-SCRATCH-NEXT: s_mov_b32 s7, 4 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s30, 4 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s31, 5 -; GFX10-SCRATCH-NEXT: s_swappc_b64 s[30:31], s[0:1] -; GFX10-SCRATCH-NEXT: v_readlane_b32 s31, v40, 5 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s30, v40, 4 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s7, v40, 3 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s6, v40, 2 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s5, v40, 1 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s4, v40, 0 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s0, v40, 6 +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s31, 1 +; GFX10-SCRATCH-NEXT: s_swappc_b64 s[30:31], s[34:35] +; GFX10-SCRATCH-NEXT: v_readlane_b32 s31, v40, 1 +; GFX10-SCRATCH-NEXT: v_readlane_b32 s30, v40, 0 +; GFX10-SCRATCH-NEXT: v_readlane_b32 s0, v40, 2 ; GFX10-SCRATCH-NEXT: s_or_saveexec_b32 s1, -1 ; GFX10-SCRATCH-NEXT: scratch_load_dword v40, off, s33 ; 4-byte Folded Reload ; GFX10-SCRATCH-NEXT: s_waitcnt_depctr 0xffe3 @@ -10394,32 +10300,29 @@ define amdgpu_gfx void @test_call_external_void_func_v3i64_inreg() #0 { ; GFX9-NEXT: s_or_saveexec_b64 s[36:37], -1 ; GFX9-NEXT: buffer_store_dword v40, off, s[0:3], s33 ; 4-byte Folded Spill ; GFX9-NEXT: s_mov_b64 exec, s[36:37] -; GFX9-NEXT: v_writelane_b32 v40, s34, 8 +; GFX9-NEXT: v_writelane_b32 v40, s34, 4 +; GFX9-NEXT: s_mov_b64 s[34:35], 0 +; GFX9-NEXT: s_load_dwordx4 s[36:39], s[34:35], 0x0 ; GFX9-NEXT: v_writelane_b32 v40, s4, 0 ; GFX9-NEXT: v_writelane_b32 v40, s5, 1 -; GFX9-NEXT: v_writelane_b32 v40, s6, 2 -; GFX9-NEXT: s_mov_b64 s[34:35], 0 -; GFX9-NEXT: v_writelane_b32 v40, s7, 3 -; GFX9-NEXT: s_load_dwordx4 s[4:7], s[34:35], 0x0 -; GFX9-NEXT: v_writelane_b32 v40, s8, 4 -; GFX9-NEXT: v_writelane_b32 v40, s9, 5 -; GFX9-NEXT: v_writelane_b32 v40, s30, 6 +; GFX9-NEXT: v_writelane_b32 v40, s30, 2 ; GFX9-NEXT: s_mov_b32 s35, external_void_func_v3i64_inreg@abs32@hi ; GFX9-NEXT: s_mov_b32 s34, external_void_func_v3i64_inreg@abs32@lo -; GFX9-NEXT: s_mov_b32 s8, 1 -; GFX9-NEXT: s_mov_b32 s9, 2 +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: s_mov_b32 s0, s36 +; GFX9-NEXT: s_mov_b32 s1, s37 +; GFX9-NEXT: s_mov_b32 s2, s38 +; GFX9-NEXT: s_mov_b32 s3, s39 +; GFX9-NEXT: s_mov_b32 s4, 1 +; GFX9-NEXT: s_mov_b32 s5, 2 ; GFX9-NEXT: s_addk_i32 s32, 0x400 -; GFX9-NEXT: v_writelane_b32 v40, s31, 7 +; GFX9-NEXT: v_writelane_b32 v40, s31, 3 ; GFX9-NEXT: s_swappc_b64 s[30:31], s[34:35] -; GFX9-NEXT: v_readlane_b32 s31, v40, 7 -; GFX9-NEXT: v_readlane_b32 s30, v40, 6 -; GFX9-NEXT: v_readlane_b32 s9, v40, 5 -; GFX9-NEXT: v_readlane_b32 s8, v40, 4 -; GFX9-NEXT: v_readlane_b32 s7, v40, 3 -; GFX9-NEXT: v_readlane_b32 s6, v40, 2 +; GFX9-NEXT: v_readlane_b32 s31, v40, 3 +; GFX9-NEXT: v_readlane_b32 s30, v40, 2 ; GFX9-NEXT: v_readlane_b32 s5, v40, 1 ; GFX9-NEXT: v_readlane_b32 s4, v40, 0 -; GFX9-NEXT: v_readlane_b32 s34, v40, 8 +; GFX9-NEXT: v_readlane_b32 s34, v40, 4 ; GFX9-NEXT: s_or_saveexec_b64 s[36:37], -1 ; GFX9-NEXT: buffer_load_dword v40, off, s[0:3], s33 ; 4-byte Folded Reload ; GFX9-NEXT: s_mov_b64 exec, s[36:37] @@ -10437,32 +10340,29 @@ define amdgpu_gfx void @test_call_external_void_func_v3i64_inreg() #0 { ; GFX10-NEXT: buffer_store_dword v40, off, s[0:3], s33 ; 4-byte Folded Spill ; GFX10-NEXT: s_waitcnt_depctr 0xffe3 ; GFX10-NEXT: s_mov_b32 exec_lo, s35 -; GFX10-NEXT: v_writelane_b32 v40, s34, 8 +; GFX10-NEXT: v_writelane_b32 v40, s34, 4 ; GFX10-NEXT: s_mov_b64 s[34:35], 0 ; GFX10-NEXT: s_addk_i32 s32, 0x200 -; GFX10-NEXT: v_writelane_b32 v40, s4, 0 -; GFX10-NEXT: v_writelane_b32 v40, s5, 1 -; GFX10-NEXT: v_writelane_b32 v40, s6, 2 -; GFX10-NEXT: v_writelane_b32 v40, s7, 3 -; GFX10-NEXT: s_load_dwordx4 s[4:7], s[34:35], 0x0 +; GFX10-NEXT: s_load_dwordx4 s[36:39], s[34:35], 0x0 ; GFX10-NEXT: s_mov_b32 s35, external_void_func_v3i64_inreg@abs32@hi +; GFX10-NEXT: v_writelane_b32 v40, s4, 0 ; GFX10-NEXT: s_mov_b32 s34, external_void_func_v3i64_inreg@abs32@lo -; GFX10-NEXT: v_writelane_b32 v40, s8, 4 -; GFX10-NEXT: s_mov_b32 s8, 1 -; GFX10-NEXT: v_writelane_b32 v40, s9, 5 -; GFX10-NEXT: s_mov_b32 s9, 2 -; GFX10-NEXT: v_writelane_b32 v40, s30, 6 -; GFX10-NEXT: v_writelane_b32 v40, s31, 7 +; GFX10-NEXT: s_mov_b32 s4, 1 +; GFX10-NEXT: v_writelane_b32 v40, s5, 1 +; GFX10-NEXT: s_mov_b32 s5, 2 +; GFX10-NEXT: v_writelane_b32 v40, s30, 2 +; GFX10-NEXT: v_writelane_b32 v40, s31, 3 +; GFX10-NEXT: s_waitcnt lgkmcnt(0) +; GFX10-NEXT: s_mov_b32 s0, s36 +; GFX10-NEXT: s_mov_b32 s1, s37 +; GFX10-NEXT: s_mov_b32 s2, s38 +; GFX10-NEXT: s_mov_b32 s3, s39 ; GFX10-NEXT: s_swappc_b64 s[30:31], s[34:35] -; GFX10-NEXT: v_readlane_b32 s31, v40, 7 -; GFX10-NEXT: v_readlane_b32 s30, v40, 6 -; GFX10-NEXT: v_readlane_b32 s9, v40, 5 -; GFX10-NEXT: v_readlane_b32 s8, v40, 4 -; GFX10-NEXT: v_readlane_b32 s7, v40, 3 -; GFX10-NEXT: v_readlane_b32 s6, v40, 2 +; GFX10-NEXT: v_readlane_b32 s31, v40, 3 +; GFX10-NEXT: v_readlane_b32 s30, v40, 2 ; GFX10-NEXT: v_readlane_b32 s5, v40, 1 ; GFX10-NEXT: v_readlane_b32 s4, v40, 0 -; GFX10-NEXT: v_readlane_b32 s34, v40, 8 +; GFX10-NEXT: v_readlane_b32 s34, v40, 4 ; GFX10-NEXT: s_or_saveexec_b32 s35, -1 ; GFX10-NEXT: buffer_load_dword v40, off, s[0:3], s33 ; 4-byte Folded Reload ; GFX10-NEXT: s_waitcnt_depctr 0xffe3 @@ -10480,33 +10380,25 @@ define amdgpu_gfx void @test_call_external_void_func_v3i64_inreg() #0 { ; GFX11-NEXT: s_or_saveexec_b32 s1, -1 ; GFX11-NEXT: scratch_store_b32 off, v40, s33 ; 4-byte Folded Spill ; GFX11-NEXT: s_mov_b32 exec_lo, s1 -; GFX11-NEXT: v_writelane_b32 v40, s0, 8 +; GFX11-NEXT: v_writelane_b32 v40, s0, 4 ; GFX11-NEXT: s_mov_b64 s[0:1], 0 -; GFX11-NEXT: s_add_i32 s32, s32, 16 +; GFX11-NEXT: s_mov_b32 s35, external_void_func_v3i64_inreg@abs32@hi +; GFX11-NEXT: s_load_b128 s[0:3], s[0:1], 0x0 +; GFX11-NEXT: s_mov_b32 s34, external_void_func_v3i64_inreg@abs32@lo ; GFX11-NEXT: v_writelane_b32 v40, s4, 0 +; GFX11-NEXT: s_mov_b32 s4, 1 +; GFX11-NEXT: s_add_i32 s32, s32, 16 ; GFX11-NEXT: v_writelane_b32 v40, s5, 1 -; GFX11-NEXT: v_writelane_b32 v40, s6, 2 -; GFX11-NEXT: v_writelane_b32 v40, s7, 3 -; GFX11-NEXT: s_load_b128 s[4:7], s[0:1], 0x0 -; GFX11-NEXT: s_mov_b32 s1, external_void_func_v3i64_inreg@abs32@hi -; GFX11-NEXT: s_mov_b32 s0, external_void_func_v3i64_inreg@abs32@lo -; GFX11-NEXT: v_writelane_b32 v40, s8, 4 -; GFX11-NEXT: s_mov_b32 s8, 1 -; GFX11-NEXT: v_writelane_b32 v40, s9, 5 -; GFX11-NEXT: s_mov_b32 s9, 2 -; GFX11-NEXT: v_writelane_b32 v40, s30, 6 -; GFX11-NEXT: v_writelane_b32 v40, s31, 7 -; GFX11-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX11-NEXT: s_mov_b32 s5, 2 +; GFX11-NEXT: v_writelane_b32 v40, s30, 2 +; GFX11-NEXT: v_writelane_b32 v40, s31, 3 +; GFX11-NEXT: s_swappc_b64 s[30:31], s[34:35] ; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_1) -; GFX11-NEXT: v_readlane_b32 s31, v40, 7 -; GFX11-NEXT: v_readlane_b32 s30, v40, 6 -; GFX11-NEXT: v_readlane_b32 s9, v40, 5 -; GFX11-NEXT: v_readlane_b32 s8, v40, 4 -; GFX11-NEXT: v_readlane_b32 s7, v40, 3 -; GFX11-NEXT: v_readlane_b32 s6, v40, 2 +; GFX11-NEXT: v_readlane_b32 s31, v40, 3 +; GFX11-NEXT: v_readlane_b32 s30, v40, 2 ; GFX11-NEXT: v_readlane_b32 s5, v40, 1 ; GFX11-NEXT: v_readlane_b32 s4, v40, 0 -; GFX11-NEXT: v_readlane_b32 s0, v40, 8 +; GFX11-NEXT: v_readlane_b32 s0, v40, 4 ; GFX11-NEXT: s_or_saveexec_b32 s1, -1 ; GFX11-NEXT: scratch_load_b32 v40, off, s33 ; 4-byte Folded Reload ; GFX11-NEXT: s_mov_b32 exec_lo, s1 @@ -10524,32 +10416,24 @@ define amdgpu_gfx void @test_call_external_void_func_v3i64_inreg() #0 { ; GFX10-SCRATCH-NEXT: scratch_store_dword off, v40, s33 ; 4-byte Folded Spill ; GFX10-SCRATCH-NEXT: s_waitcnt_depctr 0xffe3 ; GFX10-SCRATCH-NEXT: s_mov_b32 exec_lo, s1 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s0, 8 +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s0, 4 ; GFX10-SCRATCH-NEXT: s_mov_b64 s[0:1], 0 -; GFX10-SCRATCH-NEXT: s_add_i32 s32, s32, 16 +; GFX10-SCRATCH-NEXT: s_mov_b32 s35, external_void_func_v3i64_inreg@abs32@hi +; GFX10-SCRATCH-NEXT: s_load_dwordx4 s[0:3], s[0:1], 0x0 +; GFX10-SCRATCH-NEXT: s_mov_b32 s34, external_void_func_v3i64_inreg@abs32@lo ; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s4, 0 +; GFX10-SCRATCH-NEXT: s_mov_b32 s4, 1 +; GFX10-SCRATCH-NEXT: s_add_i32 s32, s32, 16 ; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s5, 1 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s6, 2 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s7, 3 -; GFX10-SCRATCH-NEXT: s_load_dwordx4 s[4:7], s[0:1], 0x0 -; GFX10-SCRATCH-NEXT: s_mov_b32 s1, external_void_func_v3i64_inreg@abs32@hi -; GFX10-SCRATCH-NEXT: s_mov_b32 s0, external_void_func_v3i64_inreg@abs32@lo -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s8, 4 -; GFX10-SCRATCH-NEXT: s_mov_b32 s8, 1 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s9, 5 -; GFX10-SCRATCH-NEXT: s_mov_b32 s9, 2 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s30, 6 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s31, 7 -; GFX10-SCRATCH-NEXT: s_swappc_b64 s[30:31], s[0:1] -; GFX10-SCRATCH-NEXT: v_readlane_b32 s31, v40, 7 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s30, v40, 6 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s9, v40, 5 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s8, v40, 4 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s7, v40, 3 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s6, v40, 2 +; GFX10-SCRATCH-NEXT: s_mov_b32 s5, 2 +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s30, 2 +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s31, 3 +; GFX10-SCRATCH-NEXT: s_swappc_b64 s[30:31], s[34:35] +; GFX10-SCRATCH-NEXT: v_readlane_b32 s31, v40, 3 +; GFX10-SCRATCH-NEXT: v_readlane_b32 s30, v40, 2 ; GFX10-SCRATCH-NEXT: v_readlane_b32 s5, v40, 1 ; GFX10-SCRATCH-NEXT: v_readlane_b32 s4, v40, 0 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s0, v40, 8 +; GFX10-SCRATCH-NEXT: v_readlane_b32 s0, v40, 4 ; GFX10-SCRATCH-NEXT: s_or_saveexec_b32 s1, -1 ; GFX10-SCRATCH-NEXT: scratch_load_dword v40, off, s33 ; 4-byte Folded Reload ; GFX10-SCRATCH-NEXT: s_waitcnt_depctr 0xffe3 @@ -10574,38 +10458,35 @@ define amdgpu_gfx void @test_call_external_void_func_v4i64_inreg() #0 { ; GFX9-NEXT: s_or_saveexec_b64 s[36:37], -1 ; GFX9-NEXT: buffer_store_dword v40, off, s[0:3], s33 ; 4-byte Folded Spill ; GFX9-NEXT: s_mov_b64 exec, s[36:37] -; GFX9-NEXT: v_writelane_b32 v40, s34, 10 +; GFX9-NEXT: v_writelane_b32 v40, s34, 6 +; GFX9-NEXT: s_mov_b64 s[34:35], 0 +; GFX9-NEXT: s_load_dwordx4 s[36:39], s[34:35], 0x0 ; GFX9-NEXT: v_writelane_b32 v40, s4, 0 ; GFX9-NEXT: v_writelane_b32 v40, s5, 1 ; GFX9-NEXT: v_writelane_b32 v40, s6, 2 ; GFX9-NEXT: v_writelane_b32 v40, s7, 3 -; GFX9-NEXT: s_mov_b64 s[34:35], 0 -; GFX9-NEXT: v_writelane_b32 v40, s8, 4 -; GFX9-NEXT: s_load_dwordx4 s[4:7], s[34:35], 0x0 -; GFX9-NEXT: v_writelane_b32 v40, s9, 5 -; GFX9-NEXT: v_writelane_b32 v40, s10, 6 -; GFX9-NEXT: v_writelane_b32 v40, s11, 7 -; GFX9-NEXT: v_writelane_b32 v40, s30, 8 +; GFX9-NEXT: v_writelane_b32 v40, s30, 4 ; GFX9-NEXT: s_mov_b32 s35, external_void_func_v4i64_inreg@abs32@hi ; GFX9-NEXT: s_mov_b32 s34, external_void_func_v4i64_inreg@abs32@lo -; GFX9-NEXT: s_mov_b32 s8, 1 -; GFX9-NEXT: s_mov_b32 s9, 2 -; GFX9-NEXT: s_mov_b32 s10, 3 -; GFX9-NEXT: s_mov_b32 s11, 4 -; GFX9-NEXT: s_addk_i32 s32, 0x400 -; GFX9-NEXT: v_writelane_b32 v40, s31, 9 -; GFX9-NEXT: s_swappc_b64 s[30:31], s[34:35] -; GFX9-NEXT: v_readlane_b32 s31, v40, 9 -; GFX9-NEXT: v_readlane_b32 s30, v40, 8 -; GFX9-NEXT: v_readlane_b32 s11, v40, 7 -; GFX9-NEXT: v_readlane_b32 s10, v40, 6 -; GFX9-NEXT: v_readlane_b32 s9, v40, 5 -; GFX9-NEXT: v_readlane_b32 s8, v40, 4 +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: s_mov_b32 s0, s36 +; GFX9-NEXT: s_mov_b32 s1, s37 +; GFX9-NEXT: s_mov_b32 s2, s38 +; GFX9-NEXT: s_mov_b32 s3, s39 +; GFX9-NEXT: s_mov_b32 s4, 1 +; GFX9-NEXT: s_mov_b32 s5, 2 +; GFX9-NEXT: s_mov_b32 s6, 3 +; GFX9-NEXT: s_mov_b32 s7, 4 +; GFX9-NEXT: s_addk_i32 s32, 0x400 +; GFX9-NEXT: v_writelane_b32 v40, s31, 5 +; GFX9-NEXT: s_swappc_b64 s[30:31], s[34:35] +; GFX9-NEXT: v_readlane_b32 s31, v40, 5 +; GFX9-NEXT: v_readlane_b32 s30, v40, 4 ; GFX9-NEXT: v_readlane_b32 s7, v40, 3 ; GFX9-NEXT: v_readlane_b32 s6, v40, 2 ; GFX9-NEXT: v_readlane_b32 s5, v40, 1 ; GFX9-NEXT: v_readlane_b32 s4, v40, 0 -; GFX9-NEXT: v_readlane_b32 s34, v40, 10 +; GFX9-NEXT: v_readlane_b32 s34, v40, 6 ; GFX9-NEXT: s_or_saveexec_b64 s[36:37], -1 ; GFX9-NEXT: buffer_load_dword v40, off, s[0:3], s33 ; 4-byte Folded Reload ; GFX9-NEXT: s_mov_b64 exec, s[36:37] @@ -10623,38 +10504,35 @@ define amdgpu_gfx void @test_call_external_void_func_v4i64_inreg() #0 { ; GFX10-NEXT: buffer_store_dword v40, off, s[0:3], s33 ; 4-byte Folded Spill ; GFX10-NEXT: s_waitcnt_depctr 0xffe3 ; GFX10-NEXT: s_mov_b32 exec_lo, s35 -; GFX10-NEXT: v_writelane_b32 v40, s34, 10 +; GFX10-NEXT: v_writelane_b32 v40, s34, 6 ; GFX10-NEXT: s_mov_b64 s[34:35], 0 ; GFX10-NEXT: s_addk_i32 s32, 0x200 +; GFX10-NEXT: s_load_dwordx4 s[36:39], s[34:35], 0x0 +; GFX10-NEXT: s_mov_b32 s35, external_void_func_v4i64_inreg@abs32@hi ; GFX10-NEXT: v_writelane_b32 v40, s4, 0 +; GFX10-NEXT: s_mov_b32 s34, external_void_func_v4i64_inreg@abs32@lo +; GFX10-NEXT: s_mov_b32 s4, 1 ; GFX10-NEXT: v_writelane_b32 v40, s5, 1 +; GFX10-NEXT: s_mov_b32 s5, 2 ; GFX10-NEXT: v_writelane_b32 v40, s6, 2 +; GFX10-NEXT: s_mov_b32 s6, 3 ; GFX10-NEXT: v_writelane_b32 v40, s7, 3 -; GFX10-NEXT: s_load_dwordx4 s[4:7], s[34:35], 0x0 -; GFX10-NEXT: s_mov_b32 s35, external_void_func_v4i64_inreg@abs32@hi -; GFX10-NEXT: s_mov_b32 s34, external_void_func_v4i64_inreg@abs32@lo -; GFX10-NEXT: v_writelane_b32 v40, s8, 4 -; GFX10-NEXT: s_mov_b32 s8, 1 -; GFX10-NEXT: v_writelane_b32 v40, s9, 5 -; GFX10-NEXT: s_mov_b32 s9, 2 -; GFX10-NEXT: v_writelane_b32 v40, s10, 6 -; GFX10-NEXT: s_mov_b32 s10, 3 -; GFX10-NEXT: v_writelane_b32 v40, s11, 7 -; GFX10-NEXT: s_mov_b32 s11, 4 -; GFX10-NEXT: v_writelane_b32 v40, s30, 8 -; GFX10-NEXT: v_writelane_b32 v40, s31, 9 +; GFX10-NEXT: s_mov_b32 s7, 4 +; GFX10-NEXT: s_waitcnt lgkmcnt(0) +; GFX10-NEXT: s_mov_b32 s0, s36 +; GFX10-NEXT: s_mov_b32 s1, s37 +; GFX10-NEXT: v_writelane_b32 v40, s30, 4 +; GFX10-NEXT: s_mov_b32 s2, s38 +; GFX10-NEXT: s_mov_b32 s3, s39 +; GFX10-NEXT: v_writelane_b32 v40, s31, 5 ; GFX10-NEXT: s_swappc_b64 s[30:31], s[34:35] -; GFX10-NEXT: v_readlane_b32 s31, v40, 9 -; GFX10-NEXT: v_readlane_b32 s30, v40, 8 -; GFX10-NEXT: v_readlane_b32 s11, v40, 7 -; GFX10-NEXT: v_readlane_b32 s10, v40, 6 -; GFX10-NEXT: v_readlane_b32 s9, v40, 5 -; GFX10-NEXT: v_readlane_b32 s8, v40, 4 +; GFX10-NEXT: v_readlane_b32 s31, v40, 5 +; GFX10-NEXT: v_readlane_b32 s30, v40, 4 ; GFX10-NEXT: v_readlane_b32 s7, v40, 3 ; GFX10-NEXT: v_readlane_b32 s6, v40, 2 ; GFX10-NEXT: v_readlane_b32 s5, v40, 1 ; GFX10-NEXT: v_readlane_b32 s4, v40, 0 -; GFX10-NEXT: v_readlane_b32 s34, v40, 10 +; GFX10-NEXT: v_readlane_b32 s34, v40, 6 ; GFX10-NEXT: s_or_saveexec_b32 s35, -1 ; GFX10-NEXT: buffer_load_dword v40, off, s[0:3], s33 ; 4-byte Folded Reload ; GFX10-NEXT: s_waitcnt_depctr 0xffe3 @@ -10672,39 +10550,31 @@ define amdgpu_gfx void @test_call_external_void_func_v4i64_inreg() #0 { ; GFX11-NEXT: s_or_saveexec_b32 s1, -1 ; GFX11-NEXT: scratch_store_b32 off, v40, s33 ; 4-byte Folded Spill ; GFX11-NEXT: s_mov_b32 exec_lo, s1 -; GFX11-NEXT: v_writelane_b32 v40, s0, 10 +; GFX11-NEXT: v_writelane_b32 v40, s0, 6 ; GFX11-NEXT: s_mov_b64 s[0:1], 0 -; GFX11-NEXT: s_add_i32 s32, s32, 16 +; GFX11-NEXT: s_mov_b32 s35, external_void_func_v4i64_inreg@abs32@hi +; GFX11-NEXT: s_load_b128 s[0:3], s[0:1], 0x0 +; GFX11-NEXT: s_mov_b32 s34, external_void_func_v4i64_inreg@abs32@lo ; GFX11-NEXT: v_writelane_b32 v40, s4, 0 +; GFX11-NEXT: s_mov_b32 s4, 1 +; GFX11-NEXT: s_add_i32 s32, s32, 16 ; GFX11-NEXT: v_writelane_b32 v40, s5, 1 +; GFX11-NEXT: s_mov_b32 s5, 2 ; GFX11-NEXT: v_writelane_b32 v40, s6, 2 +; GFX11-NEXT: s_mov_b32 s6, 3 ; GFX11-NEXT: v_writelane_b32 v40, s7, 3 -; GFX11-NEXT: s_load_b128 s[4:7], s[0:1], 0x0 -; GFX11-NEXT: s_mov_b32 s1, external_void_func_v4i64_inreg@abs32@hi -; GFX11-NEXT: s_mov_b32 s0, external_void_func_v4i64_inreg@abs32@lo -; GFX11-NEXT: v_writelane_b32 v40, s8, 4 -; GFX11-NEXT: s_mov_b32 s8, 1 -; GFX11-NEXT: v_writelane_b32 v40, s9, 5 -; GFX11-NEXT: s_mov_b32 s9, 2 -; GFX11-NEXT: v_writelane_b32 v40, s10, 6 -; GFX11-NEXT: s_mov_b32 s10, 3 -; GFX11-NEXT: v_writelane_b32 v40, s11, 7 -; GFX11-NEXT: s_mov_b32 s11, 4 -; GFX11-NEXT: v_writelane_b32 v40, s30, 8 -; GFX11-NEXT: v_writelane_b32 v40, s31, 9 -; GFX11-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX11-NEXT: s_mov_b32 s7, 4 +; GFX11-NEXT: v_writelane_b32 v40, s30, 4 +; GFX11-NEXT: v_writelane_b32 v40, s31, 5 +; GFX11-NEXT: s_swappc_b64 s[30:31], s[34:35] ; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_1) -; GFX11-NEXT: v_readlane_b32 s31, v40, 9 -; GFX11-NEXT: v_readlane_b32 s30, v40, 8 -; GFX11-NEXT: v_readlane_b32 s11, v40, 7 -; GFX11-NEXT: v_readlane_b32 s10, v40, 6 -; GFX11-NEXT: v_readlane_b32 s9, v40, 5 -; GFX11-NEXT: v_readlane_b32 s8, v40, 4 +; GFX11-NEXT: v_readlane_b32 s31, v40, 5 +; GFX11-NEXT: v_readlane_b32 s30, v40, 4 ; GFX11-NEXT: v_readlane_b32 s7, v40, 3 ; GFX11-NEXT: v_readlane_b32 s6, v40, 2 ; GFX11-NEXT: v_readlane_b32 s5, v40, 1 ; GFX11-NEXT: v_readlane_b32 s4, v40, 0 -; GFX11-NEXT: v_readlane_b32 s0, v40, 10 +; GFX11-NEXT: v_readlane_b32 s0, v40, 6 ; GFX11-NEXT: s_or_saveexec_b32 s1, -1 ; GFX11-NEXT: scratch_load_b32 v40, off, s33 ; 4-byte Folded Reload ; GFX11-NEXT: s_mov_b32 exec_lo, s1 @@ -10722,38 +10592,30 @@ define amdgpu_gfx void @test_call_external_void_func_v4i64_inreg() #0 { ; GFX10-SCRATCH-NEXT: scratch_store_dword off, v40, s33 ; 4-byte Folded Spill ; GFX10-SCRATCH-NEXT: s_waitcnt_depctr 0xffe3 ; GFX10-SCRATCH-NEXT: s_mov_b32 exec_lo, s1 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s0, 10 +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s0, 6 ; GFX10-SCRATCH-NEXT: s_mov_b64 s[0:1], 0 -; GFX10-SCRATCH-NEXT: s_add_i32 s32, s32, 16 +; GFX10-SCRATCH-NEXT: s_mov_b32 s35, external_void_func_v4i64_inreg@abs32@hi +; GFX10-SCRATCH-NEXT: s_load_dwordx4 s[0:3], s[0:1], 0x0 +; GFX10-SCRATCH-NEXT: s_mov_b32 s34, external_void_func_v4i64_inreg@abs32@lo ; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s4, 0 +; GFX10-SCRATCH-NEXT: s_mov_b32 s4, 1 +; GFX10-SCRATCH-NEXT: s_add_i32 s32, s32, 16 ; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s5, 1 +; GFX10-SCRATCH-NEXT: s_mov_b32 s5, 2 ; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s6, 2 +; GFX10-SCRATCH-NEXT: s_mov_b32 s6, 3 ; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s7, 3 -; GFX10-SCRATCH-NEXT: s_load_dwordx4 s[4:7], s[0:1], 0x0 -; GFX10-SCRATCH-NEXT: s_mov_b32 s1, external_void_func_v4i64_inreg@abs32@hi -; GFX10-SCRATCH-NEXT: s_mov_b32 s0, external_void_func_v4i64_inreg@abs32@lo -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s8, 4 -; GFX10-SCRATCH-NEXT: s_mov_b32 s8, 1 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s9, 5 -; GFX10-SCRATCH-NEXT: s_mov_b32 s9, 2 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s10, 6 -; GFX10-SCRATCH-NEXT: s_mov_b32 s10, 3 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s11, 7 -; GFX10-SCRATCH-NEXT: s_mov_b32 s11, 4 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s30, 8 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s31, 9 -; GFX10-SCRATCH-NEXT: s_swappc_b64 s[30:31], s[0:1] -; GFX10-SCRATCH-NEXT: v_readlane_b32 s31, v40, 9 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s30, v40, 8 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s11, v40, 7 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s10, v40, 6 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s9, v40, 5 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s8, v40, 4 +; GFX10-SCRATCH-NEXT: s_mov_b32 s7, 4 +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s30, 4 +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s31, 5 +; GFX10-SCRATCH-NEXT: s_swappc_b64 s[30:31], s[34:35] +; GFX10-SCRATCH-NEXT: v_readlane_b32 s31, v40, 5 +; GFX10-SCRATCH-NEXT: v_readlane_b32 s30, v40, 4 ; GFX10-SCRATCH-NEXT: v_readlane_b32 s7, v40, 3 ; GFX10-SCRATCH-NEXT: v_readlane_b32 s6, v40, 2 ; GFX10-SCRATCH-NEXT: v_readlane_b32 s5, v40, 1 ; GFX10-SCRATCH-NEXT: v_readlane_b32 s4, v40, 0 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s0, v40, 10 +; GFX10-SCRATCH-NEXT: v_readlane_b32 s0, v40, 6 ; GFX10-SCRATCH-NEXT: s_or_saveexec_b32 s1, -1 ; GFX10-SCRATCH-NEXT: scratch_load_dword v40, off, s33 ; 4-byte Folded Reload ; GFX10-SCRATCH-NEXT: s_waitcnt_depctr 0xffe3 @@ -10777,19 +10639,17 @@ define amdgpu_gfx void @test_call_external_void_func_f16_imm_inreg() #0 { ; GFX9-NEXT: s_or_saveexec_b64 s[36:37], -1 ; GFX9-NEXT: buffer_store_dword v40, off, s[0:3], s33 ; 4-byte Folded Spill ; GFX9-NEXT: s_mov_b64 exec, s[36:37] -; GFX9-NEXT: v_writelane_b32 v40, s34, 3 -; GFX9-NEXT: v_writelane_b32 v40, s4, 0 -; GFX9-NEXT: v_writelane_b32 v40, s30, 1 +; GFX9-NEXT: v_writelane_b32 v40, s34, 2 +; GFX9-NEXT: v_writelane_b32 v40, s30, 0 ; GFX9-NEXT: s_mov_b32 s35, external_void_func_f16_inreg@abs32@hi ; GFX9-NEXT: s_mov_b32 s34, external_void_func_f16_inreg@abs32@lo -; GFX9-NEXT: s_movk_i32 s4, 0x4400 +; GFX9-NEXT: s_movk_i32 s0, 0x4400 ; GFX9-NEXT: s_addk_i32 s32, 0x400 -; GFX9-NEXT: v_writelane_b32 v40, s31, 2 +; GFX9-NEXT: v_writelane_b32 v40, s31, 1 ; GFX9-NEXT: s_swappc_b64 s[30:31], s[34:35] -; GFX9-NEXT: v_readlane_b32 s31, v40, 2 -; GFX9-NEXT: v_readlane_b32 s30, v40, 1 -; GFX9-NEXT: v_readlane_b32 s4, v40, 0 -; GFX9-NEXT: v_readlane_b32 s34, v40, 3 +; GFX9-NEXT: v_readlane_b32 s31, v40, 1 +; GFX9-NEXT: v_readlane_b32 s30, v40, 0 +; GFX9-NEXT: v_readlane_b32 s34, v40, 2 ; GFX9-NEXT: s_or_saveexec_b64 s[36:37], -1 ; GFX9-NEXT: buffer_load_dword v40, off, s[0:3], s33 ; 4-byte Folded Reload ; GFX9-NEXT: s_mov_b64 exec, s[36:37] @@ -10807,19 +10667,17 @@ define amdgpu_gfx void @test_call_external_void_func_f16_imm_inreg() #0 { ; GFX10-NEXT: buffer_store_dword v40, off, s[0:3], s33 ; 4-byte Folded Spill ; GFX10-NEXT: s_waitcnt_depctr 0xffe3 ; GFX10-NEXT: s_mov_b32 exec_lo, s35 -; GFX10-NEXT: v_writelane_b32 v40, s34, 3 +; GFX10-NEXT: v_writelane_b32 v40, s34, 2 ; GFX10-NEXT: s_mov_b32 s35, external_void_func_f16_inreg@abs32@hi ; GFX10-NEXT: s_mov_b32 s34, external_void_func_f16_inreg@abs32@lo +; GFX10-NEXT: s_movk_i32 s0, 0x4400 ; GFX10-NEXT: s_addk_i32 s32, 0x200 -; GFX10-NEXT: v_writelane_b32 v40, s4, 0 -; GFX10-NEXT: s_movk_i32 s4, 0x4400 -; GFX10-NEXT: v_writelane_b32 v40, s30, 1 -; GFX10-NEXT: v_writelane_b32 v40, s31, 2 +; GFX10-NEXT: v_writelane_b32 v40, s30, 0 +; GFX10-NEXT: v_writelane_b32 v40, s31, 1 ; GFX10-NEXT: s_swappc_b64 s[30:31], s[34:35] -; GFX10-NEXT: v_readlane_b32 s31, v40, 2 -; GFX10-NEXT: v_readlane_b32 s30, v40, 1 -; GFX10-NEXT: v_readlane_b32 s4, v40, 0 -; GFX10-NEXT: v_readlane_b32 s34, v40, 3 +; GFX10-NEXT: v_readlane_b32 s31, v40, 1 +; GFX10-NEXT: v_readlane_b32 s30, v40, 0 +; GFX10-NEXT: v_readlane_b32 s34, v40, 2 ; GFX10-NEXT: s_or_saveexec_b32 s35, -1 ; GFX10-NEXT: buffer_load_dword v40, off, s[0:3], s33 ; 4-byte Folded Reload ; GFX10-NEXT: s_waitcnt_depctr 0xffe3 @@ -10837,20 +10695,18 @@ define amdgpu_gfx void @test_call_external_void_func_f16_imm_inreg() #0 { ; GFX11-NEXT: s_or_saveexec_b32 s1, -1 ; GFX11-NEXT: scratch_store_b32 off, v40, s33 ; 4-byte Folded Spill ; GFX11-NEXT: s_mov_b32 exec_lo, s1 -; GFX11-NEXT: v_writelane_b32 v40, s0, 3 -; GFX11-NEXT: s_mov_b32 s1, external_void_func_f16_inreg@abs32@hi -; GFX11-NEXT: s_mov_b32 s0, external_void_func_f16_inreg@abs32@lo +; GFX11-NEXT: v_writelane_b32 v40, s0, 2 +; GFX11-NEXT: s_mov_b32 s3, external_void_func_f16_inreg@abs32@hi +; GFX11-NEXT: s_mov_b32 s2, external_void_func_f16_inreg@abs32@lo +; GFX11-NEXT: s_movk_i32 s0, 0x4400 ; GFX11-NEXT: s_add_i32 s32, s32, 16 -; GFX11-NEXT: v_writelane_b32 v40, s4, 0 -; GFX11-NEXT: s_movk_i32 s4, 0x4400 -; GFX11-NEXT: v_writelane_b32 v40, s30, 1 -; GFX11-NEXT: v_writelane_b32 v40, s31, 2 -; GFX11-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX11-NEXT: v_writelane_b32 v40, s30, 0 +; GFX11-NEXT: v_writelane_b32 v40, s31, 1 +; GFX11-NEXT: s_swappc_b64 s[30:31], s[2:3] ; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_1) -; GFX11-NEXT: v_readlane_b32 s31, v40, 2 -; GFX11-NEXT: v_readlane_b32 s30, v40, 1 -; GFX11-NEXT: v_readlane_b32 s4, v40, 0 -; GFX11-NEXT: v_readlane_b32 s0, v40, 3 +; GFX11-NEXT: v_readlane_b32 s31, v40, 1 +; GFX11-NEXT: v_readlane_b32 s30, v40, 0 +; GFX11-NEXT: v_readlane_b32 s0, v40, 2 ; GFX11-NEXT: s_or_saveexec_b32 s1, -1 ; GFX11-NEXT: scratch_load_b32 v40, off, s33 ; 4-byte Folded Reload ; GFX11-NEXT: s_mov_b32 exec_lo, s1 @@ -10868,19 +10724,17 @@ define amdgpu_gfx void @test_call_external_void_func_f16_imm_inreg() #0 { ; GFX10-SCRATCH-NEXT: scratch_store_dword off, v40, s33 ; 4-byte Folded Spill ; GFX10-SCRATCH-NEXT: s_waitcnt_depctr 0xffe3 ; GFX10-SCRATCH-NEXT: s_mov_b32 exec_lo, s1 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s0, 3 -; GFX10-SCRATCH-NEXT: s_mov_b32 s1, external_void_func_f16_inreg@abs32@hi -; GFX10-SCRATCH-NEXT: s_mov_b32 s0, external_void_func_f16_inreg@abs32@lo +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s0, 2 +; GFX10-SCRATCH-NEXT: s_mov_b32 s3, external_void_func_f16_inreg@abs32@hi +; GFX10-SCRATCH-NEXT: s_mov_b32 s2, external_void_func_f16_inreg@abs32@lo +; GFX10-SCRATCH-NEXT: s_movk_i32 s0, 0x4400 ; GFX10-SCRATCH-NEXT: s_add_i32 s32, s32, 16 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s4, 0 -; GFX10-SCRATCH-NEXT: s_movk_i32 s4, 0x4400 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s30, 1 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s31, 2 -; GFX10-SCRATCH-NEXT: s_swappc_b64 s[30:31], s[0:1] -; GFX10-SCRATCH-NEXT: v_readlane_b32 s31, v40, 2 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s30, v40, 1 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s4, v40, 0 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s0, v40, 3 +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s30, 0 +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s31, 1 +; GFX10-SCRATCH-NEXT: s_swappc_b64 s[30:31], s[2:3] +; GFX10-SCRATCH-NEXT: v_readlane_b32 s31, v40, 1 +; GFX10-SCRATCH-NEXT: v_readlane_b32 s30, v40, 0 +; GFX10-SCRATCH-NEXT: v_readlane_b32 s0, v40, 2 ; GFX10-SCRATCH-NEXT: s_or_saveexec_b32 s1, -1 ; GFX10-SCRATCH-NEXT: scratch_load_dword v40, off, s33 ; 4-byte Folded Reload ; GFX10-SCRATCH-NEXT: s_waitcnt_depctr 0xffe3 @@ -10902,19 +10756,17 @@ define amdgpu_gfx void @test_call_external_void_func_f32_imm_inreg() #0 { ; GFX9-NEXT: s_or_saveexec_b64 s[36:37], -1 ; GFX9-NEXT: buffer_store_dword v40, off, s[0:3], s33 ; 4-byte Folded Spill ; GFX9-NEXT: s_mov_b64 exec, s[36:37] -; GFX9-NEXT: v_writelane_b32 v40, s34, 3 -; GFX9-NEXT: v_writelane_b32 v40, s4, 0 -; GFX9-NEXT: v_writelane_b32 v40, s30, 1 +; GFX9-NEXT: v_writelane_b32 v40, s34, 2 +; GFX9-NEXT: v_writelane_b32 v40, s30, 0 ; GFX9-NEXT: s_mov_b32 s35, external_void_func_f32_inreg@abs32@hi ; GFX9-NEXT: s_mov_b32 s34, external_void_func_f32_inreg@abs32@lo -; GFX9-NEXT: s_mov_b32 s4, 4.0 +; GFX9-NEXT: s_mov_b32 s0, 4.0 ; GFX9-NEXT: s_addk_i32 s32, 0x400 -; GFX9-NEXT: v_writelane_b32 v40, s31, 2 +; GFX9-NEXT: v_writelane_b32 v40, s31, 1 ; GFX9-NEXT: s_swappc_b64 s[30:31], s[34:35] -; GFX9-NEXT: v_readlane_b32 s31, v40, 2 -; GFX9-NEXT: v_readlane_b32 s30, v40, 1 -; GFX9-NEXT: v_readlane_b32 s4, v40, 0 -; GFX9-NEXT: v_readlane_b32 s34, v40, 3 +; GFX9-NEXT: v_readlane_b32 s31, v40, 1 +; GFX9-NEXT: v_readlane_b32 s30, v40, 0 +; GFX9-NEXT: v_readlane_b32 s34, v40, 2 ; GFX9-NEXT: s_or_saveexec_b64 s[36:37], -1 ; GFX9-NEXT: buffer_load_dword v40, off, s[0:3], s33 ; 4-byte Folded Reload ; GFX9-NEXT: s_mov_b64 exec, s[36:37] @@ -10932,19 +10784,17 @@ define amdgpu_gfx void @test_call_external_void_func_f32_imm_inreg() #0 { ; GFX10-NEXT: buffer_store_dword v40, off, s[0:3], s33 ; 4-byte Folded Spill ; GFX10-NEXT: s_waitcnt_depctr 0xffe3 ; GFX10-NEXT: s_mov_b32 exec_lo, s35 -; GFX10-NEXT: v_writelane_b32 v40, s34, 3 +; GFX10-NEXT: v_writelane_b32 v40, s34, 2 ; GFX10-NEXT: s_mov_b32 s35, external_void_func_f32_inreg@abs32@hi ; GFX10-NEXT: s_mov_b32 s34, external_void_func_f32_inreg@abs32@lo +; GFX10-NEXT: s_mov_b32 s0, 4.0 ; GFX10-NEXT: s_addk_i32 s32, 0x200 -; GFX10-NEXT: v_writelane_b32 v40, s4, 0 -; GFX10-NEXT: s_mov_b32 s4, 4.0 -; GFX10-NEXT: v_writelane_b32 v40, s30, 1 -; GFX10-NEXT: v_writelane_b32 v40, s31, 2 +; GFX10-NEXT: v_writelane_b32 v40, s30, 0 +; GFX10-NEXT: v_writelane_b32 v40, s31, 1 ; GFX10-NEXT: s_swappc_b64 s[30:31], s[34:35] -; GFX10-NEXT: v_readlane_b32 s31, v40, 2 -; GFX10-NEXT: v_readlane_b32 s30, v40, 1 -; GFX10-NEXT: v_readlane_b32 s4, v40, 0 -; GFX10-NEXT: v_readlane_b32 s34, v40, 3 +; GFX10-NEXT: v_readlane_b32 s31, v40, 1 +; GFX10-NEXT: v_readlane_b32 s30, v40, 0 +; GFX10-NEXT: v_readlane_b32 s34, v40, 2 ; GFX10-NEXT: s_or_saveexec_b32 s35, -1 ; GFX10-NEXT: buffer_load_dword v40, off, s[0:3], s33 ; 4-byte Folded Reload ; GFX10-NEXT: s_waitcnt_depctr 0xffe3 @@ -10962,20 +10812,18 @@ define amdgpu_gfx void @test_call_external_void_func_f32_imm_inreg() #0 { ; GFX11-NEXT: s_or_saveexec_b32 s1, -1 ; GFX11-NEXT: scratch_store_b32 off, v40, s33 ; 4-byte Folded Spill ; GFX11-NEXT: s_mov_b32 exec_lo, s1 -; GFX11-NEXT: v_writelane_b32 v40, s0, 3 -; GFX11-NEXT: s_mov_b32 s1, external_void_func_f32_inreg@abs32@hi -; GFX11-NEXT: s_mov_b32 s0, external_void_func_f32_inreg@abs32@lo +; GFX11-NEXT: v_writelane_b32 v40, s0, 2 +; GFX11-NEXT: s_mov_b32 s3, external_void_func_f32_inreg@abs32@hi +; GFX11-NEXT: s_mov_b32 s2, external_void_func_f32_inreg@abs32@lo +; GFX11-NEXT: s_mov_b32 s0, 4.0 ; GFX11-NEXT: s_add_i32 s32, s32, 16 -; GFX11-NEXT: v_writelane_b32 v40, s4, 0 -; GFX11-NEXT: s_mov_b32 s4, 4.0 -; GFX11-NEXT: v_writelane_b32 v40, s30, 1 -; GFX11-NEXT: v_writelane_b32 v40, s31, 2 -; GFX11-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX11-NEXT: v_writelane_b32 v40, s30, 0 +; GFX11-NEXT: v_writelane_b32 v40, s31, 1 +; GFX11-NEXT: s_swappc_b64 s[30:31], s[2:3] ; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_1) -; GFX11-NEXT: v_readlane_b32 s31, v40, 2 -; GFX11-NEXT: v_readlane_b32 s30, v40, 1 -; GFX11-NEXT: v_readlane_b32 s4, v40, 0 -; GFX11-NEXT: v_readlane_b32 s0, v40, 3 +; GFX11-NEXT: v_readlane_b32 s31, v40, 1 +; GFX11-NEXT: v_readlane_b32 s30, v40, 0 +; GFX11-NEXT: v_readlane_b32 s0, v40, 2 ; GFX11-NEXT: s_or_saveexec_b32 s1, -1 ; GFX11-NEXT: scratch_load_b32 v40, off, s33 ; 4-byte Folded Reload ; GFX11-NEXT: s_mov_b32 exec_lo, s1 @@ -10993,19 +10841,17 @@ define amdgpu_gfx void @test_call_external_void_func_f32_imm_inreg() #0 { ; GFX10-SCRATCH-NEXT: scratch_store_dword off, v40, s33 ; 4-byte Folded Spill ; GFX10-SCRATCH-NEXT: s_waitcnt_depctr 0xffe3 ; GFX10-SCRATCH-NEXT: s_mov_b32 exec_lo, s1 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s0, 3 -; GFX10-SCRATCH-NEXT: s_mov_b32 s1, external_void_func_f32_inreg@abs32@hi -; GFX10-SCRATCH-NEXT: s_mov_b32 s0, external_void_func_f32_inreg@abs32@lo +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s0, 2 +; GFX10-SCRATCH-NEXT: s_mov_b32 s3, external_void_func_f32_inreg@abs32@hi +; GFX10-SCRATCH-NEXT: s_mov_b32 s2, external_void_func_f32_inreg@abs32@lo +; GFX10-SCRATCH-NEXT: s_mov_b32 s0, 4.0 ; GFX10-SCRATCH-NEXT: s_add_i32 s32, s32, 16 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s4, 0 -; GFX10-SCRATCH-NEXT: s_mov_b32 s4, 4.0 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s30, 1 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s31, 2 -; GFX10-SCRATCH-NEXT: s_swappc_b64 s[30:31], s[0:1] -; GFX10-SCRATCH-NEXT: v_readlane_b32 s31, v40, 2 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s30, v40, 1 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s4, v40, 0 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s0, v40, 3 +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s30, 0 +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s31, 1 +; GFX10-SCRATCH-NEXT: s_swappc_b64 s[30:31], s[2:3] +; GFX10-SCRATCH-NEXT: v_readlane_b32 s31, v40, 1 +; GFX10-SCRATCH-NEXT: v_readlane_b32 s30, v40, 0 +; GFX10-SCRATCH-NEXT: v_readlane_b32 s0, v40, 2 ; GFX10-SCRATCH-NEXT: s_or_saveexec_b32 s1, -1 ; GFX10-SCRATCH-NEXT: scratch_load_dword v40, off, s33 ; 4-byte Folded Reload ; GFX10-SCRATCH-NEXT: s_waitcnt_depctr 0xffe3 @@ -11027,22 +10873,18 @@ define amdgpu_gfx void @test_call_external_void_func_v2f32_imm_inreg() #0 { ; GFX9-NEXT: s_or_saveexec_b64 s[36:37], -1 ; GFX9-NEXT: buffer_store_dword v40, off, s[0:3], s33 ; 4-byte Folded Spill ; GFX9-NEXT: s_mov_b64 exec, s[36:37] -; GFX9-NEXT: v_writelane_b32 v40, s34, 4 -; GFX9-NEXT: v_writelane_b32 v40, s4, 0 -; GFX9-NEXT: v_writelane_b32 v40, s5, 1 -; GFX9-NEXT: v_writelane_b32 v40, s30, 2 +; GFX9-NEXT: v_writelane_b32 v40, s34, 2 +; GFX9-NEXT: v_writelane_b32 v40, s30, 0 ; GFX9-NEXT: s_mov_b32 s35, external_void_func_v2f32_inreg@abs32@hi ; GFX9-NEXT: s_mov_b32 s34, external_void_func_v2f32_inreg@abs32@lo -; GFX9-NEXT: s_mov_b32 s4, 1.0 -; GFX9-NEXT: s_mov_b32 s5, 2.0 +; GFX9-NEXT: s_mov_b32 s0, 1.0 +; GFX9-NEXT: s_mov_b32 s1, 2.0 ; GFX9-NEXT: s_addk_i32 s32, 0x400 -; GFX9-NEXT: v_writelane_b32 v40, s31, 3 +; GFX9-NEXT: v_writelane_b32 v40, s31, 1 ; GFX9-NEXT: s_swappc_b64 s[30:31], s[34:35] -; GFX9-NEXT: v_readlane_b32 s31, v40, 3 -; GFX9-NEXT: v_readlane_b32 s30, v40, 2 -; GFX9-NEXT: v_readlane_b32 s5, v40, 1 -; GFX9-NEXT: v_readlane_b32 s4, v40, 0 -; GFX9-NEXT: v_readlane_b32 s34, v40, 4 +; GFX9-NEXT: v_readlane_b32 s31, v40, 1 +; GFX9-NEXT: v_readlane_b32 s30, v40, 0 +; GFX9-NEXT: v_readlane_b32 s34, v40, 2 ; GFX9-NEXT: s_or_saveexec_b64 s[36:37], -1 ; GFX9-NEXT: buffer_load_dword v40, off, s[0:3], s33 ; 4-byte Folded Reload ; GFX9-NEXT: s_mov_b64 exec, s[36:37] @@ -11060,22 +10902,18 @@ define amdgpu_gfx void @test_call_external_void_func_v2f32_imm_inreg() #0 { ; GFX10-NEXT: buffer_store_dword v40, off, s[0:3], s33 ; 4-byte Folded Spill ; GFX10-NEXT: s_waitcnt_depctr 0xffe3 ; GFX10-NEXT: s_mov_b32 exec_lo, s35 -; GFX10-NEXT: v_writelane_b32 v40, s34, 4 +; GFX10-NEXT: v_writelane_b32 v40, s34, 2 ; GFX10-NEXT: s_mov_b32 s35, external_void_func_v2f32_inreg@abs32@hi ; GFX10-NEXT: s_mov_b32 s34, external_void_func_v2f32_inreg@abs32@lo +; GFX10-NEXT: s_mov_b32 s0, 1.0 +; GFX10-NEXT: s_mov_b32 s1, 2.0 +; GFX10-NEXT: v_writelane_b32 v40, s30, 0 ; GFX10-NEXT: s_addk_i32 s32, 0x200 -; GFX10-NEXT: v_writelane_b32 v40, s4, 0 -; GFX10-NEXT: s_mov_b32 s4, 1.0 -; GFX10-NEXT: v_writelane_b32 v40, s5, 1 -; GFX10-NEXT: s_mov_b32 s5, 2.0 -; GFX10-NEXT: v_writelane_b32 v40, s30, 2 -; GFX10-NEXT: v_writelane_b32 v40, s31, 3 +; GFX10-NEXT: v_writelane_b32 v40, s31, 1 ; GFX10-NEXT: s_swappc_b64 s[30:31], s[34:35] -; GFX10-NEXT: v_readlane_b32 s31, v40, 3 -; GFX10-NEXT: v_readlane_b32 s30, v40, 2 -; GFX10-NEXT: v_readlane_b32 s5, v40, 1 -; GFX10-NEXT: v_readlane_b32 s4, v40, 0 -; GFX10-NEXT: v_readlane_b32 s34, v40, 4 +; GFX10-NEXT: v_readlane_b32 s31, v40, 1 +; GFX10-NEXT: v_readlane_b32 s30, v40, 0 +; GFX10-NEXT: v_readlane_b32 s34, v40, 2 ; GFX10-NEXT: s_or_saveexec_b32 s35, -1 ; GFX10-NEXT: buffer_load_dword v40, off, s[0:3], s33 ; 4-byte Folded Reload ; GFX10-NEXT: s_waitcnt_depctr 0xffe3 @@ -11093,23 +10931,19 @@ define amdgpu_gfx void @test_call_external_void_func_v2f32_imm_inreg() #0 { ; GFX11-NEXT: s_or_saveexec_b32 s1, -1 ; GFX11-NEXT: scratch_store_b32 off, v40, s33 ; 4-byte Folded Spill ; GFX11-NEXT: s_mov_b32 exec_lo, s1 -; GFX11-NEXT: v_writelane_b32 v40, s0, 4 -; GFX11-NEXT: s_mov_b32 s1, external_void_func_v2f32_inreg@abs32@hi -; GFX11-NEXT: s_mov_b32 s0, external_void_func_v2f32_inreg@abs32@lo +; GFX11-NEXT: v_writelane_b32 v40, s0, 2 +; GFX11-NEXT: s_mov_b32 s3, external_void_func_v2f32_inreg@abs32@hi +; GFX11-NEXT: s_mov_b32 s2, external_void_func_v2f32_inreg@abs32@lo +; GFX11-NEXT: s_mov_b32 s0, 1.0 +; GFX11-NEXT: s_mov_b32 s1, 2.0 +; GFX11-NEXT: v_writelane_b32 v40, s30, 0 ; GFX11-NEXT: s_add_i32 s32, s32, 16 -; GFX11-NEXT: v_writelane_b32 v40, s4, 0 -; GFX11-NEXT: s_mov_b32 s4, 1.0 -; GFX11-NEXT: v_writelane_b32 v40, s5, 1 -; GFX11-NEXT: s_mov_b32 s5, 2.0 -; GFX11-NEXT: v_writelane_b32 v40, s30, 2 -; GFX11-NEXT: v_writelane_b32 v40, s31, 3 -; GFX11-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX11-NEXT: v_writelane_b32 v40, s31, 1 +; GFX11-NEXT: s_swappc_b64 s[30:31], s[2:3] ; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_1) -; GFX11-NEXT: v_readlane_b32 s31, v40, 3 -; GFX11-NEXT: v_readlane_b32 s30, v40, 2 -; GFX11-NEXT: v_readlane_b32 s5, v40, 1 -; GFX11-NEXT: v_readlane_b32 s4, v40, 0 -; GFX11-NEXT: v_readlane_b32 s0, v40, 4 +; GFX11-NEXT: v_readlane_b32 s31, v40, 1 +; GFX11-NEXT: v_readlane_b32 s30, v40, 0 +; GFX11-NEXT: v_readlane_b32 s0, v40, 2 ; GFX11-NEXT: s_or_saveexec_b32 s1, -1 ; GFX11-NEXT: scratch_load_b32 v40, off, s33 ; 4-byte Folded Reload ; GFX11-NEXT: s_mov_b32 exec_lo, s1 @@ -11127,22 +10961,18 @@ define amdgpu_gfx void @test_call_external_void_func_v2f32_imm_inreg() #0 { ; GFX10-SCRATCH-NEXT: scratch_store_dword off, v40, s33 ; 4-byte Folded Spill ; GFX10-SCRATCH-NEXT: s_waitcnt_depctr 0xffe3 ; GFX10-SCRATCH-NEXT: s_mov_b32 exec_lo, s1 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s0, 4 -; GFX10-SCRATCH-NEXT: s_mov_b32 s1, external_void_func_v2f32_inreg@abs32@hi -; GFX10-SCRATCH-NEXT: s_mov_b32 s0, external_void_func_v2f32_inreg@abs32@lo +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s0, 2 +; GFX10-SCRATCH-NEXT: s_mov_b32 s3, external_void_func_v2f32_inreg@abs32@hi +; GFX10-SCRATCH-NEXT: s_mov_b32 s2, external_void_func_v2f32_inreg@abs32@lo +; GFX10-SCRATCH-NEXT: s_mov_b32 s0, 1.0 +; GFX10-SCRATCH-NEXT: s_mov_b32 s1, 2.0 +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s30, 0 ; GFX10-SCRATCH-NEXT: s_add_i32 s32, s32, 16 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s4, 0 -; GFX10-SCRATCH-NEXT: s_mov_b32 s4, 1.0 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s5, 1 -; GFX10-SCRATCH-NEXT: s_mov_b32 s5, 2.0 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s30, 2 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s31, 3 -; GFX10-SCRATCH-NEXT: s_swappc_b64 s[30:31], s[0:1] -; GFX10-SCRATCH-NEXT: v_readlane_b32 s31, v40, 3 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s30, v40, 2 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s5, v40, 1 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s4, v40, 0 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s0, v40, 4 +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s31, 1 +; GFX10-SCRATCH-NEXT: s_swappc_b64 s[30:31], s[2:3] +; GFX10-SCRATCH-NEXT: v_readlane_b32 s31, v40, 1 +; GFX10-SCRATCH-NEXT: v_readlane_b32 s30, v40, 0 +; GFX10-SCRATCH-NEXT: v_readlane_b32 s0, v40, 2 ; GFX10-SCRATCH-NEXT: s_or_saveexec_b32 s1, -1 ; GFX10-SCRATCH-NEXT: scratch_load_dword v40, off, s33 ; 4-byte Folded Reload ; GFX10-SCRATCH-NEXT: s_waitcnt_depctr 0xffe3 @@ -11164,25 +10994,19 @@ define amdgpu_gfx void @test_call_external_void_func_v3f32_imm_inreg() #0 { ; GFX9-NEXT: s_or_saveexec_b64 s[36:37], -1 ; GFX9-NEXT: buffer_store_dword v40, off, s[0:3], s33 ; 4-byte Folded Spill ; GFX9-NEXT: s_mov_b64 exec, s[36:37] -; GFX9-NEXT: v_writelane_b32 v40, s34, 5 -; GFX9-NEXT: v_writelane_b32 v40, s4, 0 -; GFX9-NEXT: v_writelane_b32 v40, s5, 1 -; GFX9-NEXT: v_writelane_b32 v40, s6, 2 -; GFX9-NEXT: v_writelane_b32 v40, s30, 3 +; GFX9-NEXT: v_writelane_b32 v40, s34, 2 +; GFX9-NEXT: v_writelane_b32 v40, s30, 0 ; GFX9-NEXT: s_mov_b32 s35, external_void_func_v3f32_inreg@abs32@hi ; GFX9-NEXT: s_mov_b32 s34, external_void_func_v3f32_inreg@abs32@lo -; GFX9-NEXT: s_mov_b32 s4, 1.0 -; GFX9-NEXT: s_mov_b32 s5, 2.0 -; GFX9-NEXT: s_mov_b32 s6, 4.0 +; GFX9-NEXT: s_mov_b32 s0, 1.0 +; GFX9-NEXT: s_mov_b32 s1, 2.0 +; GFX9-NEXT: s_mov_b32 s2, 4.0 ; GFX9-NEXT: s_addk_i32 s32, 0x400 -; GFX9-NEXT: v_writelane_b32 v40, s31, 4 +; GFX9-NEXT: v_writelane_b32 v40, s31, 1 ; GFX9-NEXT: s_swappc_b64 s[30:31], s[34:35] -; GFX9-NEXT: v_readlane_b32 s31, v40, 4 -; GFX9-NEXT: v_readlane_b32 s30, v40, 3 -; GFX9-NEXT: v_readlane_b32 s6, v40, 2 -; GFX9-NEXT: v_readlane_b32 s5, v40, 1 -; GFX9-NEXT: v_readlane_b32 s4, v40, 0 -; GFX9-NEXT: v_readlane_b32 s34, v40, 5 +; GFX9-NEXT: v_readlane_b32 s31, v40, 1 +; GFX9-NEXT: v_readlane_b32 s30, v40, 0 +; GFX9-NEXT: v_readlane_b32 s34, v40, 2 ; GFX9-NEXT: s_or_saveexec_b64 s[36:37], -1 ; GFX9-NEXT: buffer_load_dword v40, off, s[0:3], s33 ; 4-byte Folded Reload ; GFX9-NEXT: s_mov_b64 exec, s[36:37] @@ -11200,25 +11024,19 @@ define amdgpu_gfx void @test_call_external_void_func_v3f32_imm_inreg() #0 { ; GFX10-NEXT: buffer_store_dword v40, off, s[0:3], s33 ; 4-byte Folded Spill ; GFX10-NEXT: s_waitcnt_depctr 0xffe3 ; GFX10-NEXT: s_mov_b32 exec_lo, s35 -; GFX10-NEXT: v_writelane_b32 v40, s34, 5 +; GFX10-NEXT: v_writelane_b32 v40, s34, 2 ; GFX10-NEXT: s_mov_b32 s35, external_void_func_v3f32_inreg@abs32@hi ; GFX10-NEXT: s_mov_b32 s34, external_void_func_v3f32_inreg@abs32@lo +; GFX10-NEXT: s_mov_b32 s0, 1.0 +; GFX10-NEXT: s_mov_b32 s1, 2.0 +; GFX10-NEXT: v_writelane_b32 v40, s30, 0 +; GFX10-NEXT: s_mov_b32 s2, 4.0 ; GFX10-NEXT: s_addk_i32 s32, 0x200 -; GFX10-NEXT: v_writelane_b32 v40, s4, 0 -; GFX10-NEXT: s_mov_b32 s4, 1.0 -; GFX10-NEXT: v_writelane_b32 v40, s5, 1 -; GFX10-NEXT: s_mov_b32 s5, 2.0 -; GFX10-NEXT: v_writelane_b32 v40, s6, 2 -; GFX10-NEXT: s_mov_b32 s6, 4.0 -; GFX10-NEXT: v_writelane_b32 v40, s30, 3 -; GFX10-NEXT: v_writelane_b32 v40, s31, 4 +; GFX10-NEXT: v_writelane_b32 v40, s31, 1 ; GFX10-NEXT: s_swappc_b64 s[30:31], s[34:35] -; GFX10-NEXT: v_readlane_b32 s31, v40, 4 -; GFX10-NEXT: v_readlane_b32 s30, v40, 3 -; GFX10-NEXT: v_readlane_b32 s6, v40, 2 -; GFX10-NEXT: v_readlane_b32 s5, v40, 1 -; GFX10-NEXT: v_readlane_b32 s4, v40, 0 -; GFX10-NEXT: v_readlane_b32 s34, v40, 5 +; GFX10-NEXT: v_readlane_b32 s31, v40, 1 +; GFX10-NEXT: v_readlane_b32 s30, v40, 0 +; GFX10-NEXT: v_readlane_b32 s34, v40, 2 ; GFX10-NEXT: s_or_saveexec_b32 s35, -1 ; GFX10-NEXT: buffer_load_dword v40, off, s[0:3], s33 ; 4-byte Folded Reload ; GFX10-NEXT: s_waitcnt_depctr 0xffe3 @@ -11236,26 +11054,20 @@ define amdgpu_gfx void @test_call_external_void_func_v3f32_imm_inreg() #0 { ; GFX11-NEXT: s_or_saveexec_b32 s1, -1 ; GFX11-NEXT: scratch_store_b32 off, v40, s33 ; 4-byte Folded Spill ; GFX11-NEXT: s_mov_b32 exec_lo, s1 -; GFX11-NEXT: v_writelane_b32 v40, s0, 5 -; GFX11-NEXT: s_mov_b32 s1, external_void_func_v3f32_inreg@abs32@hi -; GFX11-NEXT: s_mov_b32 s0, external_void_func_v3f32_inreg@abs32@lo +; GFX11-NEXT: v_writelane_b32 v40, s0, 2 +; GFX11-NEXT: s_mov_b32 s35, external_void_func_v3f32_inreg@abs32@hi +; GFX11-NEXT: s_mov_b32 s34, external_void_func_v3f32_inreg@abs32@lo +; GFX11-NEXT: s_mov_b32 s0, 1.0 +; GFX11-NEXT: s_mov_b32 s1, 2.0 +; GFX11-NEXT: v_writelane_b32 v40, s30, 0 +; GFX11-NEXT: s_mov_b32 s2, 4.0 ; GFX11-NEXT: s_add_i32 s32, s32, 16 -; GFX11-NEXT: v_writelane_b32 v40, s4, 0 -; GFX11-NEXT: s_mov_b32 s4, 1.0 -; GFX11-NEXT: v_writelane_b32 v40, s5, 1 -; GFX11-NEXT: s_mov_b32 s5, 2.0 -; GFX11-NEXT: v_writelane_b32 v40, s6, 2 -; GFX11-NEXT: s_mov_b32 s6, 4.0 -; GFX11-NEXT: v_writelane_b32 v40, s30, 3 -; GFX11-NEXT: v_writelane_b32 v40, s31, 4 -; GFX11-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX11-NEXT: v_writelane_b32 v40, s31, 1 +; GFX11-NEXT: s_swappc_b64 s[30:31], s[34:35] ; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_1) -; GFX11-NEXT: v_readlane_b32 s31, v40, 4 -; GFX11-NEXT: v_readlane_b32 s30, v40, 3 -; GFX11-NEXT: v_readlane_b32 s6, v40, 2 -; GFX11-NEXT: v_readlane_b32 s5, v40, 1 -; GFX11-NEXT: v_readlane_b32 s4, v40, 0 -; GFX11-NEXT: v_readlane_b32 s0, v40, 5 +; GFX11-NEXT: v_readlane_b32 s31, v40, 1 +; GFX11-NEXT: v_readlane_b32 s30, v40, 0 +; GFX11-NEXT: v_readlane_b32 s0, v40, 2 ; GFX11-NEXT: s_or_saveexec_b32 s1, -1 ; GFX11-NEXT: scratch_load_b32 v40, off, s33 ; 4-byte Folded Reload ; GFX11-NEXT: s_mov_b32 exec_lo, s1 @@ -11273,25 +11085,19 @@ define amdgpu_gfx void @test_call_external_void_func_v3f32_imm_inreg() #0 { ; GFX10-SCRATCH-NEXT: scratch_store_dword off, v40, s33 ; 4-byte Folded Spill ; GFX10-SCRATCH-NEXT: s_waitcnt_depctr 0xffe3 ; GFX10-SCRATCH-NEXT: s_mov_b32 exec_lo, s1 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s0, 5 -; GFX10-SCRATCH-NEXT: s_mov_b32 s1, external_void_func_v3f32_inreg@abs32@hi -; GFX10-SCRATCH-NEXT: s_mov_b32 s0, external_void_func_v3f32_inreg@abs32@lo +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s0, 2 +; GFX10-SCRATCH-NEXT: s_mov_b32 s35, external_void_func_v3f32_inreg@abs32@hi +; GFX10-SCRATCH-NEXT: s_mov_b32 s34, external_void_func_v3f32_inreg@abs32@lo +; GFX10-SCRATCH-NEXT: s_mov_b32 s0, 1.0 +; GFX10-SCRATCH-NEXT: s_mov_b32 s1, 2.0 +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s30, 0 +; GFX10-SCRATCH-NEXT: s_mov_b32 s2, 4.0 ; GFX10-SCRATCH-NEXT: s_add_i32 s32, s32, 16 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s4, 0 -; GFX10-SCRATCH-NEXT: s_mov_b32 s4, 1.0 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s5, 1 -; GFX10-SCRATCH-NEXT: s_mov_b32 s5, 2.0 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s6, 2 -; GFX10-SCRATCH-NEXT: s_mov_b32 s6, 4.0 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s30, 3 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s31, 4 -; GFX10-SCRATCH-NEXT: s_swappc_b64 s[30:31], s[0:1] -; GFX10-SCRATCH-NEXT: v_readlane_b32 s31, v40, 4 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s30, v40, 3 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s6, v40, 2 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s5, v40, 1 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s4, v40, 0 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s0, v40, 5 +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s31, 1 +; GFX10-SCRATCH-NEXT: s_swappc_b64 s[30:31], s[34:35] +; GFX10-SCRATCH-NEXT: v_readlane_b32 s31, v40, 1 +; GFX10-SCRATCH-NEXT: v_readlane_b32 s30, v40, 0 +; GFX10-SCRATCH-NEXT: v_readlane_b32 s0, v40, 2 ; GFX10-SCRATCH-NEXT: s_or_saveexec_b32 s1, -1 ; GFX10-SCRATCH-NEXT: scratch_load_dword v40, off, s33 ; 4-byte Folded Reload ; GFX10-SCRATCH-NEXT: s_waitcnt_depctr 0xffe3 @@ -11313,31 +11119,23 @@ define amdgpu_gfx void @test_call_external_void_func_v5f32_imm_inreg() #0 { ; GFX9-NEXT: s_or_saveexec_b64 s[36:37], -1 ; GFX9-NEXT: buffer_store_dword v40, off, s[0:3], s33 ; 4-byte Folded Spill ; GFX9-NEXT: s_mov_b64 exec, s[36:37] -; GFX9-NEXT: v_writelane_b32 v40, s34, 7 +; GFX9-NEXT: v_writelane_b32 v40, s34, 3 ; GFX9-NEXT: v_writelane_b32 v40, s4, 0 -; GFX9-NEXT: v_writelane_b32 v40, s5, 1 -; GFX9-NEXT: v_writelane_b32 v40, s6, 2 -; GFX9-NEXT: v_writelane_b32 v40, s7, 3 -; GFX9-NEXT: v_writelane_b32 v40, s8, 4 -; GFX9-NEXT: v_writelane_b32 v40, s30, 5 +; GFX9-NEXT: v_writelane_b32 v40, s30, 1 ; GFX9-NEXT: s_mov_b32 s35, external_void_func_v5f32_inreg@abs32@hi ; GFX9-NEXT: s_mov_b32 s34, external_void_func_v5f32_inreg@abs32@lo -; GFX9-NEXT: s_mov_b32 s4, 1.0 -; GFX9-NEXT: s_mov_b32 s5, 2.0 -; GFX9-NEXT: s_mov_b32 s6, 4.0 -; GFX9-NEXT: s_mov_b32 s7, -1.0 -; GFX9-NEXT: s_mov_b32 s8, 0.5 +; GFX9-NEXT: s_mov_b32 s0, 1.0 +; GFX9-NEXT: s_mov_b32 s1, 2.0 +; GFX9-NEXT: s_mov_b32 s2, 4.0 +; GFX9-NEXT: s_mov_b32 s3, -1.0 +; GFX9-NEXT: s_mov_b32 s4, 0.5 ; GFX9-NEXT: s_addk_i32 s32, 0x400 -; GFX9-NEXT: v_writelane_b32 v40, s31, 6 +; GFX9-NEXT: v_writelane_b32 v40, s31, 2 ; GFX9-NEXT: s_swappc_b64 s[30:31], s[34:35] -; GFX9-NEXT: v_readlane_b32 s31, v40, 6 -; GFX9-NEXT: v_readlane_b32 s30, v40, 5 -; GFX9-NEXT: v_readlane_b32 s8, v40, 4 -; GFX9-NEXT: v_readlane_b32 s7, v40, 3 -; GFX9-NEXT: v_readlane_b32 s6, v40, 2 -; GFX9-NEXT: v_readlane_b32 s5, v40, 1 +; GFX9-NEXT: v_readlane_b32 s31, v40, 2 +; GFX9-NEXT: v_readlane_b32 s30, v40, 1 ; GFX9-NEXT: v_readlane_b32 s4, v40, 0 -; GFX9-NEXT: v_readlane_b32 s34, v40, 7 +; GFX9-NEXT: v_readlane_b32 s34, v40, 3 ; GFX9-NEXT: s_or_saveexec_b64 s[36:37], -1 ; GFX9-NEXT: buffer_load_dword v40, off, s[0:3], s33 ; 4-byte Folded Reload ; GFX9-NEXT: s_mov_b64 exec, s[36:37] @@ -11355,31 +11153,23 @@ define amdgpu_gfx void @test_call_external_void_func_v5f32_imm_inreg() #0 { ; GFX10-NEXT: buffer_store_dword v40, off, s[0:3], s33 ; 4-byte Folded Spill ; GFX10-NEXT: s_waitcnt_depctr 0xffe3 ; GFX10-NEXT: s_mov_b32 exec_lo, s35 -; GFX10-NEXT: v_writelane_b32 v40, s34, 7 +; GFX10-NEXT: v_writelane_b32 v40, s34, 3 ; GFX10-NEXT: s_mov_b32 s35, external_void_func_v5f32_inreg@abs32@hi ; GFX10-NEXT: s_mov_b32 s34, external_void_func_v5f32_inreg@abs32@lo -; GFX10-NEXT: s_addk_i32 s32, 0x200 +; GFX10-NEXT: s_mov_b32 s0, 1.0 +; GFX10-NEXT: s_mov_b32 s1, 2.0 ; GFX10-NEXT: v_writelane_b32 v40, s4, 0 -; GFX10-NEXT: s_mov_b32 s4, 1.0 -; GFX10-NEXT: v_writelane_b32 v40, s5, 1 -; GFX10-NEXT: s_mov_b32 s5, 2.0 -; GFX10-NEXT: v_writelane_b32 v40, s6, 2 -; GFX10-NEXT: s_mov_b32 s6, 4.0 -; GFX10-NEXT: v_writelane_b32 v40, s7, 3 -; GFX10-NEXT: s_mov_b32 s7, -1.0 -; GFX10-NEXT: v_writelane_b32 v40, s8, 4 -; GFX10-NEXT: s_mov_b32 s8, 0.5 -; GFX10-NEXT: v_writelane_b32 v40, s30, 5 -; GFX10-NEXT: v_writelane_b32 v40, s31, 6 +; GFX10-NEXT: s_mov_b32 s2, 4.0 +; GFX10-NEXT: s_mov_b32 s3, -1.0 +; GFX10-NEXT: s_mov_b32 s4, 0.5 +; GFX10-NEXT: s_addk_i32 s32, 0x200 +; GFX10-NEXT: v_writelane_b32 v40, s30, 1 +; GFX10-NEXT: v_writelane_b32 v40, s31, 2 ; GFX10-NEXT: s_swappc_b64 s[30:31], s[34:35] -; GFX10-NEXT: v_readlane_b32 s31, v40, 6 -; GFX10-NEXT: v_readlane_b32 s30, v40, 5 -; GFX10-NEXT: v_readlane_b32 s8, v40, 4 -; GFX10-NEXT: v_readlane_b32 s7, v40, 3 -; GFX10-NEXT: v_readlane_b32 s6, v40, 2 -; GFX10-NEXT: v_readlane_b32 s5, v40, 1 +; GFX10-NEXT: v_readlane_b32 s31, v40, 2 +; GFX10-NEXT: v_readlane_b32 s30, v40, 1 ; GFX10-NEXT: v_readlane_b32 s4, v40, 0 -; GFX10-NEXT: v_readlane_b32 s34, v40, 7 +; GFX10-NEXT: v_readlane_b32 s34, v40, 3 ; GFX10-NEXT: s_or_saveexec_b32 s35, -1 ; GFX10-NEXT: buffer_load_dword v40, off, s[0:3], s33 ; 4-byte Folded Reload ; GFX10-NEXT: s_waitcnt_depctr 0xffe3 @@ -11397,32 +11187,24 @@ define amdgpu_gfx void @test_call_external_void_func_v5f32_imm_inreg() #0 { ; GFX11-NEXT: s_or_saveexec_b32 s1, -1 ; GFX11-NEXT: scratch_store_b32 off, v40, s33 ; 4-byte Folded Spill ; GFX11-NEXT: s_mov_b32 exec_lo, s1 -; GFX11-NEXT: v_writelane_b32 v40, s0, 7 -; GFX11-NEXT: s_mov_b32 s1, external_void_func_v5f32_inreg@abs32@hi -; GFX11-NEXT: s_mov_b32 s0, external_void_func_v5f32_inreg@abs32@lo -; GFX11-NEXT: s_add_i32 s32, s32, 16 +; GFX11-NEXT: v_writelane_b32 v40, s0, 3 +; GFX11-NEXT: s_mov_b32 s35, external_void_func_v5f32_inreg@abs32@hi +; GFX11-NEXT: s_mov_b32 s34, external_void_func_v5f32_inreg@abs32@lo +; GFX11-NEXT: s_mov_b32 s0, 1.0 +; GFX11-NEXT: s_mov_b32 s1, 2.0 ; GFX11-NEXT: v_writelane_b32 v40, s4, 0 -; GFX11-NEXT: s_mov_b32 s4, 1.0 -; GFX11-NEXT: v_writelane_b32 v40, s5, 1 -; GFX11-NEXT: s_mov_b32 s5, 2.0 -; GFX11-NEXT: v_writelane_b32 v40, s6, 2 -; GFX11-NEXT: s_mov_b32 s6, 4.0 -; GFX11-NEXT: v_writelane_b32 v40, s7, 3 -; GFX11-NEXT: s_mov_b32 s7, -1.0 -; GFX11-NEXT: v_writelane_b32 v40, s8, 4 -; GFX11-NEXT: s_mov_b32 s8, 0.5 -; GFX11-NEXT: v_writelane_b32 v40, s30, 5 -; GFX11-NEXT: v_writelane_b32 v40, s31, 6 -; GFX11-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX11-NEXT: s_mov_b32 s2, 4.0 +; GFX11-NEXT: s_mov_b32 s3, -1.0 +; GFX11-NEXT: s_mov_b32 s4, 0.5 +; GFX11-NEXT: s_add_i32 s32, s32, 16 +; GFX11-NEXT: v_writelane_b32 v40, s30, 1 +; GFX11-NEXT: v_writelane_b32 v40, s31, 2 +; GFX11-NEXT: s_swappc_b64 s[30:31], s[34:35] ; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_1) -; GFX11-NEXT: v_readlane_b32 s31, v40, 6 -; GFX11-NEXT: v_readlane_b32 s30, v40, 5 -; GFX11-NEXT: v_readlane_b32 s8, v40, 4 -; GFX11-NEXT: v_readlane_b32 s7, v40, 3 -; GFX11-NEXT: v_readlane_b32 s6, v40, 2 -; GFX11-NEXT: v_readlane_b32 s5, v40, 1 +; GFX11-NEXT: v_readlane_b32 s31, v40, 2 +; GFX11-NEXT: v_readlane_b32 s30, v40, 1 ; GFX11-NEXT: v_readlane_b32 s4, v40, 0 -; GFX11-NEXT: v_readlane_b32 s0, v40, 7 +; GFX11-NEXT: v_readlane_b32 s0, v40, 3 ; GFX11-NEXT: s_or_saveexec_b32 s1, -1 ; GFX11-NEXT: scratch_load_b32 v40, off, s33 ; 4-byte Folded Reload ; GFX11-NEXT: s_mov_b32 exec_lo, s1 @@ -11440,31 +11222,23 @@ define amdgpu_gfx void @test_call_external_void_func_v5f32_imm_inreg() #0 { ; GFX10-SCRATCH-NEXT: scratch_store_dword off, v40, s33 ; 4-byte Folded Spill ; GFX10-SCRATCH-NEXT: s_waitcnt_depctr 0xffe3 ; GFX10-SCRATCH-NEXT: s_mov_b32 exec_lo, s1 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s0, 7 -; GFX10-SCRATCH-NEXT: s_mov_b32 s1, external_void_func_v5f32_inreg@abs32@hi -; GFX10-SCRATCH-NEXT: s_mov_b32 s0, external_void_func_v5f32_inreg@abs32@lo -; GFX10-SCRATCH-NEXT: s_add_i32 s32, s32, 16 +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s0, 3 +; GFX10-SCRATCH-NEXT: s_mov_b32 s35, external_void_func_v5f32_inreg@abs32@hi +; GFX10-SCRATCH-NEXT: s_mov_b32 s34, external_void_func_v5f32_inreg@abs32@lo +; GFX10-SCRATCH-NEXT: s_mov_b32 s0, 1.0 +; GFX10-SCRATCH-NEXT: s_mov_b32 s1, 2.0 ; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s4, 0 -; GFX10-SCRATCH-NEXT: s_mov_b32 s4, 1.0 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s5, 1 -; GFX10-SCRATCH-NEXT: s_mov_b32 s5, 2.0 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s6, 2 -; GFX10-SCRATCH-NEXT: s_mov_b32 s6, 4.0 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s7, 3 -; GFX10-SCRATCH-NEXT: s_mov_b32 s7, -1.0 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s8, 4 -; GFX10-SCRATCH-NEXT: s_mov_b32 s8, 0.5 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s30, 5 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s31, 6 -; GFX10-SCRATCH-NEXT: s_swappc_b64 s[30:31], s[0:1] -; GFX10-SCRATCH-NEXT: v_readlane_b32 s31, v40, 6 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s30, v40, 5 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s8, v40, 4 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s7, v40, 3 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s6, v40, 2 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s5, v40, 1 +; GFX10-SCRATCH-NEXT: s_mov_b32 s2, 4.0 +; GFX10-SCRATCH-NEXT: s_mov_b32 s3, -1.0 +; GFX10-SCRATCH-NEXT: s_mov_b32 s4, 0.5 +; GFX10-SCRATCH-NEXT: s_add_i32 s32, s32, 16 +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s30, 1 +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s31, 2 +; GFX10-SCRATCH-NEXT: s_swappc_b64 s[30:31], s[34:35] +; GFX10-SCRATCH-NEXT: v_readlane_b32 s31, v40, 2 +; GFX10-SCRATCH-NEXT: v_readlane_b32 s30, v40, 1 ; GFX10-SCRATCH-NEXT: v_readlane_b32 s4, v40, 0 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s0, v40, 7 +; GFX10-SCRATCH-NEXT: v_readlane_b32 s0, v40, 3 ; GFX10-SCRATCH-NEXT: s_or_saveexec_b32 s1, -1 ; GFX10-SCRATCH-NEXT: scratch_load_dword v40, off, s33 ; 4-byte Folded Reload ; GFX10-SCRATCH-NEXT: s_waitcnt_depctr 0xffe3 @@ -11486,22 +11260,18 @@ define amdgpu_gfx void @test_call_external_void_func_f64_imm_inreg() #0 { ; GFX9-NEXT: s_or_saveexec_b64 s[36:37], -1 ; GFX9-NEXT: buffer_store_dword v40, off, s[0:3], s33 ; 4-byte Folded Spill ; GFX9-NEXT: s_mov_b64 exec, s[36:37] -; GFX9-NEXT: v_writelane_b32 v40, s34, 4 -; GFX9-NEXT: v_writelane_b32 v40, s4, 0 -; GFX9-NEXT: v_writelane_b32 v40, s5, 1 -; GFX9-NEXT: v_writelane_b32 v40, s30, 2 +; GFX9-NEXT: v_writelane_b32 v40, s34, 2 +; GFX9-NEXT: v_writelane_b32 v40, s30, 0 ; GFX9-NEXT: s_mov_b32 s35, external_void_func_f64_inreg@abs32@hi ; GFX9-NEXT: s_mov_b32 s34, external_void_func_f64_inreg@abs32@lo -; GFX9-NEXT: s_mov_b32 s4, 0 -; GFX9-NEXT: s_mov_b32 s5, 0x40100000 +; GFX9-NEXT: s_mov_b32 s0, 0 +; GFX9-NEXT: s_mov_b32 s1, 0x40100000 ; GFX9-NEXT: s_addk_i32 s32, 0x400 -; GFX9-NEXT: v_writelane_b32 v40, s31, 3 +; GFX9-NEXT: v_writelane_b32 v40, s31, 1 ; GFX9-NEXT: s_swappc_b64 s[30:31], s[34:35] -; GFX9-NEXT: v_readlane_b32 s31, v40, 3 -; GFX9-NEXT: v_readlane_b32 s30, v40, 2 -; GFX9-NEXT: v_readlane_b32 s5, v40, 1 -; GFX9-NEXT: v_readlane_b32 s4, v40, 0 -; GFX9-NEXT: v_readlane_b32 s34, v40, 4 +; GFX9-NEXT: v_readlane_b32 s31, v40, 1 +; GFX9-NEXT: v_readlane_b32 s30, v40, 0 +; GFX9-NEXT: v_readlane_b32 s34, v40, 2 ; GFX9-NEXT: s_or_saveexec_b64 s[36:37], -1 ; GFX9-NEXT: buffer_load_dword v40, off, s[0:3], s33 ; 4-byte Folded Reload ; GFX9-NEXT: s_mov_b64 exec, s[36:37] @@ -11519,22 +11289,18 @@ define amdgpu_gfx void @test_call_external_void_func_f64_imm_inreg() #0 { ; GFX10-NEXT: buffer_store_dword v40, off, s[0:3], s33 ; 4-byte Folded Spill ; GFX10-NEXT: s_waitcnt_depctr 0xffe3 ; GFX10-NEXT: s_mov_b32 exec_lo, s35 -; GFX10-NEXT: v_writelane_b32 v40, s34, 4 +; GFX10-NEXT: v_writelane_b32 v40, s34, 2 ; GFX10-NEXT: s_mov_b32 s35, external_void_func_f64_inreg@abs32@hi ; GFX10-NEXT: s_mov_b32 s34, external_void_func_f64_inreg@abs32@lo +; GFX10-NEXT: s_mov_b32 s0, 0 +; GFX10-NEXT: s_mov_b32 s1, 0x40100000 +; GFX10-NEXT: v_writelane_b32 v40, s30, 0 ; GFX10-NEXT: s_addk_i32 s32, 0x200 -; GFX10-NEXT: v_writelane_b32 v40, s4, 0 -; GFX10-NEXT: s_mov_b32 s4, 0 -; GFX10-NEXT: v_writelane_b32 v40, s5, 1 -; GFX10-NEXT: s_mov_b32 s5, 0x40100000 -; GFX10-NEXT: v_writelane_b32 v40, s30, 2 -; GFX10-NEXT: v_writelane_b32 v40, s31, 3 +; GFX10-NEXT: v_writelane_b32 v40, s31, 1 ; GFX10-NEXT: s_swappc_b64 s[30:31], s[34:35] -; GFX10-NEXT: v_readlane_b32 s31, v40, 3 -; GFX10-NEXT: v_readlane_b32 s30, v40, 2 -; GFX10-NEXT: v_readlane_b32 s5, v40, 1 -; GFX10-NEXT: v_readlane_b32 s4, v40, 0 -; GFX10-NEXT: v_readlane_b32 s34, v40, 4 +; GFX10-NEXT: v_readlane_b32 s31, v40, 1 +; GFX10-NEXT: v_readlane_b32 s30, v40, 0 +; GFX10-NEXT: v_readlane_b32 s34, v40, 2 ; GFX10-NEXT: s_or_saveexec_b32 s35, -1 ; GFX10-NEXT: buffer_load_dword v40, off, s[0:3], s33 ; 4-byte Folded Reload ; GFX10-NEXT: s_waitcnt_depctr 0xffe3 @@ -11552,23 +11318,19 @@ define amdgpu_gfx void @test_call_external_void_func_f64_imm_inreg() #0 { ; GFX11-NEXT: s_or_saveexec_b32 s1, -1 ; GFX11-NEXT: scratch_store_b32 off, v40, s33 ; 4-byte Folded Spill ; GFX11-NEXT: s_mov_b32 exec_lo, s1 -; GFX11-NEXT: v_writelane_b32 v40, s0, 4 -; GFX11-NEXT: s_mov_b32 s1, external_void_func_f64_inreg@abs32@hi -; GFX11-NEXT: s_mov_b32 s0, external_void_func_f64_inreg@abs32@lo +; GFX11-NEXT: v_writelane_b32 v40, s0, 2 +; GFX11-NEXT: s_mov_b32 s3, external_void_func_f64_inreg@abs32@hi +; GFX11-NEXT: s_mov_b32 s2, external_void_func_f64_inreg@abs32@lo +; GFX11-NEXT: s_mov_b32 s0, 0 +; GFX11-NEXT: s_mov_b32 s1, 0x40100000 +; GFX11-NEXT: v_writelane_b32 v40, s30, 0 ; GFX11-NEXT: s_add_i32 s32, s32, 16 -; GFX11-NEXT: v_writelane_b32 v40, s4, 0 -; GFX11-NEXT: s_mov_b32 s4, 0 -; GFX11-NEXT: v_writelane_b32 v40, s5, 1 -; GFX11-NEXT: s_mov_b32 s5, 0x40100000 -; GFX11-NEXT: v_writelane_b32 v40, s30, 2 -; GFX11-NEXT: v_writelane_b32 v40, s31, 3 -; GFX11-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX11-NEXT: v_writelane_b32 v40, s31, 1 +; GFX11-NEXT: s_swappc_b64 s[30:31], s[2:3] ; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_1) -; GFX11-NEXT: v_readlane_b32 s31, v40, 3 -; GFX11-NEXT: v_readlane_b32 s30, v40, 2 -; GFX11-NEXT: v_readlane_b32 s5, v40, 1 -; GFX11-NEXT: v_readlane_b32 s4, v40, 0 -; GFX11-NEXT: v_readlane_b32 s0, v40, 4 +; GFX11-NEXT: v_readlane_b32 s31, v40, 1 +; GFX11-NEXT: v_readlane_b32 s30, v40, 0 +; GFX11-NEXT: v_readlane_b32 s0, v40, 2 ; GFX11-NEXT: s_or_saveexec_b32 s1, -1 ; GFX11-NEXT: scratch_load_b32 v40, off, s33 ; 4-byte Folded Reload ; GFX11-NEXT: s_mov_b32 exec_lo, s1 @@ -11586,22 +11348,18 @@ define amdgpu_gfx void @test_call_external_void_func_f64_imm_inreg() #0 { ; GFX10-SCRATCH-NEXT: scratch_store_dword off, v40, s33 ; 4-byte Folded Spill ; GFX10-SCRATCH-NEXT: s_waitcnt_depctr 0xffe3 ; GFX10-SCRATCH-NEXT: s_mov_b32 exec_lo, s1 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s0, 4 -; GFX10-SCRATCH-NEXT: s_mov_b32 s1, external_void_func_f64_inreg@abs32@hi -; GFX10-SCRATCH-NEXT: s_mov_b32 s0, external_void_func_f64_inreg@abs32@lo +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s0, 2 +; GFX10-SCRATCH-NEXT: s_mov_b32 s3, external_void_func_f64_inreg@abs32@hi +; GFX10-SCRATCH-NEXT: s_mov_b32 s2, external_void_func_f64_inreg@abs32@lo +; GFX10-SCRATCH-NEXT: s_mov_b32 s0, 0 +; GFX10-SCRATCH-NEXT: s_mov_b32 s1, 0x40100000 +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s30, 0 ; GFX10-SCRATCH-NEXT: s_add_i32 s32, s32, 16 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s4, 0 -; GFX10-SCRATCH-NEXT: s_mov_b32 s4, 0 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s5, 1 -; GFX10-SCRATCH-NEXT: s_mov_b32 s5, 0x40100000 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s30, 2 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s31, 3 -; GFX10-SCRATCH-NEXT: s_swappc_b64 s[30:31], s[0:1] -; GFX10-SCRATCH-NEXT: v_readlane_b32 s31, v40, 3 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s30, v40, 2 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s5, v40, 1 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s4, v40, 0 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s0, v40, 4 +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s31, 1 +; GFX10-SCRATCH-NEXT: s_swappc_b64 s[30:31], s[2:3] +; GFX10-SCRATCH-NEXT: v_readlane_b32 s31, v40, 1 +; GFX10-SCRATCH-NEXT: v_readlane_b32 s30, v40, 0 +; GFX10-SCRATCH-NEXT: v_readlane_b32 s0, v40, 2 ; GFX10-SCRATCH-NEXT: s_or_saveexec_b32 s1, -1 ; GFX10-SCRATCH-NEXT: scratch_load_dword v40, off, s33 ; 4-byte Folded Reload ; GFX10-SCRATCH-NEXT: s_waitcnt_depctr 0xffe3 @@ -11623,28 +11381,20 @@ define amdgpu_gfx void @test_call_external_void_func_v2f64_imm_inreg() #0 { ; GFX9-NEXT: s_or_saveexec_b64 s[36:37], -1 ; GFX9-NEXT: buffer_store_dword v40, off, s[0:3], s33 ; 4-byte Folded Spill ; GFX9-NEXT: s_mov_b64 exec, s[36:37] -; GFX9-NEXT: v_writelane_b32 v40, s34, 6 -; GFX9-NEXT: v_writelane_b32 v40, s4, 0 -; GFX9-NEXT: v_writelane_b32 v40, s5, 1 -; GFX9-NEXT: v_writelane_b32 v40, s6, 2 -; GFX9-NEXT: v_writelane_b32 v40, s7, 3 -; GFX9-NEXT: v_writelane_b32 v40, s30, 4 +; GFX9-NEXT: v_writelane_b32 v40, s34, 2 +; GFX9-NEXT: v_writelane_b32 v40, s30, 0 ; GFX9-NEXT: s_mov_b32 s35, external_void_func_v2f64_inreg@abs32@hi ; GFX9-NEXT: s_mov_b32 s34, external_void_func_v2f64_inreg@abs32@lo -; GFX9-NEXT: s_mov_b32 s4, 0 -; GFX9-NEXT: s_mov_b32 s5, 2.0 -; GFX9-NEXT: s_mov_b32 s6, 0 -; GFX9-NEXT: s_mov_b32 s7, 0x40100000 +; GFX9-NEXT: s_mov_b32 s2, 0 +; GFX9-NEXT: s_mov_b32 s0, 0 +; GFX9-NEXT: s_mov_b32 s1, 2.0 +; GFX9-NEXT: s_mov_b32 s3, 0x40100000 ; GFX9-NEXT: s_addk_i32 s32, 0x400 -; GFX9-NEXT: v_writelane_b32 v40, s31, 5 +; GFX9-NEXT: v_writelane_b32 v40, s31, 1 ; GFX9-NEXT: s_swappc_b64 s[30:31], s[34:35] -; GFX9-NEXT: v_readlane_b32 s31, v40, 5 -; GFX9-NEXT: v_readlane_b32 s30, v40, 4 -; GFX9-NEXT: v_readlane_b32 s7, v40, 3 -; GFX9-NEXT: v_readlane_b32 s6, v40, 2 -; GFX9-NEXT: v_readlane_b32 s5, v40, 1 -; GFX9-NEXT: v_readlane_b32 s4, v40, 0 -; GFX9-NEXT: v_readlane_b32 s34, v40, 6 +; GFX9-NEXT: v_readlane_b32 s31, v40, 1 +; GFX9-NEXT: v_readlane_b32 s30, v40, 0 +; GFX9-NEXT: v_readlane_b32 s34, v40, 2 ; GFX9-NEXT: s_or_saveexec_b64 s[36:37], -1 ; GFX9-NEXT: buffer_load_dword v40, off, s[0:3], s33 ; 4-byte Folded Reload ; GFX9-NEXT: s_mov_b64 exec, s[36:37] @@ -11662,28 +11412,20 @@ define amdgpu_gfx void @test_call_external_void_func_v2f64_imm_inreg() #0 { ; GFX10-NEXT: buffer_store_dword v40, off, s[0:3], s33 ; 4-byte Folded Spill ; GFX10-NEXT: s_waitcnt_depctr 0xffe3 ; GFX10-NEXT: s_mov_b32 exec_lo, s35 -; GFX10-NEXT: v_writelane_b32 v40, s34, 6 +; GFX10-NEXT: v_writelane_b32 v40, s34, 2 ; GFX10-NEXT: s_mov_b32 s35, external_void_func_v2f64_inreg@abs32@hi ; GFX10-NEXT: s_mov_b32 s34, external_void_func_v2f64_inreg@abs32@lo +; GFX10-NEXT: s_mov_b32 s2, 0 +; GFX10-NEXT: s_mov_b32 s0, 0 +; GFX10-NEXT: v_writelane_b32 v40, s30, 0 +; GFX10-NEXT: s_mov_b32 s1, 2.0 +; GFX10-NEXT: s_mov_b32 s3, 0x40100000 ; GFX10-NEXT: s_addk_i32 s32, 0x200 -; GFX10-NEXT: v_writelane_b32 v40, s4, 0 -; GFX10-NEXT: s_mov_b32 s4, 0 -; GFX10-NEXT: v_writelane_b32 v40, s5, 1 -; GFX10-NEXT: s_mov_b32 s5, 2.0 -; GFX10-NEXT: v_writelane_b32 v40, s6, 2 -; GFX10-NEXT: s_mov_b32 s6, 0 -; GFX10-NEXT: v_writelane_b32 v40, s7, 3 -; GFX10-NEXT: s_mov_b32 s7, 0x40100000 -; GFX10-NEXT: v_writelane_b32 v40, s30, 4 -; GFX10-NEXT: v_writelane_b32 v40, s31, 5 +; GFX10-NEXT: v_writelane_b32 v40, s31, 1 ; GFX10-NEXT: s_swappc_b64 s[30:31], s[34:35] -; GFX10-NEXT: v_readlane_b32 s31, v40, 5 -; GFX10-NEXT: v_readlane_b32 s30, v40, 4 -; GFX10-NEXT: v_readlane_b32 s7, v40, 3 -; GFX10-NEXT: v_readlane_b32 s6, v40, 2 -; GFX10-NEXT: v_readlane_b32 s5, v40, 1 -; GFX10-NEXT: v_readlane_b32 s4, v40, 0 -; GFX10-NEXT: v_readlane_b32 s34, v40, 6 +; GFX10-NEXT: v_readlane_b32 s31, v40, 1 +; GFX10-NEXT: v_readlane_b32 s30, v40, 0 +; GFX10-NEXT: v_readlane_b32 s34, v40, 2 ; GFX10-NEXT: s_or_saveexec_b32 s35, -1 ; GFX10-NEXT: buffer_load_dword v40, off, s[0:3], s33 ; 4-byte Folded Reload ; GFX10-NEXT: s_waitcnt_depctr 0xffe3 @@ -11701,29 +11443,21 @@ define amdgpu_gfx void @test_call_external_void_func_v2f64_imm_inreg() #0 { ; GFX11-NEXT: s_or_saveexec_b32 s1, -1 ; GFX11-NEXT: scratch_store_b32 off, v40, s33 ; 4-byte Folded Spill ; GFX11-NEXT: s_mov_b32 exec_lo, s1 -; GFX11-NEXT: v_writelane_b32 v40, s0, 6 -; GFX11-NEXT: s_mov_b32 s1, external_void_func_v2f64_inreg@abs32@hi -; GFX11-NEXT: s_mov_b32 s0, external_void_func_v2f64_inreg@abs32@lo +; GFX11-NEXT: v_writelane_b32 v40, s0, 2 +; GFX11-NEXT: s_mov_b32 s35, external_void_func_v2f64_inreg@abs32@hi +; GFX11-NEXT: s_mov_b32 s34, external_void_func_v2f64_inreg@abs32@lo +; GFX11-NEXT: s_mov_b32 s0, 0 +; GFX11-NEXT: s_mov_b32 s1, 2.0 +; GFX11-NEXT: v_writelane_b32 v40, s30, 0 +; GFX11-NEXT: s_mov_b32 s2, 0 +; GFX11-NEXT: s_mov_b32 s3, 0x40100000 ; GFX11-NEXT: s_add_i32 s32, s32, 16 -; GFX11-NEXT: v_writelane_b32 v40, s4, 0 -; GFX11-NEXT: s_mov_b32 s4, 0 -; GFX11-NEXT: v_writelane_b32 v40, s5, 1 -; GFX11-NEXT: s_mov_b32 s5, 2.0 -; GFX11-NEXT: v_writelane_b32 v40, s6, 2 -; GFX11-NEXT: s_mov_b32 s6, 0 -; GFX11-NEXT: v_writelane_b32 v40, s7, 3 -; GFX11-NEXT: s_mov_b32 s7, 0x40100000 -; GFX11-NEXT: v_writelane_b32 v40, s30, 4 -; GFX11-NEXT: v_writelane_b32 v40, s31, 5 -; GFX11-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX11-NEXT: v_writelane_b32 v40, s31, 1 +; GFX11-NEXT: s_swappc_b64 s[30:31], s[34:35] ; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_1) -; GFX11-NEXT: v_readlane_b32 s31, v40, 5 -; GFX11-NEXT: v_readlane_b32 s30, v40, 4 -; GFX11-NEXT: v_readlane_b32 s7, v40, 3 -; GFX11-NEXT: v_readlane_b32 s6, v40, 2 -; GFX11-NEXT: v_readlane_b32 s5, v40, 1 -; GFX11-NEXT: v_readlane_b32 s4, v40, 0 -; GFX11-NEXT: v_readlane_b32 s0, v40, 6 +; GFX11-NEXT: v_readlane_b32 s31, v40, 1 +; GFX11-NEXT: v_readlane_b32 s30, v40, 0 +; GFX11-NEXT: v_readlane_b32 s0, v40, 2 ; GFX11-NEXT: s_or_saveexec_b32 s1, -1 ; GFX11-NEXT: scratch_load_b32 v40, off, s33 ; 4-byte Folded Reload ; GFX11-NEXT: s_mov_b32 exec_lo, s1 @@ -11741,28 +11475,20 @@ define amdgpu_gfx void @test_call_external_void_func_v2f64_imm_inreg() #0 { ; GFX10-SCRATCH-NEXT: scratch_store_dword off, v40, s33 ; 4-byte Folded Spill ; GFX10-SCRATCH-NEXT: s_waitcnt_depctr 0xffe3 ; GFX10-SCRATCH-NEXT: s_mov_b32 exec_lo, s1 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s0, 6 -; GFX10-SCRATCH-NEXT: s_mov_b32 s1, external_void_func_v2f64_inreg@abs32@hi -; GFX10-SCRATCH-NEXT: s_mov_b32 s0, external_void_func_v2f64_inreg@abs32@lo +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s0, 2 +; GFX10-SCRATCH-NEXT: s_mov_b32 s35, external_void_func_v2f64_inreg@abs32@hi +; GFX10-SCRATCH-NEXT: s_mov_b32 s34, external_void_func_v2f64_inreg@abs32@lo +; GFX10-SCRATCH-NEXT: s_mov_b32 s0, 0 +; GFX10-SCRATCH-NEXT: s_mov_b32 s1, 2.0 +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s30, 0 +; GFX10-SCRATCH-NEXT: s_mov_b32 s2, 0 +; GFX10-SCRATCH-NEXT: s_mov_b32 s3, 0x40100000 ; GFX10-SCRATCH-NEXT: s_add_i32 s32, s32, 16 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s4, 0 -; GFX10-SCRATCH-NEXT: s_mov_b32 s4, 0 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s5, 1 -; GFX10-SCRATCH-NEXT: s_mov_b32 s5, 2.0 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s6, 2 -; GFX10-SCRATCH-NEXT: s_mov_b32 s6, 0 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s7, 3 -; GFX10-SCRATCH-NEXT: s_mov_b32 s7, 0x40100000 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s30, 4 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s31, 5 -; GFX10-SCRATCH-NEXT: s_swappc_b64 s[30:31], s[0:1] -; GFX10-SCRATCH-NEXT: v_readlane_b32 s31, v40, 5 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s30, v40, 4 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s7, v40, 3 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s6, v40, 2 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s5, v40, 1 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s4, v40, 0 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s0, v40, 6 +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s31, 1 +; GFX10-SCRATCH-NEXT: s_swappc_b64 s[30:31], s[34:35] +; GFX10-SCRATCH-NEXT: v_readlane_b32 s31, v40, 1 +; GFX10-SCRATCH-NEXT: v_readlane_b32 s30, v40, 0 +; GFX10-SCRATCH-NEXT: v_readlane_b32 s0, v40, 2 ; GFX10-SCRATCH-NEXT: s_or_saveexec_b32 s1, -1 ; GFX10-SCRATCH-NEXT: scratch_load_dword v40, off, s33 ; 4-byte Folded Reload ; GFX10-SCRATCH-NEXT: s_waitcnt_depctr 0xffe3 @@ -11784,34 +11510,26 @@ define amdgpu_gfx void @test_call_external_void_func_v3f64_imm_inreg() #0 { ; GFX9-NEXT: s_or_saveexec_b64 s[36:37], -1 ; GFX9-NEXT: buffer_store_dword v40, off, s[0:3], s33 ; 4-byte Folded Spill ; GFX9-NEXT: s_mov_b64 exec, s[36:37] -; GFX9-NEXT: v_writelane_b32 v40, s34, 8 +; GFX9-NEXT: v_writelane_b32 v40, s34, 4 ; GFX9-NEXT: v_writelane_b32 v40, s4, 0 ; GFX9-NEXT: v_writelane_b32 v40, s5, 1 -; GFX9-NEXT: v_writelane_b32 v40, s6, 2 -; GFX9-NEXT: v_writelane_b32 v40, s7, 3 -; GFX9-NEXT: v_writelane_b32 v40, s8, 4 -; GFX9-NEXT: v_writelane_b32 v40, s9, 5 -; GFX9-NEXT: v_writelane_b32 v40, s30, 6 +; GFX9-NEXT: v_writelane_b32 v40, s30, 2 ; GFX9-NEXT: s_mov_b32 s35, external_void_func_v3f64_inreg@abs32@hi ; GFX9-NEXT: s_mov_b32 s34, external_void_func_v3f64_inreg@abs32@lo +; GFX9-NEXT: s_mov_b32 s0, 0 +; GFX9-NEXT: s_mov_b32 s1, 2.0 +; GFX9-NEXT: s_mov_b32 s2, 0 +; GFX9-NEXT: s_mov_b32 s3, 0x40100000 ; GFX9-NEXT: s_mov_b32 s4, 0 -; GFX9-NEXT: s_mov_b32 s5, 2.0 -; GFX9-NEXT: s_mov_b32 s6, 0 -; GFX9-NEXT: s_mov_b32 s7, 0x40100000 -; GFX9-NEXT: s_mov_b32 s8, 0 -; GFX9-NEXT: s_mov_b32 s9, 0x40200000 +; GFX9-NEXT: s_mov_b32 s5, 0x40200000 ; GFX9-NEXT: s_addk_i32 s32, 0x400 -; GFX9-NEXT: v_writelane_b32 v40, s31, 7 +; GFX9-NEXT: v_writelane_b32 v40, s31, 3 ; GFX9-NEXT: s_swappc_b64 s[30:31], s[34:35] -; GFX9-NEXT: v_readlane_b32 s31, v40, 7 -; GFX9-NEXT: v_readlane_b32 s30, v40, 6 -; GFX9-NEXT: v_readlane_b32 s9, v40, 5 -; GFX9-NEXT: v_readlane_b32 s8, v40, 4 -; GFX9-NEXT: v_readlane_b32 s7, v40, 3 -; GFX9-NEXT: v_readlane_b32 s6, v40, 2 +; GFX9-NEXT: v_readlane_b32 s31, v40, 3 +; GFX9-NEXT: v_readlane_b32 s30, v40, 2 ; GFX9-NEXT: v_readlane_b32 s5, v40, 1 ; GFX9-NEXT: v_readlane_b32 s4, v40, 0 -; GFX9-NEXT: v_readlane_b32 s34, v40, 8 +; GFX9-NEXT: v_readlane_b32 s34, v40, 4 ; GFX9-NEXT: s_or_saveexec_b64 s[36:37], -1 ; GFX9-NEXT: buffer_load_dword v40, off, s[0:3], s33 ; 4-byte Folded Reload ; GFX9-NEXT: s_mov_b64 exec, s[36:37] @@ -11829,34 +11547,26 @@ define amdgpu_gfx void @test_call_external_void_func_v3f64_imm_inreg() #0 { ; GFX10-NEXT: buffer_store_dword v40, off, s[0:3], s33 ; 4-byte Folded Spill ; GFX10-NEXT: s_waitcnt_depctr 0xffe3 ; GFX10-NEXT: s_mov_b32 exec_lo, s35 -; GFX10-NEXT: v_writelane_b32 v40, s34, 8 +; GFX10-NEXT: v_writelane_b32 v40, s34, 4 ; GFX10-NEXT: s_mov_b32 s35, external_void_func_v3f64_inreg@abs32@hi ; GFX10-NEXT: s_mov_b32 s34, external_void_func_v3f64_inreg@abs32@lo -; GFX10-NEXT: s_addk_i32 s32, 0x200 +; GFX10-NEXT: s_mov_b32 s0, 0 +; GFX10-NEXT: s_mov_b32 s1, 2.0 ; GFX10-NEXT: v_writelane_b32 v40, s4, 0 +; GFX10-NEXT: s_mov_b32 s2, 0 +; GFX10-NEXT: s_mov_b32 s3, 0x40100000 ; GFX10-NEXT: s_mov_b32 s4, 0 +; GFX10-NEXT: s_addk_i32 s32, 0x200 ; GFX10-NEXT: v_writelane_b32 v40, s5, 1 -; GFX10-NEXT: s_mov_b32 s5, 2.0 -; GFX10-NEXT: v_writelane_b32 v40, s6, 2 -; GFX10-NEXT: s_mov_b32 s6, 0 -; GFX10-NEXT: v_writelane_b32 v40, s7, 3 -; GFX10-NEXT: s_mov_b32 s7, 0x40100000 -; GFX10-NEXT: v_writelane_b32 v40, s8, 4 -; GFX10-NEXT: s_mov_b32 s8, 0 -; GFX10-NEXT: v_writelane_b32 v40, s9, 5 -; GFX10-NEXT: s_mov_b32 s9, 0x40200000 -; GFX10-NEXT: v_writelane_b32 v40, s30, 6 -; GFX10-NEXT: v_writelane_b32 v40, s31, 7 +; GFX10-NEXT: s_mov_b32 s5, 0x40200000 +; GFX10-NEXT: v_writelane_b32 v40, s30, 2 +; GFX10-NEXT: v_writelane_b32 v40, s31, 3 ; GFX10-NEXT: s_swappc_b64 s[30:31], s[34:35] -; GFX10-NEXT: v_readlane_b32 s31, v40, 7 -; GFX10-NEXT: v_readlane_b32 s30, v40, 6 -; GFX10-NEXT: v_readlane_b32 s9, v40, 5 -; GFX10-NEXT: v_readlane_b32 s8, v40, 4 -; GFX10-NEXT: v_readlane_b32 s7, v40, 3 -; GFX10-NEXT: v_readlane_b32 s6, v40, 2 +; GFX10-NEXT: v_readlane_b32 s31, v40, 3 +; GFX10-NEXT: v_readlane_b32 s30, v40, 2 ; GFX10-NEXT: v_readlane_b32 s5, v40, 1 ; GFX10-NEXT: v_readlane_b32 s4, v40, 0 -; GFX10-NEXT: v_readlane_b32 s34, v40, 8 +; GFX10-NEXT: v_readlane_b32 s34, v40, 4 ; GFX10-NEXT: s_or_saveexec_b32 s35, -1 ; GFX10-NEXT: buffer_load_dword v40, off, s[0:3], s33 ; 4-byte Folded Reload ; GFX10-NEXT: s_waitcnt_depctr 0xffe3 @@ -11874,35 +11584,27 @@ define amdgpu_gfx void @test_call_external_void_func_v3f64_imm_inreg() #0 { ; GFX11-NEXT: s_or_saveexec_b32 s1, -1 ; GFX11-NEXT: scratch_store_b32 off, v40, s33 ; 4-byte Folded Spill ; GFX11-NEXT: s_mov_b32 exec_lo, s1 -; GFX11-NEXT: v_writelane_b32 v40, s0, 8 -; GFX11-NEXT: s_mov_b32 s1, external_void_func_v3f64_inreg@abs32@hi -; GFX11-NEXT: s_mov_b32 s0, external_void_func_v3f64_inreg@abs32@lo -; GFX11-NEXT: s_add_i32 s32, s32, 16 +; GFX11-NEXT: v_writelane_b32 v40, s0, 4 +; GFX11-NEXT: s_mov_b32 s35, external_void_func_v3f64_inreg@abs32@hi +; GFX11-NEXT: s_mov_b32 s34, external_void_func_v3f64_inreg@abs32@lo +; GFX11-NEXT: s_mov_b32 s0, 0 +; GFX11-NEXT: s_mov_b32 s1, 2.0 ; GFX11-NEXT: v_writelane_b32 v40, s4, 0 +; GFX11-NEXT: s_mov_b32 s2, 0 +; GFX11-NEXT: s_mov_b32 s3, 0x40100000 ; GFX11-NEXT: s_mov_b32 s4, 0 +; GFX11-NEXT: s_add_i32 s32, s32, 16 ; GFX11-NEXT: v_writelane_b32 v40, s5, 1 -; GFX11-NEXT: s_mov_b32 s5, 2.0 -; GFX11-NEXT: v_writelane_b32 v40, s6, 2 -; GFX11-NEXT: s_mov_b32 s6, 0 -; GFX11-NEXT: v_writelane_b32 v40, s7, 3 -; GFX11-NEXT: s_mov_b32 s7, 0x40100000 -; GFX11-NEXT: v_writelane_b32 v40, s8, 4 -; GFX11-NEXT: s_mov_b32 s8, 0 -; GFX11-NEXT: v_writelane_b32 v40, s9, 5 -; GFX11-NEXT: s_mov_b32 s9, 0x40200000 -; GFX11-NEXT: v_writelane_b32 v40, s30, 6 -; GFX11-NEXT: v_writelane_b32 v40, s31, 7 -; GFX11-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX11-NEXT: s_mov_b32 s5, 0x40200000 +; GFX11-NEXT: v_writelane_b32 v40, s30, 2 +; GFX11-NEXT: v_writelane_b32 v40, s31, 3 +; GFX11-NEXT: s_swappc_b64 s[30:31], s[34:35] ; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_1) -; GFX11-NEXT: v_readlane_b32 s31, v40, 7 -; GFX11-NEXT: v_readlane_b32 s30, v40, 6 -; GFX11-NEXT: v_readlane_b32 s9, v40, 5 -; GFX11-NEXT: v_readlane_b32 s8, v40, 4 -; GFX11-NEXT: v_readlane_b32 s7, v40, 3 -; GFX11-NEXT: v_readlane_b32 s6, v40, 2 +; GFX11-NEXT: v_readlane_b32 s31, v40, 3 +; GFX11-NEXT: v_readlane_b32 s30, v40, 2 ; GFX11-NEXT: v_readlane_b32 s5, v40, 1 ; GFX11-NEXT: v_readlane_b32 s4, v40, 0 -; GFX11-NEXT: v_readlane_b32 s0, v40, 8 +; GFX11-NEXT: v_readlane_b32 s0, v40, 4 ; GFX11-NEXT: s_or_saveexec_b32 s1, -1 ; GFX11-NEXT: scratch_load_b32 v40, off, s33 ; 4-byte Folded Reload ; GFX11-NEXT: s_mov_b32 exec_lo, s1 @@ -11920,34 +11622,26 @@ define amdgpu_gfx void @test_call_external_void_func_v3f64_imm_inreg() #0 { ; GFX10-SCRATCH-NEXT: scratch_store_dword off, v40, s33 ; 4-byte Folded Spill ; GFX10-SCRATCH-NEXT: s_waitcnt_depctr 0xffe3 ; GFX10-SCRATCH-NEXT: s_mov_b32 exec_lo, s1 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s0, 8 -; GFX10-SCRATCH-NEXT: s_mov_b32 s1, external_void_func_v3f64_inreg@abs32@hi -; GFX10-SCRATCH-NEXT: s_mov_b32 s0, external_void_func_v3f64_inreg@abs32@lo -; GFX10-SCRATCH-NEXT: s_add_i32 s32, s32, 16 +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s0, 4 +; GFX10-SCRATCH-NEXT: s_mov_b32 s35, external_void_func_v3f64_inreg@abs32@hi +; GFX10-SCRATCH-NEXT: s_mov_b32 s34, external_void_func_v3f64_inreg@abs32@lo +; GFX10-SCRATCH-NEXT: s_mov_b32 s0, 0 +; GFX10-SCRATCH-NEXT: s_mov_b32 s1, 2.0 ; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s4, 0 +; GFX10-SCRATCH-NEXT: s_mov_b32 s2, 0 +; GFX10-SCRATCH-NEXT: s_mov_b32 s3, 0x40100000 ; GFX10-SCRATCH-NEXT: s_mov_b32 s4, 0 +; GFX10-SCRATCH-NEXT: s_add_i32 s32, s32, 16 ; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s5, 1 -; GFX10-SCRATCH-NEXT: s_mov_b32 s5, 2.0 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s6, 2 -; GFX10-SCRATCH-NEXT: s_mov_b32 s6, 0 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s7, 3 -; GFX10-SCRATCH-NEXT: s_mov_b32 s7, 0x40100000 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s8, 4 -; GFX10-SCRATCH-NEXT: s_mov_b32 s8, 0 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s9, 5 -; GFX10-SCRATCH-NEXT: s_mov_b32 s9, 0x40200000 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s30, 6 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s31, 7 -; GFX10-SCRATCH-NEXT: s_swappc_b64 s[30:31], s[0:1] -; GFX10-SCRATCH-NEXT: v_readlane_b32 s31, v40, 7 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s30, v40, 6 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s9, v40, 5 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s8, v40, 4 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s7, v40, 3 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s6, v40, 2 +; GFX10-SCRATCH-NEXT: s_mov_b32 s5, 0x40200000 +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s30, 2 +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s31, 3 +; GFX10-SCRATCH-NEXT: s_swappc_b64 s[30:31], s[34:35] +; GFX10-SCRATCH-NEXT: v_readlane_b32 s31, v40, 3 +; GFX10-SCRATCH-NEXT: v_readlane_b32 s30, v40, 2 ; GFX10-SCRATCH-NEXT: v_readlane_b32 s5, v40, 1 ; GFX10-SCRATCH-NEXT: v_readlane_b32 s4, v40, 0 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s0, v40, 8 +; GFX10-SCRATCH-NEXT: v_readlane_b32 s0, v40, 4 ; GFX10-SCRATCH-NEXT: s_or_saveexec_b32 s1, -1 ; GFX10-SCRATCH-NEXT: scratch_load_dword v40, off, s33 ; 4-byte Folded Reload ; GFX10-SCRATCH-NEXT: s_waitcnt_depctr 0xffe3 @@ -11969,19 +11663,17 @@ define amdgpu_gfx void @test_call_external_void_func_v2i16_inreg() #0 { ; GFX9-NEXT: s_or_saveexec_b64 s[36:37], -1 ; GFX9-NEXT: buffer_store_dword v40, off, s[0:3], s33 ; 4-byte Folded Spill ; GFX9-NEXT: s_mov_b64 exec, s[36:37] -; GFX9-NEXT: v_writelane_b32 v40, s34, 3 -; GFX9-NEXT: v_writelane_b32 v40, s4, 0 -; GFX9-NEXT: s_load_dword s4, s[34:35], 0x0 -; GFX9-NEXT: v_writelane_b32 v40, s30, 1 +; GFX9-NEXT: s_load_dword s0, s[34:35], 0x0 +; GFX9-NEXT: v_writelane_b32 v40, s34, 2 +; GFX9-NEXT: v_writelane_b32 v40, s30, 0 ; GFX9-NEXT: s_mov_b32 s35, external_void_func_v2i16_inreg@abs32@hi ; GFX9-NEXT: s_mov_b32 s34, external_void_func_v2i16_inreg@abs32@lo ; GFX9-NEXT: s_addk_i32 s32, 0x400 -; GFX9-NEXT: v_writelane_b32 v40, s31, 2 +; GFX9-NEXT: v_writelane_b32 v40, s31, 1 ; GFX9-NEXT: s_swappc_b64 s[30:31], s[34:35] -; GFX9-NEXT: v_readlane_b32 s31, v40, 2 -; GFX9-NEXT: v_readlane_b32 s30, v40, 1 -; GFX9-NEXT: v_readlane_b32 s4, v40, 0 -; GFX9-NEXT: v_readlane_b32 s34, v40, 3 +; GFX9-NEXT: v_readlane_b32 s31, v40, 1 +; GFX9-NEXT: v_readlane_b32 s30, v40, 0 +; GFX9-NEXT: v_readlane_b32 s34, v40, 2 ; GFX9-NEXT: s_or_saveexec_b64 s[36:37], -1 ; GFX9-NEXT: buffer_load_dword v40, off, s[0:3], s33 ; 4-byte Folded Reload ; GFX9-NEXT: s_mov_b64 exec, s[36:37] @@ -11999,19 +11691,17 @@ define amdgpu_gfx void @test_call_external_void_func_v2i16_inreg() #0 { ; GFX10-NEXT: buffer_store_dword v40, off, s[0:3], s33 ; 4-byte Folded Spill ; GFX10-NEXT: s_waitcnt_depctr 0xffe3 ; GFX10-NEXT: s_mov_b32 exec_lo, s35 -; GFX10-NEXT: v_writelane_b32 v40, s34, 3 -; GFX10-NEXT: s_addk_i32 s32, 0x200 -; GFX10-NEXT: v_writelane_b32 v40, s4, 0 -; GFX10-NEXT: s_load_dword s4, s[34:35], 0x0 +; GFX10-NEXT: s_load_dword s0, s[34:35], 0x0 +; GFX10-NEXT: v_writelane_b32 v40, s34, 2 ; GFX10-NEXT: s_mov_b32 s35, external_void_func_v2i16_inreg@abs32@hi ; GFX10-NEXT: s_mov_b32 s34, external_void_func_v2i16_inreg@abs32@lo -; GFX10-NEXT: v_writelane_b32 v40, s30, 1 -; GFX10-NEXT: v_writelane_b32 v40, s31, 2 +; GFX10-NEXT: s_addk_i32 s32, 0x200 +; GFX10-NEXT: v_writelane_b32 v40, s30, 0 +; GFX10-NEXT: v_writelane_b32 v40, s31, 1 ; GFX10-NEXT: s_swappc_b64 s[30:31], s[34:35] -; GFX10-NEXT: v_readlane_b32 s31, v40, 2 -; GFX10-NEXT: v_readlane_b32 s30, v40, 1 -; GFX10-NEXT: v_readlane_b32 s4, v40, 0 -; GFX10-NEXT: v_readlane_b32 s34, v40, 3 +; GFX10-NEXT: v_readlane_b32 s31, v40, 1 +; GFX10-NEXT: v_readlane_b32 s30, v40, 0 +; GFX10-NEXT: v_readlane_b32 s34, v40, 2 ; GFX10-NEXT: s_or_saveexec_b32 s35, -1 ; GFX10-NEXT: buffer_load_dword v40, off, s[0:3], s33 ; 4-byte Folded Reload ; GFX10-NEXT: s_waitcnt_depctr 0xffe3 @@ -12029,20 +11719,18 @@ define amdgpu_gfx void @test_call_external_void_func_v2i16_inreg() #0 { ; GFX11-NEXT: s_or_saveexec_b32 s1, -1 ; GFX11-NEXT: scratch_store_b32 off, v40, s33 ; 4-byte Folded Spill ; GFX11-NEXT: s_mov_b32 exec_lo, s1 -; GFX11-NEXT: v_writelane_b32 v40, s0, 3 +; GFX11-NEXT: v_writelane_b32 v40, s0, 2 +; GFX11-NEXT: s_load_b32 s0, s[0:1], 0x0 +; GFX11-NEXT: s_mov_b32 s3, external_void_func_v2i16_inreg@abs32@hi +; GFX11-NEXT: s_mov_b32 s2, external_void_func_v2i16_inreg@abs32@lo ; GFX11-NEXT: s_add_i32 s32, s32, 16 -; GFX11-NEXT: v_writelane_b32 v40, s4, 0 -; GFX11-NEXT: s_load_b32 s4, s[0:1], 0x0 -; GFX11-NEXT: s_mov_b32 s1, external_void_func_v2i16_inreg@abs32@hi -; GFX11-NEXT: s_mov_b32 s0, external_void_func_v2i16_inreg@abs32@lo -; GFX11-NEXT: v_writelane_b32 v40, s30, 1 -; GFX11-NEXT: v_writelane_b32 v40, s31, 2 -; GFX11-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX11-NEXT: v_writelane_b32 v40, s30, 0 +; GFX11-NEXT: v_writelane_b32 v40, s31, 1 +; GFX11-NEXT: s_swappc_b64 s[30:31], s[2:3] ; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_1) -; GFX11-NEXT: v_readlane_b32 s31, v40, 2 -; GFX11-NEXT: v_readlane_b32 s30, v40, 1 -; GFX11-NEXT: v_readlane_b32 s4, v40, 0 -; GFX11-NEXT: v_readlane_b32 s0, v40, 3 +; GFX11-NEXT: v_readlane_b32 s31, v40, 1 +; GFX11-NEXT: v_readlane_b32 s30, v40, 0 +; GFX11-NEXT: v_readlane_b32 s0, v40, 2 ; GFX11-NEXT: s_or_saveexec_b32 s1, -1 ; GFX11-NEXT: scratch_load_b32 v40, off, s33 ; 4-byte Folded Reload ; GFX11-NEXT: s_mov_b32 exec_lo, s1 @@ -12060,19 +11748,17 @@ define amdgpu_gfx void @test_call_external_void_func_v2i16_inreg() #0 { ; GFX10-SCRATCH-NEXT: scratch_store_dword off, v40, s33 ; 4-byte Folded Spill ; GFX10-SCRATCH-NEXT: s_waitcnt_depctr 0xffe3 ; GFX10-SCRATCH-NEXT: s_mov_b32 exec_lo, s1 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s0, 3 +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s0, 2 +; GFX10-SCRATCH-NEXT: s_load_dword s0, s[0:1], 0x0 +; GFX10-SCRATCH-NEXT: s_mov_b32 s3, external_void_func_v2i16_inreg@abs32@hi +; GFX10-SCRATCH-NEXT: s_mov_b32 s2, external_void_func_v2i16_inreg@abs32@lo ; GFX10-SCRATCH-NEXT: s_add_i32 s32, s32, 16 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s4, 0 -; GFX10-SCRATCH-NEXT: s_load_dword s4, s[0:1], 0x0 -; GFX10-SCRATCH-NEXT: s_mov_b32 s1, external_void_func_v2i16_inreg@abs32@hi -; GFX10-SCRATCH-NEXT: s_mov_b32 s0, external_void_func_v2i16_inreg@abs32@lo -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s30, 1 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s31, 2 -; GFX10-SCRATCH-NEXT: s_swappc_b64 s[30:31], s[0:1] -; GFX10-SCRATCH-NEXT: v_readlane_b32 s31, v40, 2 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s30, v40, 1 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s4, v40, 0 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s0, v40, 3 +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s30, 0 +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s31, 1 +; GFX10-SCRATCH-NEXT: s_swappc_b64 s[30:31], s[2:3] +; GFX10-SCRATCH-NEXT: v_readlane_b32 s31, v40, 1 +; GFX10-SCRATCH-NEXT: v_readlane_b32 s30, v40, 0 +; GFX10-SCRATCH-NEXT: v_readlane_b32 s0, v40, 2 ; GFX10-SCRATCH-NEXT: s_or_saveexec_b32 s1, -1 ; GFX10-SCRATCH-NEXT: scratch_load_dword v40, off, s33 ; 4-byte Folded Reload ; GFX10-SCRATCH-NEXT: s_waitcnt_depctr 0xffe3 @@ -12095,21 +11781,20 @@ define amdgpu_gfx void @test_call_external_void_func_v3i16_inreg() #0 { ; GFX9-NEXT: s_or_saveexec_b64 s[36:37], -1 ; GFX9-NEXT: buffer_store_dword v40, off, s[0:3], s33 ; 4-byte Folded Spill ; GFX9-NEXT: s_mov_b64 exec, s[36:37] -; GFX9-NEXT: v_writelane_b32 v40, s34, 4 -; GFX9-NEXT: v_writelane_b32 v40, s4, 0 -; GFX9-NEXT: v_writelane_b32 v40, s5, 1 -; GFX9-NEXT: s_load_dwordx2 s[4:5], s[34:35], 0x0 -; GFX9-NEXT: v_writelane_b32 v40, s30, 2 -; GFX9-NEXT: s_mov_b32 s35, external_void_func_v3i16_inreg@abs32@hi -; GFX9-NEXT: s_mov_b32 s34, external_void_func_v3i16_inreg@abs32@lo +; GFX9-NEXT: v_writelane_b32 v40, s34, 2 +; GFX9-NEXT: s_load_dwordx2 s[34:35], s[34:35], 0x0 +; GFX9-NEXT: v_writelane_b32 v40, s30, 0 +; GFX9-NEXT: s_mov_b32 s37, external_void_func_v3i16_inreg@abs32@hi +; GFX9-NEXT: s_mov_b32 s36, external_void_func_v3i16_inreg@abs32@lo ; GFX9-NEXT: s_addk_i32 s32, 0x400 -; GFX9-NEXT: v_writelane_b32 v40, s31, 3 -; GFX9-NEXT: s_swappc_b64 s[30:31], s[34:35] -; GFX9-NEXT: v_readlane_b32 s31, v40, 3 -; GFX9-NEXT: v_readlane_b32 s30, v40, 2 -; GFX9-NEXT: v_readlane_b32 s5, v40, 1 -; GFX9-NEXT: v_readlane_b32 s4, v40, 0 -; GFX9-NEXT: v_readlane_b32 s34, v40, 4 +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: s_mov_b32 s1, s35 +; GFX9-NEXT: s_mov_b32 s0, s34 +; GFX9-NEXT: v_writelane_b32 v40, s31, 1 +; GFX9-NEXT: s_swappc_b64 s[30:31], s[36:37] +; GFX9-NEXT: v_readlane_b32 s31, v40, 1 +; GFX9-NEXT: v_readlane_b32 s30, v40, 0 +; GFX9-NEXT: v_readlane_b32 s34, v40, 2 ; GFX9-NEXT: s_or_saveexec_b64 s[36:37], -1 ; GFX9-NEXT: buffer_load_dword v40, off, s[0:3], s33 ; 4-byte Folded Reload ; GFX9-NEXT: s_mov_b64 exec, s[36:37] @@ -12127,21 +11812,20 @@ define amdgpu_gfx void @test_call_external_void_func_v3i16_inreg() #0 { ; GFX10-NEXT: buffer_store_dword v40, off, s[0:3], s33 ; 4-byte Folded Spill ; GFX10-NEXT: s_waitcnt_depctr 0xffe3 ; GFX10-NEXT: s_mov_b32 exec_lo, s35 -; GFX10-NEXT: v_writelane_b32 v40, s34, 4 +; GFX10-NEXT: v_writelane_b32 v40, s34, 2 +; GFX10-NEXT: s_load_dwordx2 s[34:35], s[34:35], 0x0 +; GFX10-NEXT: s_mov_b32 s37, external_void_func_v3i16_inreg@abs32@hi +; GFX10-NEXT: s_mov_b32 s36, external_void_func_v3i16_inreg@abs32@lo ; GFX10-NEXT: s_addk_i32 s32, 0x200 -; GFX10-NEXT: v_writelane_b32 v40, s4, 0 -; GFX10-NEXT: v_writelane_b32 v40, s5, 1 -; GFX10-NEXT: s_load_dwordx2 s[4:5], s[34:35], 0x0 -; GFX10-NEXT: s_mov_b32 s35, external_void_func_v3i16_inreg@abs32@hi -; GFX10-NEXT: s_mov_b32 s34, external_void_func_v3i16_inreg@abs32@lo -; GFX10-NEXT: v_writelane_b32 v40, s30, 2 -; GFX10-NEXT: v_writelane_b32 v40, s31, 3 -; GFX10-NEXT: s_swappc_b64 s[30:31], s[34:35] -; GFX10-NEXT: v_readlane_b32 s31, v40, 3 -; GFX10-NEXT: v_readlane_b32 s30, v40, 2 -; GFX10-NEXT: v_readlane_b32 s5, v40, 1 -; GFX10-NEXT: v_readlane_b32 s4, v40, 0 -; GFX10-NEXT: v_readlane_b32 s34, v40, 4 +; GFX10-NEXT: v_writelane_b32 v40, s30, 0 +; GFX10-NEXT: v_writelane_b32 v40, s31, 1 +; GFX10-NEXT: s_waitcnt lgkmcnt(0) +; GFX10-NEXT: s_mov_b32 s1, s35 +; GFX10-NEXT: s_mov_b32 s0, s34 +; GFX10-NEXT: s_swappc_b64 s[30:31], s[36:37] +; GFX10-NEXT: v_readlane_b32 s31, v40, 1 +; GFX10-NEXT: v_readlane_b32 s30, v40, 0 +; GFX10-NEXT: v_readlane_b32 s34, v40, 2 ; GFX10-NEXT: s_or_saveexec_b32 s35, -1 ; GFX10-NEXT: buffer_load_dword v40, off, s[0:3], s33 ; 4-byte Folded Reload ; GFX10-NEXT: s_waitcnt_depctr 0xffe3 @@ -12159,22 +11843,18 @@ define amdgpu_gfx void @test_call_external_void_func_v3i16_inreg() #0 { ; GFX11-NEXT: s_or_saveexec_b32 s1, -1 ; GFX11-NEXT: scratch_store_b32 off, v40, s33 ; 4-byte Folded Spill ; GFX11-NEXT: s_mov_b32 exec_lo, s1 -; GFX11-NEXT: v_writelane_b32 v40, s0, 4 +; GFX11-NEXT: v_writelane_b32 v40, s0, 2 +; GFX11-NEXT: s_load_b64 s[0:1], s[0:1], 0x0 +; GFX11-NEXT: s_mov_b32 s3, external_void_func_v3i16_inreg@abs32@hi +; GFX11-NEXT: s_mov_b32 s2, external_void_func_v3i16_inreg@abs32@lo ; GFX11-NEXT: s_add_i32 s32, s32, 16 -; GFX11-NEXT: v_writelane_b32 v40, s4, 0 -; GFX11-NEXT: v_writelane_b32 v40, s5, 1 -; GFX11-NEXT: s_load_b64 s[4:5], s[0:1], 0x0 -; GFX11-NEXT: s_mov_b32 s1, external_void_func_v3i16_inreg@abs32@hi -; GFX11-NEXT: s_mov_b32 s0, external_void_func_v3i16_inreg@abs32@lo -; GFX11-NEXT: v_writelane_b32 v40, s30, 2 -; GFX11-NEXT: v_writelane_b32 v40, s31, 3 -; GFX11-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX11-NEXT: v_writelane_b32 v40, s30, 0 +; GFX11-NEXT: v_writelane_b32 v40, s31, 1 +; GFX11-NEXT: s_swappc_b64 s[30:31], s[2:3] ; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_1) -; GFX11-NEXT: v_readlane_b32 s31, v40, 3 -; GFX11-NEXT: v_readlane_b32 s30, v40, 2 -; GFX11-NEXT: v_readlane_b32 s5, v40, 1 -; GFX11-NEXT: v_readlane_b32 s4, v40, 0 -; GFX11-NEXT: v_readlane_b32 s0, v40, 4 +; GFX11-NEXT: v_readlane_b32 s31, v40, 1 +; GFX11-NEXT: v_readlane_b32 s30, v40, 0 +; GFX11-NEXT: v_readlane_b32 s0, v40, 2 ; GFX11-NEXT: s_or_saveexec_b32 s1, -1 ; GFX11-NEXT: scratch_load_b32 v40, off, s33 ; 4-byte Folded Reload ; GFX11-NEXT: s_mov_b32 exec_lo, s1 @@ -12192,21 +11872,17 @@ define amdgpu_gfx void @test_call_external_void_func_v3i16_inreg() #0 { ; GFX10-SCRATCH-NEXT: scratch_store_dword off, v40, s33 ; 4-byte Folded Spill ; GFX10-SCRATCH-NEXT: s_waitcnt_depctr 0xffe3 ; GFX10-SCRATCH-NEXT: s_mov_b32 exec_lo, s1 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s0, 4 +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s0, 2 +; GFX10-SCRATCH-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x0 +; GFX10-SCRATCH-NEXT: s_mov_b32 s3, external_void_func_v3i16_inreg@abs32@hi +; GFX10-SCRATCH-NEXT: s_mov_b32 s2, external_void_func_v3i16_inreg@abs32@lo ; GFX10-SCRATCH-NEXT: s_add_i32 s32, s32, 16 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s4, 0 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s5, 1 -; GFX10-SCRATCH-NEXT: s_load_dwordx2 s[4:5], s[0:1], 0x0 -; GFX10-SCRATCH-NEXT: s_mov_b32 s1, external_void_func_v3i16_inreg@abs32@hi -; GFX10-SCRATCH-NEXT: s_mov_b32 s0, external_void_func_v3i16_inreg@abs32@lo -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s30, 2 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s31, 3 -; GFX10-SCRATCH-NEXT: s_swappc_b64 s[30:31], s[0:1] -; GFX10-SCRATCH-NEXT: v_readlane_b32 s31, v40, 3 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s30, v40, 2 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s5, v40, 1 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s4, v40, 0 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s0, v40, 4 +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s30, 0 +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s31, 1 +; GFX10-SCRATCH-NEXT: s_swappc_b64 s[30:31], s[2:3] +; GFX10-SCRATCH-NEXT: v_readlane_b32 s31, v40, 1 +; GFX10-SCRATCH-NEXT: v_readlane_b32 s30, v40, 0 +; GFX10-SCRATCH-NEXT: v_readlane_b32 s0, v40, 2 ; GFX10-SCRATCH-NEXT: s_or_saveexec_b32 s1, -1 ; GFX10-SCRATCH-NEXT: scratch_load_dword v40, off, s33 ; 4-byte Folded Reload ; GFX10-SCRATCH-NEXT: s_waitcnt_depctr 0xffe3 @@ -12229,21 +11905,20 @@ define amdgpu_gfx void @test_call_external_void_func_v3f16_inreg() #0 { ; GFX9-NEXT: s_or_saveexec_b64 s[36:37], -1 ; GFX9-NEXT: buffer_store_dword v40, off, s[0:3], s33 ; 4-byte Folded Spill ; GFX9-NEXT: s_mov_b64 exec, s[36:37] -; GFX9-NEXT: v_writelane_b32 v40, s34, 4 -; GFX9-NEXT: v_writelane_b32 v40, s4, 0 -; GFX9-NEXT: v_writelane_b32 v40, s5, 1 -; GFX9-NEXT: s_load_dwordx2 s[4:5], s[34:35], 0x0 -; GFX9-NEXT: v_writelane_b32 v40, s30, 2 -; GFX9-NEXT: s_mov_b32 s35, external_void_func_v3f16_inreg@abs32@hi -; GFX9-NEXT: s_mov_b32 s34, external_void_func_v3f16_inreg@abs32@lo +; GFX9-NEXT: v_writelane_b32 v40, s34, 2 +; GFX9-NEXT: s_load_dwordx2 s[34:35], s[34:35], 0x0 +; GFX9-NEXT: v_writelane_b32 v40, s30, 0 +; GFX9-NEXT: s_mov_b32 s37, external_void_func_v3f16_inreg@abs32@hi +; GFX9-NEXT: s_mov_b32 s36, external_void_func_v3f16_inreg@abs32@lo ; GFX9-NEXT: s_addk_i32 s32, 0x400 -; GFX9-NEXT: v_writelane_b32 v40, s31, 3 -; GFX9-NEXT: s_swappc_b64 s[30:31], s[34:35] -; GFX9-NEXT: v_readlane_b32 s31, v40, 3 -; GFX9-NEXT: v_readlane_b32 s30, v40, 2 -; GFX9-NEXT: v_readlane_b32 s5, v40, 1 -; GFX9-NEXT: v_readlane_b32 s4, v40, 0 -; GFX9-NEXT: v_readlane_b32 s34, v40, 4 +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: s_mov_b32 s1, s35 +; GFX9-NEXT: s_mov_b32 s0, s34 +; GFX9-NEXT: v_writelane_b32 v40, s31, 1 +; GFX9-NEXT: s_swappc_b64 s[30:31], s[36:37] +; GFX9-NEXT: v_readlane_b32 s31, v40, 1 +; GFX9-NEXT: v_readlane_b32 s30, v40, 0 +; GFX9-NEXT: v_readlane_b32 s34, v40, 2 ; GFX9-NEXT: s_or_saveexec_b64 s[36:37], -1 ; GFX9-NEXT: buffer_load_dword v40, off, s[0:3], s33 ; 4-byte Folded Reload ; GFX9-NEXT: s_mov_b64 exec, s[36:37] @@ -12261,21 +11936,20 @@ define amdgpu_gfx void @test_call_external_void_func_v3f16_inreg() #0 { ; GFX10-NEXT: buffer_store_dword v40, off, s[0:3], s33 ; 4-byte Folded Spill ; GFX10-NEXT: s_waitcnt_depctr 0xffe3 ; GFX10-NEXT: s_mov_b32 exec_lo, s35 -; GFX10-NEXT: v_writelane_b32 v40, s34, 4 +; GFX10-NEXT: v_writelane_b32 v40, s34, 2 +; GFX10-NEXT: s_load_dwordx2 s[34:35], s[34:35], 0x0 +; GFX10-NEXT: s_mov_b32 s37, external_void_func_v3f16_inreg@abs32@hi +; GFX10-NEXT: s_mov_b32 s36, external_void_func_v3f16_inreg@abs32@lo ; GFX10-NEXT: s_addk_i32 s32, 0x200 -; GFX10-NEXT: v_writelane_b32 v40, s4, 0 -; GFX10-NEXT: v_writelane_b32 v40, s5, 1 -; GFX10-NEXT: s_load_dwordx2 s[4:5], s[34:35], 0x0 -; GFX10-NEXT: s_mov_b32 s35, external_void_func_v3f16_inreg@abs32@hi -; GFX10-NEXT: s_mov_b32 s34, external_void_func_v3f16_inreg@abs32@lo -; GFX10-NEXT: v_writelane_b32 v40, s30, 2 -; GFX10-NEXT: v_writelane_b32 v40, s31, 3 -; GFX10-NEXT: s_swappc_b64 s[30:31], s[34:35] -; GFX10-NEXT: v_readlane_b32 s31, v40, 3 -; GFX10-NEXT: v_readlane_b32 s30, v40, 2 -; GFX10-NEXT: v_readlane_b32 s5, v40, 1 -; GFX10-NEXT: v_readlane_b32 s4, v40, 0 -; GFX10-NEXT: v_readlane_b32 s34, v40, 4 +; GFX10-NEXT: v_writelane_b32 v40, s30, 0 +; GFX10-NEXT: v_writelane_b32 v40, s31, 1 +; GFX10-NEXT: s_waitcnt lgkmcnt(0) +; GFX10-NEXT: s_mov_b32 s1, s35 +; GFX10-NEXT: s_mov_b32 s0, s34 +; GFX10-NEXT: s_swappc_b64 s[30:31], s[36:37] +; GFX10-NEXT: v_readlane_b32 s31, v40, 1 +; GFX10-NEXT: v_readlane_b32 s30, v40, 0 +; GFX10-NEXT: v_readlane_b32 s34, v40, 2 ; GFX10-NEXT: s_or_saveexec_b32 s35, -1 ; GFX10-NEXT: buffer_load_dword v40, off, s[0:3], s33 ; 4-byte Folded Reload ; GFX10-NEXT: s_waitcnt_depctr 0xffe3 @@ -12293,22 +11967,18 @@ define amdgpu_gfx void @test_call_external_void_func_v3f16_inreg() #0 { ; GFX11-NEXT: s_or_saveexec_b32 s1, -1 ; GFX11-NEXT: scratch_store_b32 off, v40, s33 ; 4-byte Folded Spill ; GFX11-NEXT: s_mov_b32 exec_lo, s1 -; GFX11-NEXT: v_writelane_b32 v40, s0, 4 +; GFX11-NEXT: v_writelane_b32 v40, s0, 2 +; GFX11-NEXT: s_load_b64 s[0:1], s[0:1], 0x0 +; GFX11-NEXT: s_mov_b32 s3, external_void_func_v3f16_inreg@abs32@hi +; GFX11-NEXT: s_mov_b32 s2, external_void_func_v3f16_inreg@abs32@lo ; GFX11-NEXT: s_add_i32 s32, s32, 16 -; GFX11-NEXT: v_writelane_b32 v40, s4, 0 -; GFX11-NEXT: v_writelane_b32 v40, s5, 1 -; GFX11-NEXT: s_load_b64 s[4:5], s[0:1], 0x0 -; GFX11-NEXT: s_mov_b32 s1, external_void_func_v3f16_inreg@abs32@hi -; GFX11-NEXT: s_mov_b32 s0, external_void_func_v3f16_inreg@abs32@lo -; GFX11-NEXT: v_writelane_b32 v40, s30, 2 -; GFX11-NEXT: v_writelane_b32 v40, s31, 3 -; GFX11-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX11-NEXT: v_writelane_b32 v40, s30, 0 +; GFX11-NEXT: v_writelane_b32 v40, s31, 1 +; GFX11-NEXT: s_swappc_b64 s[30:31], s[2:3] ; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_1) -; GFX11-NEXT: v_readlane_b32 s31, v40, 3 -; GFX11-NEXT: v_readlane_b32 s30, v40, 2 -; GFX11-NEXT: v_readlane_b32 s5, v40, 1 -; GFX11-NEXT: v_readlane_b32 s4, v40, 0 -; GFX11-NEXT: v_readlane_b32 s0, v40, 4 +; GFX11-NEXT: v_readlane_b32 s31, v40, 1 +; GFX11-NEXT: v_readlane_b32 s30, v40, 0 +; GFX11-NEXT: v_readlane_b32 s0, v40, 2 ; GFX11-NEXT: s_or_saveexec_b32 s1, -1 ; GFX11-NEXT: scratch_load_b32 v40, off, s33 ; 4-byte Folded Reload ; GFX11-NEXT: s_mov_b32 exec_lo, s1 @@ -12326,21 +11996,17 @@ define amdgpu_gfx void @test_call_external_void_func_v3f16_inreg() #0 { ; GFX10-SCRATCH-NEXT: scratch_store_dword off, v40, s33 ; 4-byte Folded Spill ; GFX10-SCRATCH-NEXT: s_waitcnt_depctr 0xffe3 ; GFX10-SCRATCH-NEXT: s_mov_b32 exec_lo, s1 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s0, 4 +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s0, 2 +; GFX10-SCRATCH-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x0 +; GFX10-SCRATCH-NEXT: s_mov_b32 s3, external_void_func_v3f16_inreg@abs32@hi +; GFX10-SCRATCH-NEXT: s_mov_b32 s2, external_void_func_v3f16_inreg@abs32@lo ; GFX10-SCRATCH-NEXT: s_add_i32 s32, s32, 16 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s4, 0 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s5, 1 -; GFX10-SCRATCH-NEXT: s_load_dwordx2 s[4:5], s[0:1], 0x0 -; GFX10-SCRATCH-NEXT: s_mov_b32 s1, external_void_func_v3f16_inreg@abs32@hi -; GFX10-SCRATCH-NEXT: s_mov_b32 s0, external_void_func_v3f16_inreg@abs32@lo -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s30, 2 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s31, 3 -; GFX10-SCRATCH-NEXT: s_swappc_b64 s[30:31], s[0:1] -; GFX10-SCRATCH-NEXT: v_readlane_b32 s31, v40, 3 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s30, v40, 2 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s5, v40, 1 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s4, v40, 0 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s0, v40, 4 +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s30, 0 +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s31, 1 +; GFX10-SCRATCH-NEXT: s_swappc_b64 s[30:31], s[2:3] +; GFX10-SCRATCH-NEXT: v_readlane_b32 s31, v40, 1 +; GFX10-SCRATCH-NEXT: v_readlane_b32 s30, v40, 0 +; GFX10-SCRATCH-NEXT: v_readlane_b32 s0, v40, 2 ; GFX10-SCRATCH-NEXT: s_or_saveexec_b32 s1, -1 ; GFX10-SCRATCH-NEXT: scratch_load_dword v40, off, s33 ; 4-byte Folded Reload ; GFX10-SCRATCH-NEXT: s_waitcnt_depctr 0xffe3 @@ -12363,22 +12029,18 @@ define amdgpu_gfx void @test_call_external_void_func_v3i16_imm_inreg() #0 { ; GFX9-NEXT: s_or_saveexec_b64 s[36:37], -1 ; GFX9-NEXT: buffer_store_dword v40, off, s[0:3], s33 ; 4-byte Folded Spill ; GFX9-NEXT: s_mov_b64 exec, s[36:37] -; GFX9-NEXT: v_writelane_b32 v40, s34, 4 -; GFX9-NEXT: v_writelane_b32 v40, s4, 0 -; GFX9-NEXT: v_writelane_b32 v40, s5, 1 -; GFX9-NEXT: v_writelane_b32 v40, s30, 2 +; GFX9-NEXT: v_writelane_b32 v40, s34, 2 +; GFX9-NEXT: v_writelane_b32 v40, s30, 0 ; GFX9-NEXT: s_mov_b32 s35, external_void_func_v3i16_inreg@abs32@hi ; GFX9-NEXT: s_mov_b32 s34, external_void_func_v3i16_inreg@abs32@lo -; GFX9-NEXT: s_mov_b32 s4, 0x20001 -; GFX9-NEXT: s_mov_b32 s5, 3 +; GFX9-NEXT: s_mov_b32 s0, 0x20001 +; GFX9-NEXT: s_mov_b32 s1, 3 ; GFX9-NEXT: s_addk_i32 s32, 0x400 -; GFX9-NEXT: v_writelane_b32 v40, s31, 3 +; GFX9-NEXT: v_writelane_b32 v40, s31, 1 ; GFX9-NEXT: s_swappc_b64 s[30:31], s[34:35] -; GFX9-NEXT: v_readlane_b32 s31, v40, 3 -; GFX9-NEXT: v_readlane_b32 s30, v40, 2 -; GFX9-NEXT: v_readlane_b32 s5, v40, 1 -; GFX9-NEXT: v_readlane_b32 s4, v40, 0 -; GFX9-NEXT: v_readlane_b32 s34, v40, 4 +; GFX9-NEXT: v_readlane_b32 s31, v40, 1 +; GFX9-NEXT: v_readlane_b32 s30, v40, 0 +; GFX9-NEXT: v_readlane_b32 s34, v40, 2 ; GFX9-NEXT: s_or_saveexec_b64 s[36:37], -1 ; GFX9-NEXT: buffer_load_dword v40, off, s[0:3], s33 ; 4-byte Folded Reload ; GFX9-NEXT: s_mov_b64 exec, s[36:37] @@ -12396,22 +12058,18 @@ define amdgpu_gfx void @test_call_external_void_func_v3i16_imm_inreg() #0 { ; GFX10-NEXT: buffer_store_dword v40, off, s[0:3], s33 ; 4-byte Folded Spill ; GFX10-NEXT: s_waitcnt_depctr 0xffe3 ; GFX10-NEXT: s_mov_b32 exec_lo, s35 -; GFX10-NEXT: v_writelane_b32 v40, s34, 4 +; GFX10-NEXT: v_writelane_b32 v40, s34, 2 ; GFX10-NEXT: s_mov_b32 s35, external_void_func_v3i16_inreg@abs32@hi ; GFX10-NEXT: s_mov_b32 s34, external_void_func_v3i16_inreg@abs32@lo +; GFX10-NEXT: s_mov_b32 s0, 0x20001 +; GFX10-NEXT: s_mov_b32 s1, 3 +; GFX10-NEXT: v_writelane_b32 v40, s30, 0 ; GFX10-NEXT: s_addk_i32 s32, 0x200 -; GFX10-NEXT: v_writelane_b32 v40, s4, 0 -; GFX10-NEXT: s_mov_b32 s4, 0x20001 -; GFX10-NEXT: v_writelane_b32 v40, s5, 1 -; GFX10-NEXT: s_mov_b32 s5, 3 -; GFX10-NEXT: v_writelane_b32 v40, s30, 2 -; GFX10-NEXT: v_writelane_b32 v40, s31, 3 +; GFX10-NEXT: v_writelane_b32 v40, s31, 1 ; GFX10-NEXT: s_swappc_b64 s[30:31], s[34:35] -; GFX10-NEXT: v_readlane_b32 s31, v40, 3 -; GFX10-NEXT: v_readlane_b32 s30, v40, 2 -; GFX10-NEXT: v_readlane_b32 s5, v40, 1 -; GFX10-NEXT: v_readlane_b32 s4, v40, 0 -; GFX10-NEXT: v_readlane_b32 s34, v40, 4 +; GFX10-NEXT: v_readlane_b32 s31, v40, 1 +; GFX10-NEXT: v_readlane_b32 s30, v40, 0 +; GFX10-NEXT: v_readlane_b32 s34, v40, 2 ; GFX10-NEXT: s_or_saveexec_b32 s35, -1 ; GFX10-NEXT: buffer_load_dword v40, off, s[0:3], s33 ; 4-byte Folded Reload ; GFX10-NEXT: s_waitcnt_depctr 0xffe3 @@ -12429,23 +12087,19 @@ define amdgpu_gfx void @test_call_external_void_func_v3i16_imm_inreg() #0 { ; GFX11-NEXT: s_or_saveexec_b32 s1, -1 ; GFX11-NEXT: scratch_store_b32 off, v40, s33 ; 4-byte Folded Spill ; GFX11-NEXT: s_mov_b32 exec_lo, s1 -; GFX11-NEXT: v_writelane_b32 v40, s0, 4 -; GFX11-NEXT: s_mov_b32 s1, external_void_func_v3i16_inreg@abs32@hi -; GFX11-NEXT: s_mov_b32 s0, external_void_func_v3i16_inreg@abs32@lo +; GFX11-NEXT: v_writelane_b32 v40, s0, 2 +; GFX11-NEXT: s_mov_b32 s3, external_void_func_v3i16_inreg@abs32@hi +; GFX11-NEXT: s_mov_b32 s2, external_void_func_v3i16_inreg@abs32@lo +; GFX11-NEXT: s_mov_b32 s0, 0x20001 +; GFX11-NEXT: s_mov_b32 s1, 3 +; GFX11-NEXT: v_writelane_b32 v40, s30, 0 ; GFX11-NEXT: s_add_i32 s32, s32, 16 -; GFX11-NEXT: v_writelane_b32 v40, s4, 0 -; GFX11-NEXT: s_mov_b32 s4, 0x20001 -; GFX11-NEXT: v_writelane_b32 v40, s5, 1 -; GFX11-NEXT: s_mov_b32 s5, 3 -; GFX11-NEXT: v_writelane_b32 v40, s30, 2 -; GFX11-NEXT: v_writelane_b32 v40, s31, 3 -; GFX11-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX11-NEXT: v_writelane_b32 v40, s31, 1 +; GFX11-NEXT: s_swappc_b64 s[30:31], s[2:3] ; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_1) -; GFX11-NEXT: v_readlane_b32 s31, v40, 3 -; GFX11-NEXT: v_readlane_b32 s30, v40, 2 -; GFX11-NEXT: v_readlane_b32 s5, v40, 1 -; GFX11-NEXT: v_readlane_b32 s4, v40, 0 -; GFX11-NEXT: v_readlane_b32 s0, v40, 4 +; GFX11-NEXT: v_readlane_b32 s31, v40, 1 +; GFX11-NEXT: v_readlane_b32 s30, v40, 0 +; GFX11-NEXT: v_readlane_b32 s0, v40, 2 ; GFX11-NEXT: s_or_saveexec_b32 s1, -1 ; GFX11-NEXT: scratch_load_b32 v40, off, s33 ; 4-byte Folded Reload ; GFX11-NEXT: s_mov_b32 exec_lo, s1 @@ -12463,22 +12117,18 @@ define amdgpu_gfx void @test_call_external_void_func_v3i16_imm_inreg() #0 { ; GFX10-SCRATCH-NEXT: scratch_store_dword off, v40, s33 ; 4-byte Folded Spill ; GFX10-SCRATCH-NEXT: s_waitcnt_depctr 0xffe3 ; GFX10-SCRATCH-NEXT: s_mov_b32 exec_lo, s1 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s0, 4 -; GFX10-SCRATCH-NEXT: s_mov_b32 s1, external_void_func_v3i16_inreg@abs32@hi -; GFX10-SCRATCH-NEXT: s_mov_b32 s0, external_void_func_v3i16_inreg@abs32@lo +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s0, 2 +; GFX10-SCRATCH-NEXT: s_mov_b32 s3, external_void_func_v3i16_inreg@abs32@hi +; GFX10-SCRATCH-NEXT: s_mov_b32 s2, external_void_func_v3i16_inreg@abs32@lo +; GFX10-SCRATCH-NEXT: s_mov_b32 s0, 0x20001 +; GFX10-SCRATCH-NEXT: s_mov_b32 s1, 3 +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s30, 0 ; GFX10-SCRATCH-NEXT: s_add_i32 s32, s32, 16 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s4, 0 -; GFX10-SCRATCH-NEXT: s_mov_b32 s4, 0x20001 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s5, 1 -; GFX10-SCRATCH-NEXT: s_mov_b32 s5, 3 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s30, 2 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s31, 3 -; GFX10-SCRATCH-NEXT: s_swappc_b64 s[30:31], s[0:1] -; GFX10-SCRATCH-NEXT: v_readlane_b32 s31, v40, 3 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s30, v40, 2 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s5, v40, 1 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s4, v40, 0 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s0, v40, 4 +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s31, 1 +; GFX10-SCRATCH-NEXT: s_swappc_b64 s[30:31], s[2:3] +; GFX10-SCRATCH-NEXT: v_readlane_b32 s31, v40, 1 +; GFX10-SCRATCH-NEXT: v_readlane_b32 s30, v40, 0 +; GFX10-SCRATCH-NEXT: v_readlane_b32 s0, v40, 2 ; GFX10-SCRATCH-NEXT: s_or_saveexec_b32 s1, -1 ; GFX10-SCRATCH-NEXT: scratch_load_dword v40, off, s33 ; 4-byte Folded Reload ; GFX10-SCRATCH-NEXT: s_waitcnt_depctr 0xffe3 @@ -12500,22 +12150,18 @@ define amdgpu_gfx void @test_call_external_void_func_v3f16_imm_inreg() #0 { ; GFX9-NEXT: s_or_saveexec_b64 s[36:37], -1 ; GFX9-NEXT: buffer_store_dword v40, off, s[0:3], s33 ; 4-byte Folded Spill ; GFX9-NEXT: s_mov_b64 exec, s[36:37] -; GFX9-NEXT: v_writelane_b32 v40, s34, 4 -; GFX9-NEXT: v_writelane_b32 v40, s4, 0 -; GFX9-NEXT: v_writelane_b32 v40, s5, 1 -; GFX9-NEXT: v_writelane_b32 v40, s30, 2 +; GFX9-NEXT: v_writelane_b32 v40, s34, 2 +; GFX9-NEXT: v_writelane_b32 v40, s30, 0 ; GFX9-NEXT: s_mov_b32 s35, external_void_func_v3f16_inreg@abs32@hi ; GFX9-NEXT: s_mov_b32 s34, external_void_func_v3f16_inreg@abs32@lo -; GFX9-NEXT: s_mov_b32 s4, 0x40003c00 -; GFX9-NEXT: s_movk_i32 s5, 0x4400 +; GFX9-NEXT: s_mov_b32 s0, 0x40003c00 +; GFX9-NEXT: s_movk_i32 s1, 0x4400 ; GFX9-NEXT: s_addk_i32 s32, 0x400 -; GFX9-NEXT: v_writelane_b32 v40, s31, 3 +; GFX9-NEXT: v_writelane_b32 v40, s31, 1 ; GFX9-NEXT: s_swappc_b64 s[30:31], s[34:35] -; GFX9-NEXT: v_readlane_b32 s31, v40, 3 -; GFX9-NEXT: v_readlane_b32 s30, v40, 2 -; GFX9-NEXT: v_readlane_b32 s5, v40, 1 -; GFX9-NEXT: v_readlane_b32 s4, v40, 0 -; GFX9-NEXT: v_readlane_b32 s34, v40, 4 +; GFX9-NEXT: v_readlane_b32 s31, v40, 1 +; GFX9-NEXT: v_readlane_b32 s30, v40, 0 +; GFX9-NEXT: v_readlane_b32 s34, v40, 2 ; GFX9-NEXT: s_or_saveexec_b64 s[36:37], -1 ; GFX9-NEXT: buffer_load_dword v40, off, s[0:3], s33 ; 4-byte Folded Reload ; GFX9-NEXT: s_mov_b64 exec, s[36:37] @@ -12533,22 +12179,18 @@ define amdgpu_gfx void @test_call_external_void_func_v3f16_imm_inreg() #0 { ; GFX10-NEXT: buffer_store_dword v40, off, s[0:3], s33 ; 4-byte Folded Spill ; GFX10-NEXT: s_waitcnt_depctr 0xffe3 ; GFX10-NEXT: s_mov_b32 exec_lo, s35 -; GFX10-NEXT: v_writelane_b32 v40, s34, 4 +; GFX10-NEXT: v_writelane_b32 v40, s34, 2 ; GFX10-NEXT: s_mov_b32 s35, external_void_func_v3f16_inreg@abs32@hi ; GFX10-NEXT: s_mov_b32 s34, external_void_func_v3f16_inreg@abs32@lo +; GFX10-NEXT: s_mov_b32 s0, 0x40003c00 +; GFX10-NEXT: s_movk_i32 s1, 0x4400 +; GFX10-NEXT: v_writelane_b32 v40, s30, 0 ; GFX10-NEXT: s_addk_i32 s32, 0x200 -; GFX10-NEXT: v_writelane_b32 v40, s4, 0 -; GFX10-NEXT: s_mov_b32 s4, 0x40003c00 -; GFX10-NEXT: v_writelane_b32 v40, s5, 1 -; GFX10-NEXT: s_movk_i32 s5, 0x4400 -; GFX10-NEXT: v_writelane_b32 v40, s30, 2 -; GFX10-NEXT: v_writelane_b32 v40, s31, 3 +; GFX10-NEXT: v_writelane_b32 v40, s31, 1 ; GFX10-NEXT: s_swappc_b64 s[30:31], s[34:35] -; GFX10-NEXT: v_readlane_b32 s31, v40, 3 -; GFX10-NEXT: v_readlane_b32 s30, v40, 2 -; GFX10-NEXT: v_readlane_b32 s5, v40, 1 -; GFX10-NEXT: v_readlane_b32 s4, v40, 0 -; GFX10-NEXT: v_readlane_b32 s34, v40, 4 +; GFX10-NEXT: v_readlane_b32 s31, v40, 1 +; GFX10-NEXT: v_readlane_b32 s30, v40, 0 +; GFX10-NEXT: v_readlane_b32 s34, v40, 2 ; GFX10-NEXT: s_or_saveexec_b32 s35, -1 ; GFX10-NEXT: buffer_load_dword v40, off, s[0:3], s33 ; 4-byte Folded Reload ; GFX10-NEXT: s_waitcnt_depctr 0xffe3 @@ -12566,23 +12208,19 @@ define amdgpu_gfx void @test_call_external_void_func_v3f16_imm_inreg() #0 { ; GFX11-NEXT: s_or_saveexec_b32 s1, -1 ; GFX11-NEXT: scratch_store_b32 off, v40, s33 ; 4-byte Folded Spill ; GFX11-NEXT: s_mov_b32 exec_lo, s1 -; GFX11-NEXT: v_writelane_b32 v40, s0, 4 -; GFX11-NEXT: s_mov_b32 s1, external_void_func_v3f16_inreg@abs32@hi -; GFX11-NEXT: s_mov_b32 s0, external_void_func_v3f16_inreg@abs32@lo +; GFX11-NEXT: v_writelane_b32 v40, s0, 2 +; GFX11-NEXT: s_mov_b32 s3, external_void_func_v3f16_inreg@abs32@hi +; GFX11-NEXT: s_mov_b32 s2, external_void_func_v3f16_inreg@abs32@lo +; GFX11-NEXT: s_mov_b32 s0, 0x40003c00 +; GFX11-NEXT: s_movk_i32 s1, 0x4400 +; GFX11-NEXT: v_writelane_b32 v40, s30, 0 ; GFX11-NEXT: s_add_i32 s32, s32, 16 -; GFX11-NEXT: v_writelane_b32 v40, s4, 0 -; GFX11-NEXT: s_mov_b32 s4, 0x40003c00 -; GFX11-NEXT: v_writelane_b32 v40, s5, 1 -; GFX11-NEXT: s_movk_i32 s5, 0x4400 -; GFX11-NEXT: v_writelane_b32 v40, s30, 2 -; GFX11-NEXT: v_writelane_b32 v40, s31, 3 -; GFX11-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX11-NEXT: v_writelane_b32 v40, s31, 1 +; GFX11-NEXT: s_swappc_b64 s[30:31], s[2:3] ; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_1) -; GFX11-NEXT: v_readlane_b32 s31, v40, 3 -; GFX11-NEXT: v_readlane_b32 s30, v40, 2 -; GFX11-NEXT: v_readlane_b32 s5, v40, 1 -; GFX11-NEXT: v_readlane_b32 s4, v40, 0 -; GFX11-NEXT: v_readlane_b32 s0, v40, 4 +; GFX11-NEXT: v_readlane_b32 s31, v40, 1 +; GFX11-NEXT: v_readlane_b32 s30, v40, 0 +; GFX11-NEXT: v_readlane_b32 s0, v40, 2 ; GFX11-NEXT: s_or_saveexec_b32 s1, -1 ; GFX11-NEXT: scratch_load_b32 v40, off, s33 ; 4-byte Folded Reload ; GFX11-NEXT: s_mov_b32 exec_lo, s1 @@ -12600,22 +12238,18 @@ define amdgpu_gfx void @test_call_external_void_func_v3f16_imm_inreg() #0 { ; GFX10-SCRATCH-NEXT: scratch_store_dword off, v40, s33 ; 4-byte Folded Spill ; GFX10-SCRATCH-NEXT: s_waitcnt_depctr 0xffe3 ; GFX10-SCRATCH-NEXT: s_mov_b32 exec_lo, s1 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s0, 4 -; GFX10-SCRATCH-NEXT: s_mov_b32 s1, external_void_func_v3f16_inreg@abs32@hi -; GFX10-SCRATCH-NEXT: s_mov_b32 s0, external_void_func_v3f16_inreg@abs32@lo +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s0, 2 +; GFX10-SCRATCH-NEXT: s_mov_b32 s3, external_void_func_v3f16_inreg@abs32@hi +; GFX10-SCRATCH-NEXT: s_mov_b32 s2, external_void_func_v3f16_inreg@abs32@lo +; GFX10-SCRATCH-NEXT: s_mov_b32 s0, 0x40003c00 +; GFX10-SCRATCH-NEXT: s_movk_i32 s1, 0x4400 +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s30, 0 ; GFX10-SCRATCH-NEXT: s_add_i32 s32, s32, 16 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s4, 0 -; GFX10-SCRATCH-NEXT: s_mov_b32 s4, 0x40003c00 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s5, 1 -; GFX10-SCRATCH-NEXT: s_movk_i32 s5, 0x4400 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s30, 2 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s31, 3 -; GFX10-SCRATCH-NEXT: s_swappc_b64 s[30:31], s[0:1] -; GFX10-SCRATCH-NEXT: v_readlane_b32 s31, v40, 3 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s30, v40, 2 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s5, v40, 1 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s4, v40, 0 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s0, v40, 4 +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s31, 1 +; GFX10-SCRATCH-NEXT: s_swappc_b64 s[30:31], s[2:3] +; GFX10-SCRATCH-NEXT: v_readlane_b32 s31, v40, 1 +; GFX10-SCRATCH-NEXT: v_readlane_b32 s30, v40, 0 +; GFX10-SCRATCH-NEXT: v_readlane_b32 s0, v40, 2 ; GFX10-SCRATCH-NEXT: s_or_saveexec_b32 s1, -1 ; GFX10-SCRATCH-NEXT: scratch_load_dword v40, off, s33 ; 4-byte Folded Reload ; GFX10-SCRATCH-NEXT: s_waitcnt_depctr 0xffe3 @@ -12637,21 +12271,20 @@ define amdgpu_gfx void @test_call_external_void_func_v4i16_inreg() #0 { ; GFX9-NEXT: s_or_saveexec_b64 s[36:37], -1 ; GFX9-NEXT: buffer_store_dword v40, off, s[0:3], s33 ; 4-byte Folded Spill ; GFX9-NEXT: s_mov_b64 exec, s[36:37] -; GFX9-NEXT: v_writelane_b32 v40, s34, 4 -; GFX9-NEXT: v_writelane_b32 v40, s4, 0 -; GFX9-NEXT: v_writelane_b32 v40, s5, 1 -; GFX9-NEXT: s_load_dwordx2 s[4:5], s[34:35], 0x0 -; GFX9-NEXT: v_writelane_b32 v40, s30, 2 -; GFX9-NEXT: s_mov_b32 s35, external_void_func_v4i16_inreg@abs32@hi -; GFX9-NEXT: s_mov_b32 s34, external_void_func_v4i16_inreg@abs32@lo +; GFX9-NEXT: v_writelane_b32 v40, s34, 2 +; GFX9-NEXT: s_load_dwordx2 s[34:35], s[34:35], 0x0 +; GFX9-NEXT: v_writelane_b32 v40, s30, 0 +; GFX9-NEXT: s_mov_b32 s37, external_void_func_v4i16_inreg@abs32@hi +; GFX9-NEXT: s_mov_b32 s36, external_void_func_v4i16_inreg@abs32@lo ; GFX9-NEXT: s_addk_i32 s32, 0x400 -; GFX9-NEXT: v_writelane_b32 v40, s31, 3 -; GFX9-NEXT: s_swappc_b64 s[30:31], s[34:35] -; GFX9-NEXT: v_readlane_b32 s31, v40, 3 -; GFX9-NEXT: v_readlane_b32 s30, v40, 2 -; GFX9-NEXT: v_readlane_b32 s5, v40, 1 -; GFX9-NEXT: v_readlane_b32 s4, v40, 0 -; GFX9-NEXT: v_readlane_b32 s34, v40, 4 +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: s_mov_b32 s0, s34 +; GFX9-NEXT: s_mov_b32 s1, s35 +; GFX9-NEXT: v_writelane_b32 v40, s31, 1 +; GFX9-NEXT: s_swappc_b64 s[30:31], s[36:37] +; GFX9-NEXT: v_readlane_b32 s31, v40, 1 +; GFX9-NEXT: v_readlane_b32 s30, v40, 0 +; GFX9-NEXT: v_readlane_b32 s34, v40, 2 ; GFX9-NEXT: s_or_saveexec_b64 s[36:37], -1 ; GFX9-NEXT: buffer_load_dword v40, off, s[0:3], s33 ; 4-byte Folded Reload ; GFX9-NEXT: s_mov_b64 exec, s[36:37] @@ -12669,21 +12302,20 @@ define amdgpu_gfx void @test_call_external_void_func_v4i16_inreg() #0 { ; GFX10-NEXT: buffer_store_dword v40, off, s[0:3], s33 ; 4-byte Folded Spill ; GFX10-NEXT: s_waitcnt_depctr 0xffe3 ; GFX10-NEXT: s_mov_b32 exec_lo, s35 -; GFX10-NEXT: v_writelane_b32 v40, s34, 4 +; GFX10-NEXT: v_writelane_b32 v40, s34, 2 +; GFX10-NEXT: s_load_dwordx2 s[34:35], s[34:35], 0x0 +; GFX10-NEXT: s_mov_b32 s37, external_void_func_v4i16_inreg@abs32@hi +; GFX10-NEXT: s_mov_b32 s36, external_void_func_v4i16_inreg@abs32@lo ; GFX10-NEXT: s_addk_i32 s32, 0x200 -; GFX10-NEXT: v_writelane_b32 v40, s4, 0 -; GFX10-NEXT: v_writelane_b32 v40, s5, 1 -; GFX10-NEXT: s_load_dwordx2 s[4:5], s[34:35], 0x0 -; GFX10-NEXT: s_mov_b32 s35, external_void_func_v4i16_inreg@abs32@hi -; GFX10-NEXT: s_mov_b32 s34, external_void_func_v4i16_inreg@abs32@lo -; GFX10-NEXT: v_writelane_b32 v40, s30, 2 -; GFX10-NEXT: v_writelane_b32 v40, s31, 3 -; GFX10-NEXT: s_swappc_b64 s[30:31], s[34:35] -; GFX10-NEXT: v_readlane_b32 s31, v40, 3 -; GFX10-NEXT: v_readlane_b32 s30, v40, 2 -; GFX10-NEXT: v_readlane_b32 s5, v40, 1 -; GFX10-NEXT: v_readlane_b32 s4, v40, 0 -; GFX10-NEXT: v_readlane_b32 s34, v40, 4 +; GFX10-NEXT: v_writelane_b32 v40, s30, 0 +; GFX10-NEXT: v_writelane_b32 v40, s31, 1 +; GFX10-NEXT: s_waitcnt lgkmcnt(0) +; GFX10-NEXT: s_mov_b32 s0, s34 +; GFX10-NEXT: s_mov_b32 s1, s35 +; GFX10-NEXT: s_swappc_b64 s[30:31], s[36:37] +; GFX10-NEXT: v_readlane_b32 s31, v40, 1 +; GFX10-NEXT: v_readlane_b32 s30, v40, 0 +; GFX10-NEXT: v_readlane_b32 s34, v40, 2 ; GFX10-NEXT: s_or_saveexec_b32 s35, -1 ; GFX10-NEXT: buffer_load_dword v40, off, s[0:3], s33 ; 4-byte Folded Reload ; GFX10-NEXT: s_waitcnt_depctr 0xffe3 @@ -12701,22 +12333,18 @@ define amdgpu_gfx void @test_call_external_void_func_v4i16_inreg() #0 { ; GFX11-NEXT: s_or_saveexec_b32 s1, -1 ; GFX11-NEXT: scratch_store_b32 off, v40, s33 ; 4-byte Folded Spill ; GFX11-NEXT: s_mov_b32 exec_lo, s1 -; GFX11-NEXT: v_writelane_b32 v40, s0, 4 +; GFX11-NEXT: v_writelane_b32 v40, s0, 2 +; GFX11-NEXT: s_load_b64 s[0:1], s[0:1], 0x0 +; GFX11-NEXT: s_mov_b32 s3, external_void_func_v4i16_inreg@abs32@hi +; GFX11-NEXT: s_mov_b32 s2, external_void_func_v4i16_inreg@abs32@lo ; GFX11-NEXT: s_add_i32 s32, s32, 16 -; GFX11-NEXT: v_writelane_b32 v40, s4, 0 -; GFX11-NEXT: v_writelane_b32 v40, s5, 1 -; GFX11-NEXT: s_load_b64 s[4:5], s[0:1], 0x0 -; GFX11-NEXT: s_mov_b32 s1, external_void_func_v4i16_inreg@abs32@hi -; GFX11-NEXT: s_mov_b32 s0, external_void_func_v4i16_inreg@abs32@lo -; GFX11-NEXT: v_writelane_b32 v40, s30, 2 -; GFX11-NEXT: v_writelane_b32 v40, s31, 3 -; GFX11-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX11-NEXT: v_writelane_b32 v40, s30, 0 +; GFX11-NEXT: v_writelane_b32 v40, s31, 1 +; GFX11-NEXT: s_swappc_b64 s[30:31], s[2:3] ; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_1) -; GFX11-NEXT: v_readlane_b32 s31, v40, 3 -; GFX11-NEXT: v_readlane_b32 s30, v40, 2 -; GFX11-NEXT: v_readlane_b32 s5, v40, 1 -; GFX11-NEXT: v_readlane_b32 s4, v40, 0 -; GFX11-NEXT: v_readlane_b32 s0, v40, 4 +; GFX11-NEXT: v_readlane_b32 s31, v40, 1 +; GFX11-NEXT: v_readlane_b32 s30, v40, 0 +; GFX11-NEXT: v_readlane_b32 s0, v40, 2 ; GFX11-NEXT: s_or_saveexec_b32 s1, -1 ; GFX11-NEXT: scratch_load_b32 v40, off, s33 ; 4-byte Folded Reload ; GFX11-NEXT: s_mov_b32 exec_lo, s1 @@ -12734,21 +12362,17 @@ define amdgpu_gfx void @test_call_external_void_func_v4i16_inreg() #0 { ; GFX10-SCRATCH-NEXT: scratch_store_dword off, v40, s33 ; 4-byte Folded Spill ; GFX10-SCRATCH-NEXT: s_waitcnt_depctr 0xffe3 ; GFX10-SCRATCH-NEXT: s_mov_b32 exec_lo, s1 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s0, 4 +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s0, 2 +; GFX10-SCRATCH-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x0 +; GFX10-SCRATCH-NEXT: s_mov_b32 s3, external_void_func_v4i16_inreg@abs32@hi +; GFX10-SCRATCH-NEXT: s_mov_b32 s2, external_void_func_v4i16_inreg@abs32@lo ; GFX10-SCRATCH-NEXT: s_add_i32 s32, s32, 16 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s4, 0 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s5, 1 -; GFX10-SCRATCH-NEXT: s_load_dwordx2 s[4:5], s[0:1], 0x0 -; GFX10-SCRATCH-NEXT: s_mov_b32 s1, external_void_func_v4i16_inreg@abs32@hi -; GFX10-SCRATCH-NEXT: s_mov_b32 s0, external_void_func_v4i16_inreg@abs32@lo -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s30, 2 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s31, 3 -; GFX10-SCRATCH-NEXT: s_swappc_b64 s[30:31], s[0:1] -; GFX10-SCRATCH-NEXT: v_readlane_b32 s31, v40, 3 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s30, v40, 2 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s5, v40, 1 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s4, v40, 0 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s0, v40, 4 +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s30, 0 +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s31, 1 +; GFX10-SCRATCH-NEXT: s_swappc_b64 s[30:31], s[2:3] +; GFX10-SCRATCH-NEXT: v_readlane_b32 s31, v40, 1 +; GFX10-SCRATCH-NEXT: v_readlane_b32 s30, v40, 0 +; GFX10-SCRATCH-NEXT: v_readlane_b32 s0, v40, 2 ; GFX10-SCRATCH-NEXT: s_or_saveexec_b32 s1, -1 ; GFX10-SCRATCH-NEXT: scratch_load_dword v40, off, s33 ; 4-byte Folded Reload ; GFX10-SCRATCH-NEXT: s_waitcnt_depctr 0xffe3 @@ -12771,22 +12395,18 @@ define amdgpu_gfx void @test_call_external_void_func_v4i16_imm_inreg() #0 { ; GFX9-NEXT: s_or_saveexec_b64 s[36:37], -1 ; GFX9-NEXT: buffer_store_dword v40, off, s[0:3], s33 ; 4-byte Folded Spill ; GFX9-NEXT: s_mov_b64 exec, s[36:37] -; GFX9-NEXT: v_writelane_b32 v40, s34, 4 -; GFX9-NEXT: v_writelane_b32 v40, s4, 0 -; GFX9-NEXT: v_writelane_b32 v40, s5, 1 -; GFX9-NEXT: v_writelane_b32 v40, s30, 2 +; GFX9-NEXT: v_writelane_b32 v40, s34, 2 +; GFX9-NEXT: v_writelane_b32 v40, s30, 0 ; GFX9-NEXT: s_mov_b32 s35, external_void_func_v4i16_inreg@abs32@hi ; GFX9-NEXT: s_mov_b32 s34, external_void_func_v4i16_inreg@abs32@lo -; GFX9-NEXT: s_mov_b32 s4, 0x20001 -; GFX9-NEXT: s_mov_b32 s5, 0x40003 +; GFX9-NEXT: s_mov_b32 s0, 0x20001 +; GFX9-NEXT: s_mov_b32 s1, 0x40003 ; GFX9-NEXT: s_addk_i32 s32, 0x400 -; GFX9-NEXT: v_writelane_b32 v40, s31, 3 +; GFX9-NEXT: v_writelane_b32 v40, s31, 1 ; GFX9-NEXT: s_swappc_b64 s[30:31], s[34:35] -; GFX9-NEXT: v_readlane_b32 s31, v40, 3 -; GFX9-NEXT: v_readlane_b32 s30, v40, 2 -; GFX9-NEXT: v_readlane_b32 s5, v40, 1 -; GFX9-NEXT: v_readlane_b32 s4, v40, 0 -; GFX9-NEXT: v_readlane_b32 s34, v40, 4 +; GFX9-NEXT: v_readlane_b32 s31, v40, 1 +; GFX9-NEXT: v_readlane_b32 s30, v40, 0 +; GFX9-NEXT: v_readlane_b32 s34, v40, 2 ; GFX9-NEXT: s_or_saveexec_b64 s[36:37], -1 ; GFX9-NEXT: buffer_load_dword v40, off, s[0:3], s33 ; 4-byte Folded Reload ; GFX9-NEXT: s_mov_b64 exec, s[36:37] @@ -12804,22 +12424,18 @@ define amdgpu_gfx void @test_call_external_void_func_v4i16_imm_inreg() #0 { ; GFX10-NEXT: buffer_store_dword v40, off, s[0:3], s33 ; 4-byte Folded Spill ; GFX10-NEXT: s_waitcnt_depctr 0xffe3 ; GFX10-NEXT: s_mov_b32 exec_lo, s35 -; GFX10-NEXT: v_writelane_b32 v40, s34, 4 +; GFX10-NEXT: v_writelane_b32 v40, s34, 2 ; GFX10-NEXT: s_mov_b32 s35, external_void_func_v4i16_inreg@abs32@hi ; GFX10-NEXT: s_mov_b32 s34, external_void_func_v4i16_inreg@abs32@lo +; GFX10-NEXT: s_mov_b32 s0, 0x20001 +; GFX10-NEXT: s_mov_b32 s1, 0x40003 +; GFX10-NEXT: v_writelane_b32 v40, s30, 0 ; GFX10-NEXT: s_addk_i32 s32, 0x200 -; GFX10-NEXT: v_writelane_b32 v40, s4, 0 -; GFX10-NEXT: s_mov_b32 s4, 0x20001 -; GFX10-NEXT: v_writelane_b32 v40, s5, 1 -; GFX10-NEXT: s_mov_b32 s5, 0x40003 -; GFX10-NEXT: v_writelane_b32 v40, s30, 2 -; GFX10-NEXT: v_writelane_b32 v40, s31, 3 +; GFX10-NEXT: v_writelane_b32 v40, s31, 1 ; GFX10-NEXT: s_swappc_b64 s[30:31], s[34:35] -; GFX10-NEXT: v_readlane_b32 s31, v40, 3 -; GFX10-NEXT: v_readlane_b32 s30, v40, 2 -; GFX10-NEXT: v_readlane_b32 s5, v40, 1 -; GFX10-NEXT: v_readlane_b32 s4, v40, 0 -; GFX10-NEXT: v_readlane_b32 s34, v40, 4 +; GFX10-NEXT: v_readlane_b32 s31, v40, 1 +; GFX10-NEXT: v_readlane_b32 s30, v40, 0 +; GFX10-NEXT: v_readlane_b32 s34, v40, 2 ; GFX10-NEXT: s_or_saveexec_b32 s35, -1 ; GFX10-NEXT: buffer_load_dword v40, off, s[0:3], s33 ; 4-byte Folded Reload ; GFX10-NEXT: s_waitcnt_depctr 0xffe3 @@ -12837,23 +12453,19 @@ define amdgpu_gfx void @test_call_external_void_func_v4i16_imm_inreg() #0 { ; GFX11-NEXT: s_or_saveexec_b32 s1, -1 ; GFX11-NEXT: scratch_store_b32 off, v40, s33 ; 4-byte Folded Spill ; GFX11-NEXT: s_mov_b32 exec_lo, s1 -; GFX11-NEXT: v_writelane_b32 v40, s0, 4 -; GFX11-NEXT: s_mov_b32 s1, external_void_func_v4i16_inreg@abs32@hi -; GFX11-NEXT: s_mov_b32 s0, external_void_func_v4i16_inreg@abs32@lo +; GFX11-NEXT: v_writelane_b32 v40, s0, 2 +; GFX11-NEXT: s_mov_b32 s3, external_void_func_v4i16_inreg@abs32@hi +; GFX11-NEXT: s_mov_b32 s2, external_void_func_v4i16_inreg@abs32@lo +; GFX11-NEXT: s_mov_b32 s0, 0x20001 +; GFX11-NEXT: s_mov_b32 s1, 0x40003 +; GFX11-NEXT: v_writelane_b32 v40, s30, 0 ; GFX11-NEXT: s_add_i32 s32, s32, 16 -; GFX11-NEXT: v_writelane_b32 v40, s4, 0 -; GFX11-NEXT: s_mov_b32 s4, 0x20001 -; GFX11-NEXT: v_writelane_b32 v40, s5, 1 -; GFX11-NEXT: s_mov_b32 s5, 0x40003 -; GFX11-NEXT: v_writelane_b32 v40, s30, 2 -; GFX11-NEXT: v_writelane_b32 v40, s31, 3 -; GFX11-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX11-NEXT: v_writelane_b32 v40, s31, 1 +; GFX11-NEXT: s_swappc_b64 s[30:31], s[2:3] ; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_1) -; GFX11-NEXT: v_readlane_b32 s31, v40, 3 -; GFX11-NEXT: v_readlane_b32 s30, v40, 2 -; GFX11-NEXT: v_readlane_b32 s5, v40, 1 -; GFX11-NEXT: v_readlane_b32 s4, v40, 0 -; GFX11-NEXT: v_readlane_b32 s0, v40, 4 +; GFX11-NEXT: v_readlane_b32 s31, v40, 1 +; GFX11-NEXT: v_readlane_b32 s30, v40, 0 +; GFX11-NEXT: v_readlane_b32 s0, v40, 2 ; GFX11-NEXT: s_or_saveexec_b32 s1, -1 ; GFX11-NEXT: scratch_load_b32 v40, off, s33 ; 4-byte Folded Reload ; GFX11-NEXT: s_mov_b32 exec_lo, s1 @@ -12871,22 +12483,18 @@ define amdgpu_gfx void @test_call_external_void_func_v4i16_imm_inreg() #0 { ; GFX10-SCRATCH-NEXT: scratch_store_dword off, v40, s33 ; 4-byte Folded Spill ; GFX10-SCRATCH-NEXT: s_waitcnt_depctr 0xffe3 ; GFX10-SCRATCH-NEXT: s_mov_b32 exec_lo, s1 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s0, 4 -; GFX10-SCRATCH-NEXT: s_mov_b32 s1, external_void_func_v4i16_inreg@abs32@hi -; GFX10-SCRATCH-NEXT: s_mov_b32 s0, external_void_func_v4i16_inreg@abs32@lo +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s0, 2 +; GFX10-SCRATCH-NEXT: s_mov_b32 s3, external_void_func_v4i16_inreg@abs32@hi +; GFX10-SCRATCH-NEXT: s_mov_b32 s2, external_void_func_v4i16_inreg@abs32@lo +; GFX10-SCRATCH-NEXT: s_mov_b32 s0, 0x20001 +; GFX10-SCRATCH-NEXT: s_mov_b32 s1, 0x40003 +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s30, 0 ; GFX10-SCRATCH-NEXT: s_add_i32 s32, s32, 16 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s4, 0 -; GFX10-SCRATCH-NEXT: s_mov_b32 s4, 0x20001 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s5, 1 -; GFX10-SCRATCH-NEXT: s_mov_b32 s5, 0x40003 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s30, 2 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s31, 3 -; GFX10-SCRATCH-NEXT: s_swappc_b64 s[30:31], s[0:1] -; GFX10-SCRATCH-NEXT: v_readlane_b32 s31, v40, 3 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s30, v40, 2 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s5, v40, 1 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s4, v40, 0 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s0, v40, 4 +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s31, 1 +; GFX10-SCRATCH-NEXT: s_swappc_b64 s[30:31], s[2:3] +; GFX10-SCRATCH-NEXT: v_readlane_b32 s31, v40, 1 +; GFX10-SCRATCH-NEXT: v_readlane_b32 s30, v40, 0 +; GFX10-SCRATCH-NEXT: v_readlane_b32 s0, v40, 2 ; GFX10-SCRATCH-NEXT: s_or_saveexec_b32 s1, -1 ; GFX10-SCRATCH-NEXT: scratch_load_dword v40, off, s33 ; 4-byte Folded Reload ; GFX10-SCRATCH-NEXT: s_waitcnt_depctr 0xffe3 @@ -12908,19 +12516,17 @@ define amdgpu_gfx void @test_call_external_void_func_v2f16_inreg() #0 { ; GFX9-NEXT: s_or_saveexec_b64 s[36:37], -1 ; GFX9-NEXT: buffer_store_dword v40, off, s[0:3], s33 ; 4-byte Folded Spill ; GFX9-NEXT: s_mov_b64 exec, s[36:37] -; GFX9-NEXT: v_writelane_b32 v40, s34, 3 -; GFX9-NEXT: v_writelane_b32 v40, s4, 0 -; GFX9-NEXT: s_load_dword s4, s[34:35], 0x0 -; GFX9-NEXT: v_writelane_b32 v40, s30, 1 +; GFX9-NEXT: s_load_dword s0, s[34:35], 0x0 +; GFX9-NEXT: v_writelane_b32 v40, s34, 2 +; GFX9-NEXT: v_writelane_b32 v40, s30, 0 ; GFX9-NEXT: s_mov_b32 s35, external_void_func_v2f16_inreg@abs32@hi ; GFX9-NEXT: s_mov_b32 s34, external_void_func_v2f16_inreg@abs32@lo ; GFX9-NEXT: s_addk_i32 s32, 0x400 -; GFX9-NEXT: v_writelane_b32 v40, s31, 2 +; GFX9-NEXT: v_writelane_b32 v40, s31, 1 ; GFX9-NEXT: s_swappc_b64 s[30:31], s[34:35] -; GFX9-NEXT: v_readlane_b32 s31, v40, 2 -; GFX9-NEXT: v_readlane_b32 s30, v40, 1 -; GFX9-NEXT: v_readlane_b32 s4, v40, 0 -; GFX9-NEXT: v_readlane_b32 s34, v40, 3 +; GFX9-NEXT: v_readlane_b32 s31, v40, 1 +; GFX9-NEXT: v_readlane_b32 s30, v40, 0 +; GFX9-NEXT: v_readlane_b32 s34, v40, 2 ; GFX9-NEXT: s_or_saveexec_b64 s[36:37], -1 ; GFX9-NEXT: buffer_load_dword v40, off, s[0:3], s33 ; 4-byte Folded Reload ; GFX9-NEXT: s_mov_b64 exec, s[36:37] @@ -12938,19 +12544,17 @@ define amdgpu_gfx void @test_call_external_void_func_v2f16_inreg() #0 { ; GFX10-NEXT: buffer_store_dword v40, off, s[0:3], s33 ; 4-byte Folded Spill ; GFX10-NEXT: s_waitcnt_depctr 0xffe3 ; GFX10-NEXT: s_mov_b32 exec_lo, s35 -; GFX10-NEXT: v_writelane_b32 v40, s34, 3 -; GFX10-NEXT: s_addk_i32 s32, 0x200 -; GFX10-NEXT: v_writelane_b32 v40, s4, 0 -; GFX10-NEXT: s_load_dword s4, s[34:35], 0x0 +; GFX10-NEXT: s_load_dword s0, s[34:35], 0x0 +; GFX10-NEXT: v_writelane_b32 v40, s34, 2 ; GFX10-NEXT: s_mov_b32 s35, external_void_func_v2f16_inreg@abs32@hi ; GFX10-NEXT: s_mov_b32 s34, external_void_func_v2f16_inreg@abs32@lo -; GFX10-NEXT: v_writelane_b32 v40, s30, 1 -; GFX10-NEXT: v_writelane_b32 v40, s31, 2 +; GFX10-NEXT: s_addk_i32 s32, 0x200 +; GFX10-NEXT: v_writelane_b32 v40, s30, 0 +; GFX10-NEXT: v_writelane_b32 v40, s31, 1 ; GFX10-NEXT: s_swappc_b64 s[30:31], s[34:35] -; GFX10-NEXT: v_readlane_b32 s31, v40, 2 -; GFX10-NEXT: v_readlane_b32 s30, v40, 1 -; GFX10-NEXT: v_readlane_b32 s4, v40, 0 -; GFX10-NEXT: v_readlane_b32 s34, v40, 3 +; GFX10-NEXT: v_readlane_b32 s31, v40, 1 +; GFX10-NEXT: v_readlane_b32 s30, v40, 0 +; GFX10-NEXT: v_readlane_b32 s34, v40, 2 ; GFX10-NEXT: s_or_saveexec_b32 s35, -1 ; GFX10-NEXT: buffer_load_dword v40, off, s[0:3], s33 ; 4-byte Folded Reload ; GFX10-NEXT: s_waitcnt_depctr 0xffe3 @@ -12968,20 +12572,18 @@ define amdgpu_gfx void @test_call_external_void_func_v2f16_inreg() #0 { ; GFX11-NEXT: s_or_saveexec_b32 s1, -1 ; GFX11-NEXT: scratch_store_b32 off, v40, s33 ; 4-byte Folded Spill ; GFX11-NEXT: s_mov_b32 exec_lo, s1 -; GFX11-NEXT: v_writelane_b32 v40, s0, 3 +; GFX11-NEXT: v_writelane_b32 v40, s0, 2 +; GFX11-NEXT: s_load_b32 s0, s[0:1], 0x0 +; GFX11-NEXT: s_mov_b32 s3, external_void_func_v2f16_inreg@abs32@hi +; GFX11-NEXT: s_mov_b32 s2, external_void_func_v2f16_inreg@abs32@lo ; GFX11-NEXT: s_add_i32 s32, s32, 16 -; GFX11-NEXT: v_writelane_b32 v40, s4, 0 -; GFX11-NEXT: s_load_b32 s4, s[0:1], 0x0 -; GFX11-NEXT: s_mov_b32 s1, external_void_func_v2f16_inreg@abs32@hi -; GFX11-NEXT: s_mov_b32 s0, external_void_func_v2f16_inreg@abs32@lo -; GFX11-NEXT: v_writelane_b32 v40, s30, 1 -; GFX11-NEXT: v_writelane_b32 v40, s31, 2 -; GFX11-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX11-NEXT: v_writelane_b32 v40, s30, 0 +; GFX11-NEXT: v_writelane_b32 v40, s31, 1 +; GFX11-NEXT: s_swappc_b64 s[30:31], s[2:3] ; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_1) -; GFX11-NEXT: v_readlane_b32 s31, v40, 2 -; GFX11-NEXT: v_readlane_b32 s30, v40, 1 -; GFX11-NEXT: v_readlane_b32 s4, v40, 0 -; GFX11-NEXT: v_readlane_b32 s0, v40, 3 +; GFX11-NEXT: v_readlane_b32 s31, v40, 1 +; GFX11-NEXT: v_readlane_b32 s30, v40, 0 +; GFX11-NEXT: v_readlane_b32 s0, v40, 2 ; GFX11-NEXT: s_or_saveexec_b32 s1, -1 ; GFX11-NEXT: scratch_load_b32 v40, off, s33 ; 4-byte Folded Reload ; GFX11-NEXT: s_mov_b32 exec_lo, s1 @@ -12999,19 +12601,17 @@ define amdgpu_gfx void @test_call_external_void_func_v2f16_inreg() #0 { ; GFX10-SCRATCH-NEXT: scratch_store_dword off, v40, s33 ; 4-byte Folded Spill ; GFX10-SCRATCH-NEXT: s_waitcnt_depctr 0xffe3 ; GFX10-SCRATCH-NEXT: s_mov_b32 exec_lo, s1 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s0, 3 +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s0, 2 +; GFX10-SCRATCH-NEXT: s_load_dword s0, s[0:1], 0x0 +; GFX10-SCRATCH-NEXT: s_mov_b32 s3, external_void_func_v2f16_inreg@abs32@hi +; GFX10-SCRATCH-NEXT: s_mov_b32 s2, external_void_func_v2f16_inreg@abs32@lo ; GFX10-SCRATCH-NEXT: s_add_i32 s32, s32, 16 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s4, 0 -; GFX10-SCRATCH-NEXT: s_load_dword s4, s[0:1], 0x0 -; GFX10-SCRATCH-NEXT: s_mov_b32 s1, external_void_func_v2f16_inreg@abs32@hi -; GFX10-SCRATCH-NEXT: s_mov_b32 s0, external_void_func_v2f16_inreg@abs32@lo -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s30, 1 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s31, 2 -; GFX10-SCRATCH-NEXT: s_swappc_b64 s[30:31], s[0:1] -; GFX10-SCRATCH-NEXT: v_readlane_b32 s31, v40, 2 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s30, v40, 1 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s4, v40, 0 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s0, v40, 3 +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s30, 0 +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s31, 1 +; GFX10-SCRATCH-NEXT: s_swappc_b64 s[30:31], s[2:3] +; GFX10-SCRATCH-NEXT: v_readlane_b32 s31, v40, 1 +; GFX10-SCRATCH-NEXT: v_readlane_b32 s30, v40, 0 +; GFX10-SCRATCH-NEXT: v_readlane_b32 s0, v40, 2 ; GFX10-SCRATCH-NEXT: s_or_saveexec_b32 s1, -1 ; GFX10-SCRATCH-NEXT: scratch_load_dword v40, off, s33 ; 4-byte Folded Reload ; GFX10-SCRATCH-NEXT: s_waitcnt_depctr 0xffe3 @@ -13034,21 +12634,20 @@ define amdgpu_gfx void @test_call_external_void_func_v2i32_inreg() #0 { ; GFX9-NEXT: s_or_saveexec_b64 s[36:37], -1 ; GFX9-NEXT: buffer_store_dword v40, off, s[0:3], s33 ; 4-byte Folded Spill ; GFX9-NEXT: s_mov_b64 exec, s[36:37] -; GFX9-NEXT: v_writelane_b32 v40, s34, 4 -; GFX9-NEXT: v_writelane_b32 v40, s4, 0 -; GFX9-NEXT: v_writelane_b32 v40, s5, 1 -; GFX9-NEXT: s_load_dwordx2 s[4:5], s[34:35], 0x0 -; GFX9-NEXT: v_writelane_b32 v40, s30, 2 -; GFX9-NEXT: s_mov_b32 s35, external_void_func_v2i32_inreg@abs32@hi -; GFX9-NEXT: s_mov_b32 s34, external_void_func_v2i32_inreg@abs32@lo +; GFX9-NEXT: v_writelane_b32 v40, s34, 2 +; GFX9-NEXT: s_load_dwordx2 s[34:35], s[34:35], 0x0 +; GFX9-NEXT: v_writelane_b32 v40, s30, 0 +; GFX9-NEXT: s_mov_b32 s37, external_void_func_v2i32_inreg@abs32@hi +; GFX9-NEXT: s_mov_b32 s36, external_void_func_v2i32_inreg@abs32@lo ; GFX9-NEXT: s_addk_i32 s32, 0x400 -; GFX9-NEXT: v_writelane_b32 v40, s31, 3 -; GFX9-NEXT: s_swappc_b64 s[30:31], s[34:35] -; GFX9-NEXT: v_readlane_b32 s31, v40, 3 -; GFX9-NEXT: v_readlane_b32 s30, v40, 2 -; GFX9-NEXT: v_readlane_b32 s5, v40, 1 -; GFX9-NEXT: v_readlane_b32 s4, v40, 0 -; GFX9-NEXT: v_readlane_b32 s34, v40, 4 +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: s_mov_b32 s0, s34 +; GFX9-NEXT: s_mov_b32 s1, s35 +; GFX9-NEXT: v_writelane_b32 v40, s31, 1 +; GFX9-NEXT: s_swappc_b64 s[30:31], s[36:37] +; GFX9-NEXT: v_readlane_b32 s31, v40, 1 +; GFX9-NEXT: v_readlane_b32 s30, v40, 0 +; GFX9-NEXT: v_readlane_b32 s34, v40, 2 ; GFX9-NEXT: s_or_saveexec_b64 s[36:37], -1 ; GFX9-NEXT: buffer_load_dword v40, off, s[0:3], s33 ; 4-byte Folded Reload ; GFX9-NEXT: s_mov_b64 exec, s[36:37] @@ -13066,21 +12665,20 @@ define amdgpu_gfx void @test_call_external_void_func_v2i32_inreg() #0 { ; GFX10-NEXT: buffer_store_dword v40, off, s[0:3], s33 ; 4-byte Folded Spill ; GFX10-NEXT: s_waitcnt_depctr 0xffe3 ; GFX10-NEXT: s_mov_b32 exec_lo, s35 -; GFX10-NEXT: v_writelane_b32 v40, s34, 4 +; GFX10-NEXT: v_writelane_b32 v40, s34, 2 +; GFX10-NEXT: s_load_dwordx2 s[34:35], s[34:35], 0x0 +; GFX10-NEXT: s_mov_b32 s37, external_void_func_v2i32_inreg@abs32@hi +; GFX10-NEXT: s_mov_b32 s36, external_void_func_v2i32_inreg@abs32@lo ; GFX10-NEXT: s_addk_i32 s32, 0x200 -; GFX10-NEXT: v_writelane_b32 v40, s4, 0 -; GFX10-NEXT: v_writelane_b32 v40, s5, 1 -; GFX10-NEXT: s_load_dwordx2 s[4:5], s[34:35], 0x0 -; GFX10-NEXT: s_mov_b32 s35, external_void_func_v2i32_inreg@abs32@hi -; GFX10-NEXT: s_mov_b32 s34, external_void_func_v2i32_inreg@abs32@lo -; GFX10-NEXT: v_writelane_b32 v40, s30, 2 -; GFX10-NEXT: v_writelane_b32 v40, s31, 3 -; GFX10-NEXT: s_swappc_b64 s[30:31], s[34:35] -; GFX10-NEXT: v_readlane_b32 s31, v40, 3 -; GFX10-NEXT: v_readlane_b32 s30, v40, 2 -; GFX10-NEXT: v_readlane_b32 s5, v40, 1 -; GFX10-NEXT: v_readlane_b32 s4, v40, 0 -; GFX10-NEXT: v_readlane_b32 s34, v40, 4 +; GFX10-NEXT: v_writelane_b32 v40, s30, 0 +; GFX10-NEXT: v_writelane_b32 v40, s31, 1 +; GFX10-NEXT: s_waitcnt lgkmcnt(0) +; GFX10-NEXT: s_mov_b32 s0, s34 +; GFX10-NEXT: s_mov_b32 s1, s35 +; GFX10-NEXT: s_swappc_b64 s[30:31], s[36:37] +; GFX10-NEXT: v_readlane_b32 s31, v40, 1 +; GFX10-NEXT: v_readlane_b32 s30, v40, 0 +; GFX10-NEXT: v_readlane_b32 s34, v40, 2 ; GFX10-NEXT: s_or_saveexec_b32 s35, -1 ; GFX10-NEXT: buffer_load_dword v40, off, s[0:3], s33 ; 4-byte Folded Reload ; GFX10-NEXT: s_waitcnt_depctr 0xffe3 @@ -13098,22 +12696,18 @@ define amdgpu_gfx void @test_call_external_void_func_v2i32_inreg() #0 { ; GFX11-NEXT: s_or_saveexec_b32 s1, -1 ; GFX11-NEXT: scratch_store_b32 off, v40, s33 ; 4-byte Folded Spill ; GFX11-NEXT: s_mov_b32 exec_lo, s1 -; GFX11-NEXT: v_writelane_b32 v40, s0, 4 +; GFX11-NEXT: v_writelane_b32 v40, s0, 2 +; GFX11-NEXT: s_load_b64 s[0:1], s[0:1], 0x0 +; GFX11-NEXT: s_mov_b32 s3, external_void_func_v2i32_inreg@abs32@hi +; GFX11-NEXT: s_mov_b32 s2, external_void_func_v2i32_inreg@abs32@lo ; GFX11-NEXT: s_add_i32 s32, s32, 16 -; GFX11-NEXT: v_writelane_b32 v40, s4, 0 -; GFX11-NEXT: v_writelane_b32 v40, s5, 1 -; GFX11-NEXT: s_load_b64 s[4:5], s[0:1], 0x0 -; GFX11-NEXT: s_mov_b32 s1, external_void_func_v2i32_inreg@abs32@hi -; GFX11-NEXT: s_mov_b32 s0, external_void_func_v2i32_inreg@abs32@lo -; GFX11-NEXT: v_writelane_b32 v40, s30, 2 -; GFX11-NEXT: v_writelane_b32 v40, s31, 3 -; GFX11-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX11-NEXT: v_writelane_b32 v40, s30, 0 +; GFX11-NEXT: v_writelane_b32 v40, s31, 1 +; GFX11-NEXT: s_swappc_b64 s[30:31], s[2:3] ; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_1) -; GFX11-NEXT: v_readlane_b32 s31, v40, 3 -; GFX11-NEXT: v_readlane_b32 s30, v40, 2 -; GFX11-NEXT: v_readlane_b32 s5, v40, 1 -; GFX11-NEXT: v_readlane_b32 s4, v40, 0 -; GFX11-NEXT: v_readlane_b32 s0, v40, 4 +; GFX11-NEXT: v_readlane_b32 s31, v40, 1 +; GFX11-NEXT: v_readlane_b32 s30, v40, 0 +; GFX11-NEXT: v_readlane_b32 s0, v40, 2 ; GFX11-NEXT: s_or_saveexec_b32 s1, -1 ; GFX11-NEXT: scratch_load_b32 v40, off, s33 ; 4-byte Folded Reload ; GFX11-NEXT: s_mov_b32 exec_lo, s1 @@ -13131,21 +12725,17 @@ define amdgpu_gfx void @test_call_external_void_func_v2i32_inreg() #0 { ; GFX10-SCRATCH-NEXT: scratch_store_dword off, v40, s33 ; 4-byte Folded Spill ; GFX10-SCRATCH-NEXT: s_waitcnt_depctr 0xffe3 ; GFX10-SCRATCH-NEXT: s_mov_b32 exec_lo, s1 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s0, 4 +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s0, 2 +; GFX10-SCRATCH-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x0 +; GFX10-SCRATCH-NEXT: s_mov_b32 s3, external_void_func_v2i32_inreg@abs32@hi +; GFX10-SCRATCH-NEXT: s_mov_b32 s2, external_void_func_v2i32_inreg@abs32@lo ; GFX10-SCRATCH-NEXT: s_add_i32 s32, s32, 16 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s4, 0 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s5, 1 -; GFX10-SCRATCH-NEXT: s_load_dwordx2 s[4:5], s[0:1], 0x0 -; GFX10-SCRATCH-NEXT: s_mov_b32 s1, external_void_func_v2i32_inreg@abs32@hi -; GFX10-SCRATCH-NEXT: s_mov_b32 s0, external_void_func_v2i32_inreg@abs32@lo -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s30, 2 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s31, 3 -; GFX10-SCRATCH-NEXT: s_swappc_b64 s[30:31], s[0:1] -; GFX10-SCRATCH-NEXT: v_readlane_b32 s31, v40, 3 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s30, v40, 2 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s5, v40, 1 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s4, v40, 0 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s0, v40, 4 +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s30, 0 +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s31, 1 +; GFX10-SCRATCH-NEXT: s_swappc_b64 s[30:31], s[2:3] +; GFX10-SCRATCH-NEXT: v_readlane_b32 s31, v40, 1 +; GFX10-SCRATCH-NEXT: v_readlane_b32 s30, v40, 0 +; GFX10-SCRATCH-NEXT: v_readlane_b32 s0, v40, 2 ; GFX10-SCRATCH-NEXT: s_or_saveexec_b32 s1, -1 ; GFX10-SCRATCH-NEXT: scratch_load_dword v40, off, s33 ; 4-byte Folded Reload ; GFX10-SCRATCH-NEXT: s_waitcnt_depctr 0xffe3 @@ -13168,22 +12758,18 @@ define amdgpu_gfx void @test_call_external_void_func_v2i32_imm_inreg() #0 { ; GFX9-NEXT: s_or_saveexec_b64 s[36:37], -1 ; GFX9-NEXT: buffer_store_dword v40, off, s[0:3], s33 ; 4-byte Folded Spill ; GFX9-NEXT: s_mov_b64 exec, s[36:37] -; GFX9-NEXT: v_writelane_b32 v40, s34, 4 -; GFX9-NEXT: v_writelane_b32 v40, s4, 0 -; GFX9-NEXT: v_writelane_b32 v40, s5, 1 -; GFX9-NEXT: v_writelane_b32 v40, s30, 2 +; GFX9-NEXT: v_writelane_b32 v40, s34, 2 +; GFX9-NEXT: v_writelane_b32 v40, s30, 0 ; GFX9-NEXT: s_mov_b32 s35, external_void_func_v2i32_inreg@abs32@hi ; GFX9-NEXT: s_mov_b32 s34, external_void_func_v2i32_inreg@abs32@lo -; GFX9-NEXT: s_mov_b32 s4, 1 -; GFX9-NEXT: s_mov_b32 s5, 2 +; GFX9-NEXT: s_mov_b32 s0, 1 +; GFX9-NEXT: s_mov_b32 s1, 2 ; GFX9-NEXT: s_addk_i32 s32, 0x400 -; GFX9-NEXT: v_writelane_b32 v40, s31, 3 +; GFX9-NEXT: v_writelane_b32 v40, s31, 1 ; GFX9-NEXT: s_swappc_b64 s[30:31], s[34:35] -; GFX9-NEXT: v_readlane_b32 s31, v40, 3 -; GFX9-NEXT: v_readlane_b32 s30, v40, 2 -; GFX9-NEXT: v_readlane_b32 s5, v40, 1 -; GFX9-NEXT: v_readlane_b32 s4, v40, 0 -; GFX9-NEXT: v_readlane_b32 s34, v40, 4 +; GFX9-NEXT: v_readlane_b32 s31, v40, 1 +; GFX9-NEXT: v_readlane_b32 s30, v40, 0 +; GFX9-NEXT: v_readlane_b32 s34, v40, 2 ; GFX9-NEXT: s_or_saveexec_b64 s[36:37], -1 ; GFX9-NEXT: buffer_load_dword v40, off, s[0:3], s33 ; 4-byte Folded Reload ; GFX9-NEXT: s_mov_b64 exec, s[36:37] @@ -13201,22 +12787,18 @@ define amdgpu_gfx void @test_call_external_void_func_v2i32_imm_inreg() #0 { ; GFX10-NEXT: buffer_store_dword v40, off, s[0:3], s33 ; 4-byte Folded Spill ; GFX10-NEXT: s_waitcnt_depctr 0xffe3 ; GFX10-NEXT: s_mov_b32 exec_lo, s35 -; GFX10-NEXT: v_writelane_b32 v40, s34, 4 +; GFX10-NEXT: v_writelane_b32 v40, s34, 2 ; GFX10-NEXT: s_mov_b32 s35, external_void_func_v2i32_inreg@abs32@hi ; GFX10-NEXT: s_mov_b32 s34, external_void_func_v2i32_inreg@abs32@lo +; GFX10-NEXT: s_mov_b32 s0, 1 +; GFX10-NEXT: s_mov_b32 s1, 2 +; GFX10-NEXT: v_writelane_b32 v40, s30, 0 ; GFX10-NEXT: s_addk_i32 s32, 0x200 -; GFX10-NEXT: v_writelane_b32 v40, s4, 0 -; GFX10-NEXT: s_mov_b32 s4, 1 -; GFX10-NEXT: v_writelane_b32 v40, s5, 1 -; GFX10-NEXT: s_mov_b32 s5, 2 -; GFX10-NEXT: v_writelane_b32 v40, s30, 2 -; GFX10-NEXT: v_writelane_b32 v40, s31, 3 +; GFX10-NEXT: v_writelane_b32 v40, s31, 1 ; GFX10-NEXT: s_swappc_b64 s[30:31], s[34:35] -; GFX10-NEXT: v_readlane_b32 s31, v40, 3 -; GFX10-NEXT: v_readlane_b32 s30, v40, 2 -; GFX10-NEXT: v_readlane_b32 s5, v40, 1 -; GFX10-NEXT: v_readlane_b32 s4, v40, 0 -; GFX10-NEXT: v_readlane_b32 s34, v40, 4 +; GFX10-NEXT: v_readlane_b32 s31, v40, 1 +; GFX10-NEXT: v_readlane_b32 s30, v40, 0 +; GFX10-NEXT: v_readlane_b32 s34, v40, 2 ; GFX10-NEXT: s_or_saveexec_b32 s35, -1 ; GFX10-NEXT: buffer_load_dword v40, off, s[0:3], s33 ; 4-byte Folded Reload ; GFX10-NEXT: s_waitcnt_depctr 0xffe3 @@ -13234,23 +12816,19 @@ define amdgpu_gfx void @test_call_external_void_func_v2i32_imm_inreg() #0 { ; GFX11-NEXT: s_or_saveexec_b32 s1, -1 ; GFX11-NEXT: scratch_store_b32 off, v40, s33 ; 4-byte Folded Spill ; GFX11-NEXT: s_mov_b32 exec_lo, s1 -; GFX11-NEXT: v_writelane_b32 v40, s0, 4 -; GFX11-NEXT: s_mov_b32 s1, external_void_func_v2i32_inreg@abs32@hi -; GFX11-NEXT: s_mov_b32 s0, external_void_func_v2i32_inreg@abs32@lo +; GFX11-NEXT: v_writelane_b32 v40, s0, 2 +; GFX11-NEXT: s_mov_b32 s3, external_void_func_v2i32_inreg@abs32@hi +; GFX11-NEXT: s_mov_b32 s2, external_void_func_v2i32_inreg@abs32@lo +; GFX11-NEXT: s_mov_b32 s0, 1 +; GFX11-NEXT: s_mov_b32 s1, 2 +; GFX11-NEXT: v_writelane_b32 v40, s30, 0 ; GFX11-NEXT: s_add_i32 s32, s32, 16 -; GFX11-NEXT: v_writelane_b32 v40, s4, 0 -; GFX11-NEXT: s_mov_b32 s4, 1 -; GFX11-NEXT: v_writelane_b32 v40, s5, 1 -; GFX11-NEXT: s_mov_b32 s5, 2 -; GFX11-NEXT: v_writelane_b32 v40, s30, 2 -; GFX11-NEXT: v_writelane_b32 v40, s31, 3 -; GFX11-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX11-NEXT: v_writelane_b32 v40, s31, 1 +; GFX11-NEXT: s_swappc_b64 s[30:31], s[2:3] ; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_1) -; GFX11-NEXT: v_readlane_b32 s31, v40, 3 -; GFX11-NEXT: v_readlane_b32 s30, v40, 2 -; GFX11-NEXT: v_readlane_b32 s5, v40, 1 -; GFX11-NEXT: v_readlane_b32 s4, v40, 0 -; GFX11-NEXT: v_readlane_b32 s0, v40, 4 +; GFX11-NEXT: v_readlane_b32 s31, v40, 1 +; GFX11-NEXT: v_readlane_b32 s30, v40, 0 +; GFX11-NEXT: v_readlane_b32 s0, v40, 2 ; GFX11-NEXT: s_or_saveexec_b32 s1, -1 ; GFX11-NEXT: scratch_load_b32 v40, off, s33 ; 4-byte Folded Reload ; GFX11-NEXT: s_mov_b32 exec_lo, s1 @@ -13268,22 +12846,18 @@ define amdgpu_gfx void @test_call_external_void_func_v2i32_imm_inreg() #0 { ; GFX10-SCRATCH-NEXT: scratch_store_dword off, v40, s33 ; 4-byte Folded Spill ; GFX10-SCRATCH-NEXT: s_waitcnt_depctr 0xffe3 ; GFX10-SCRATCH-NEXT: s_mov_b32 exec_lo, s1 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s0, 4 -; GFX10-SCRATCH-NEXT: s_mov_b32 s1, external_void_func_v2i32_inreg@abs32@hi -; GFX10-SCRATCH-NEXT: s_mov_b32 s0, external_void_func_v2i32_inreg@abs32@lo +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s0, 2 +; GFX10-SCRATCH-NEXT: s_mov_b32 s3, external_void_func_v2i32_inreg@abs32@hi +; GFX10-SCRATCH-NEXT: s_mov_b32 s2, external_void_func_v2i32_inreg@abs32@lo +; GFX10-SCRATCH-NEXT: s_mov_b32 s0, 1 +; GFX10-SCRATCH-NEXT: s_mov_b32 s1, 2 +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s30, 0 ; GFX10-SCRATCH-NEXT: s_add_i32 s32, s32, 16 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s4, 0 -; GFX10-SCRATCH-NEXT: s_mov_b32 s4, 1 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s5, 1 -; GFX10-SCRATCH-NEXT: s_mov_b32 s5, 2 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s30, 2 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s31, 3 -; GFX10-SCRATCH-NEXT: s_swappc_b64 s[30:31], s[0:1] -; GFX10-SCRATCH-NEXT: v_readlane_b32 s31, v40, 3 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s30, v40, 2 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s5, v40, 1 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s4, v40, 0 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s0, v40, 4 +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s31, 1 +; GFX10-SCRATCH-NEXT: s_swappc_b64 s[30:31], s[2:3] +; GFX10-SCRATCH-NEXT: v_readlane_b32 s31, v40, 1 +; GFX10-SCRATCH-NEXT: v_readlane_b32 s30, v40, 0 +; GFX10-SCRATCH-NEXT: v_readlane_b32 s0, v40, 2 ; GFX10-SCRATCH-NEXT: s_or_saveexec_b32 s1, -1 ; GFX10-SCRATCH-NEXT: scratch_load_dword v40, off, s33 ; 4-byte Folded Reload ; GFX10-SCRATCH-NEXT: s_waitcnt_depctr 0xffe3 @@ -13305,25 +12879,19 @@ define amdgpu_gfx void @test_call_external_void_func_v3i32_imm_inreg(i32) #0 { ; GFX9-NEXT: s_or_saveexec_b64 s[36:37], -1 ; GFX9-NEXT: buffer_store_dword v40, off, s[0:3], s33 ; 4-byte Folded Spill ; GFX9-NEXT: s_mov_b64 exec, s[36:37] -; GFX9-NEXT: v_writelane_b32 v40, s34, 5 -; GFX9-NEXT: v_writelane_b32 v40, s4, 0 -; GFX9-NEXT: v_writelane_b32 v40, s5, 1 -; GFX9-NEXT: v_writelane_b32 v40, s6, 2 -; GFX9-NEXT: v_writelane_b32 v40, s30, 3 +; GFX9-NEXT: v_writelane_b32 v40, s34, 2 +; GFX9-NEXT: v_writelane_b32 v40, s30, 0 ; GFX9-NEXT: s_mov_b32 s35, external_void_func_v3i32_inreg@abs32@hi ; GFX9-NEXT: s_mov_b32 s34, external_void_func_v3i32_inreg@abs32@lo -; GFX9-NEXT: s_mov_b32 s4, 3 -; GFX9-NEXT: s_mov_b32 s5, 4 -; GFX9-NEXT: s_mov_b32 s6, 5 +; GFX9-NEXT: s_mov_b32 s0, 3 +; GFX9-NEXT: s_mov_b32 s1, 4 +; GFX9-NEXT: s_mov_b32 s2, 5 ; GFX9-NEXT: s_addk_i32 s32, 0x400 -; GFX9-NEXT: v_writelane_b32 v40, s31, 4 +; GFX9-NEXT: v_writelane_b32 v40, s31, 1 ; GFX9-NEXT: s_swappc_b64 s[30:31], s[34:35] -; GFX9-NEXT: v_readlane_b32 s31, v40, 4 -; GFX9-NEXT: v_readlane_b32 s30, v40, 3 -; GFX9-NEXT: v_readlane_b32 s6, v40, 2 -; GFX9-NEXT: v_readlane_b32 s5, v40, 1 -; GFX9-NEXT: v_readlane_b32 s4, v40, 0 -; GFX9-NEXT: v_readlane_b32 s34, v40, 5 +; GFX9-NEXT: v_readlane_b32 s31, v40, 1 +; GFX9-NEXT: v_readlane_b32 s30, v40, 0 +; GFX9-NEXT: v_readlane_b32 s34, v40, 2 ; GFX9-NEXT: s_or_saveexec_b64 s[36:37], -1 ; GFX9-NEXT: buffer_load_dword v40, off, s[0:3], s33 ; 4-byte Folded Reload ; GFX9-NEXT: s_mov_b64 exec, s[36:37] @@ -13341,25 +12909,19 @@ define amdgpu_gfx void @test_call_external_void_func_v3i32_imm_inreg(i32) #0 { ; GFX10-NEXT: buffer_store_dword v40, off, s[0:3], s33 ; 4-byte Folded Spill ; GFX10-NEXT: s_waitcnt_depctr 0xffe3 ; GFX10-NEXT: s_mov_b32 exec_lo, s35 -; GFX10-NEXT: v_writelane_b32 v40, s34, 5 +; GFX10-NEXT: v_writelane_b32 v40, s34, 2 ; GFX10-NEXT: s_mov_b32 s35, external_void_func_v3i32_inreg@abs32@hi ; GFX10-NEXT: s_mov_b32 s34, external_void_func_v3i32_inreg@abs32@lo +; GFX10-NEXT: s_mov_b32 s0, 3 +; GFX10-NEXT: s_mov_b32 s1, 4 +; GFX10-NEXT: v_writelane_b32 v40, s30, 0 +; GFX10-NEXT: s_mov_b32 s2, 5 ; GFX10-NEXT: s_addk_i32 s32, 0x200 -; GFX10-NEXT: v_writelane_b32 v40, s4, 0 -; GFX10-NEXT: s_mov_b32 s4, 3 -; GFX10-NEXT: v_writelane_b32 v40, s5, 1 -; GFX10-NEXT: s_mov_b32 s5, 4 -; GFX10-NEXT: v_writelane_b32 v40, s6, 2 -; GFX10-NEXT: s_mov_b32 s6, 5 -; GFX10-NEXT: v_writelane_b32 v40, s30, 3 -; GFX10-NEXT: v_writelane_b32 v40, s31, 4 +; GFX10-NEXT: v_writelane_b32 v40, s31, 1 ; GFX10-NEXT: s_swappc_b64 s[30:31], s[34:35] -; GFX10-NEXT: v_readlane_b32 s31, v40, 4 -; GFX10-NEXT: v_readlane_b32 s30, v40, 3 -; GFX10-NEXT: v_readlane_b32 s6, v40, 2 -; GFX10-NEXT: v_readlane_b32 s5, v40, 1 -; GFX10-NEXT: v_readlane_b32 s4, v40, 0 -; GFX10-NEXT: v_readlane_b32 s34, v40, 5 +; GFX10-NEXT: v_readlane_b32 s31, v40, 1 +; GFX10-NEXT: v_readlane_b32 s30, v40, 0 +; GFX10-NEXT: v_readlane_b32 s34, v40, 2 ; GFX10-NEXT: s_or_saveexec_b32 s35, -1 ; GFX10-NEXT: buffer_load_dword v40, off, s[0:3], s33 ; 4-byte Folded Reload ; GFX10-NEXT: s_waitcnt_depctr 0xffe3 @@ -13377,26 +12939,20 @@ define amdgpu_gfx void @test_call_external_void_func_v3i32_imm_inreg(i32) #0 { ; GFX11-NEXT: s_or_saveexec_b32 s1, -1 ; GFX11-NEXT: scratch_store_b32 off, v40, s33 ; 4-byte Folded Spill ; GFX11-NEXT: s_mov_b32 exec_lo, s1 -; GFX11-NEXT: v_writelane_b32 v40, s0, 5 -; GFX11-NEXT: s_mov_b32 s1, external_void_func_v3i32_inreg@abs32@hi -; GFX11-NEXT: s_mov_b32 s0, external_void_func_v3i32_inreg@abs32@lo +; GFX11-NEXT: v_writelane_b32 v40, s0, 2 +; GFX11-NEXT: s_mov_b32 s35, external_void_func_v3i32_inreg@abs32@hi +; GFX11-NEXT: s_mov_b32 s34, external_void_func_v3i32_inreg@abs32@lo +; GFX11-NEXT: s_mov_b32 s0, 3 +; GFX11-NEXT: s_mov_b32 s1, 4 +; GFX11-NEXT: v_writelane_b32 v40, s30, 0 +; GFX11-NEXT: s_mov_b32 s2, 5 ; GFX11-NEXT: s_add_i32 s32, s32, 16 -; GFX11-NEXT: v_writelane_b32 v40, s4, 0 -; GFX11-NEXT: s_mov_b32 s4, 3 -; GFX11-NEXT: v_writelane_b32 v40, s5, 1 -; GFX11-NEXT: s_mov_b32 s5, 4 -; GFX11-NEXT: v_writelane_b32 v40, s6, 2 -; GFX11-NEXT: s_mov_b32 s6, 5 -; GFX11-NEXT: v_writelane_b32 v40, s30, 3 -; GFX11-NEXT: v_writelane_b32 v40, s31, 4 -; GFX11-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX11-NEXT: v_writelane_b32 v40, s31, 1 +; GFX11-NEXT: s_swappc_b64 s[30:31], s[34:35] ; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_1) -; GFX11-NEXT: v_readlane_b32 s31, v40, 4 -; GFX11-NEXT: v_readlane_b32 s30, v40, 3 -; GFX11-NEXT: v_readlane_b32 s6, v40, 2 -; GFX11-NEXT: v_readlane_b32 s5, v40, 1 -; GFX11-NEXT: v_readlane_b32 s4, v40, 0 -; GFX11-NEXT: v_readlane_b32 s0, v40, 5 +; GFX11-NEXT: v_readlane_b32 s31, v40, 1 +; GFX11-NEXT: v_readlane_b32 s30, v40, 0 +; GFX11-NEXT: v_readlane_b32 s0, v40, 2 ; GFX11-NEXT: s_or_saveexec_b32 s1, -1 ; GFX11-NEXT: scratch_load_b32 v40, off, s33 ; 4-byte Folded Reload ; GFX11-NEXT: s_mov_b32 exec_lo, s1 @@ -13414,25 +12970,19 @@ define amdgpu_gfx void @test_call_external_void_func_v3i32_imm_inreg(i32) #0 { ; GFX10-SCRATCH-NEXT: scratch_store_dword off, v40, s33 ; 4-byte Folded Spill ; GFX10-SCRATCH-NEXT: s_waitcnt_depctr 0xffe3 ; GFX10-SCRATCH-NEXT: s_mov_b32 exec_lo, s1 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s0, 5 -; GFX10-SCRATCH-NEXT: s_mov_b32 s1, external_void_func_v3i32_inreg@abs32@hi -; GFX10-SCRATCH-NEXT: s_mov_b32 s0, external_void_func_v3i32_inreg@abs32@lo +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s0, 2 +; GFX10-SCRATCH-NEXT: s_mov_b32 s35, external_void_func_v3i32_inreg@abs32@hi +; GFX10-SCRATCH-NEXT: s_mov_b32 s34, external_void_func_v3i32_inreg@abs32@lo +; GFX10-SCRATCH-NEXT: s_mov_b32 s0, 3 +; GFX10-SCRATCH-NEXT: s_mov_b32 s1, 4 +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s30, 0 +; GFX10-SCRATCH-NEXT: s_mov_b32 s2, 5 ; GFX10-SCRATCH-NEXT: s_add_i32 s32, s32, 16 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s4, 0 -; GFX10-SCRATCH-NEXT: s_mov_b32 s4, 3 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s5, 1 -; GFX10-SCRATCH-NEXT: s_mov_b32 s5, 4 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s6, 2 -; GFX10-SCRATCH-NEXT: s_mov_b32 s6, 5 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s30, 3 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s31, 4 -; GFX10-SCRATCH-NEXT: s_swappc_b64 s[30:31], s[0:1] -; GFX10-SCRATCH-NEXT: v_readlane_b32 s31, v40, 4 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s30, v40, 3 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s6, v40, 2 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s5, v40, 1 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s4, v40, 0 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s0, v40, 5 +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s31, 1 +; GFX10-SCRATCH-NEXT: s_swappc_b64 s[30:31], s[34:35] +; GFX10-SCRATCH-NEXT: v_readlane_b32 s31, v40, 1 +; GFX10-SCRATCH-NEXT: v_readlane_b32 s30, v40, 0 +; GFX10-SCRATCH-NEXT: v_readlane_b32 s0, v40, 2 ; GFX10-SCRATCH-NEXT: s_or_saveexec_b32 s1, -1 ; GFX10-SCRATCH-NEXT: scratch_load_dword v40, off, s33 ; 4-byte Folded Reload ; GFX10-SCRATCH-NEXT: s_waitcnt_depctr 0xffe3 @@ -13454,28 +13004,20 @@ define amdgpu_gfx void @test_call_external_void_func_v3i32_i32_inreg(i32) #0 { ; GFX9-NEXT: s_or_saveexec_b64 s[36:37], -1 ; GFX9-NEXT: buffer_store_dword v40, off, s[0:3], s33 ; 4-byte Folded Spill ; GFX9-NEXT: s_mov_b64 exec, s[36:37] -; GFX9-NEXT: v_writelane_b32 v40, s34, 6 -; GFX9-NEXT: v_writelane_b32 v40, s4, 0 -; GFX9-NEXT: v_writelane_b32 v40, s5, 1 -; GFX9-NEXT: v_writelane_b32 v40, s6, 2 -; GFX9-NEXT: v_writelane_b32 v40, s7, 3 -; GFX9-NEXT: v_writelane_b32 v40, s30, 4 +; GFX9-NEXT: v_writelane_b32 v40, s34, 2 +; GFX9-NEXT: v_writelane_b32 v40, s30, 0 ; GFX9-NEXT: s_mov_b32 s35, external_void_func_v3i32_i32_inreg@abs32@hi ; GFX9-NEXT: s_mov_b32 s34, external_void_func_v3i32_i32_inreg@abs32@lo -; GFX9-NEXT: s_mov_b32 s4, 3 -; GFX9-NEXT: s_mov_b32 s5, 4 -; GFX9-NEXT: s_mov_b32 s6, 5 -; GFX9-NEXT: s_mov_b32 s7, 6 +; GFX9-NEXT: s_mov_b32 s0, 3 +; GFX9-NEXT: s_mov_b32 s1, 4 +; GFX9-NEXT: s_mov_b32 s2, 5 +; GFX9-NEXT: s_mov_b32 s3, 6 ; GFX9-NEXT: s_addk_i32 s32, 0x400 -; GFX9-NEXT: v_writelane_b32 v40, s31, 5 +; GFX9-NEXT: v_writelane_b32 v40, s31, 1 ; GFX9-NEXT: s_swappc_b64 s[30:31], s[34:35] -; GFX9-NEXT: v_readlane_b32 s31, v40, 5 -; GFX9-NEXT: v_readlane_b32 s30, v40, 4 -; GFX9-NEXT: v_readlane_b32 s7, v40, 3 -; GFX9-NEXT: v_readlane_b32 s6, v40, 2 -; GFX9-NEXT: v_readlane_b32 s5, v40, 1 -; GFX9-NEXT: v_readlane_b32 s4, v40, 0 -; GFX9-NEXT: v_readlane_b32 s34, v40, 6 +; GFX9-NEXT: v_readlane_b32 s31, v40, 1 +; GFX9-NEXT: v_readlane_b32 s30, v40, 0 +; GFX9-NEXT: v_readlane_b32 s34, v40, 2 ; GFX9-NEXT: s_or_saveexec_b64 s[36:37], -1 ; GFX9-NEXT: buffer_load_dword v40, off, s[0:3], s33 ; 4-byte Folded Reload ; GFX9-NEXT: s_mov_b64 exec, s[36:37] @@ -13493,28 +13035,20 @@ define amdgpu_gfx void @test_call_external_void_func_v3i32_i32_inreg(i32) #0 { ; GFX10-NEXT: buffer_store_dword v40, off, s[0:3], s33 ; 4-byte Folded Spill ; GFX10-NEXT: s_waitcnt_depctr 0xffe3 ; GFX10-NEXT: s_mov_b32 exec_lo, s35 -; GFX10-NEXT: v_writelane_b32 v40, s34, 6 +; GFX10-NEXT: v_writelane_b32 v40, s34, 2 ; GFX10-NEXT: s_mov_b32 s35, external_void_func_v3i32_i32_inreg@abs32@hi ; GFX10-NEXT: s_mov_b32 s34, external_void_func_v3i32_i32_inreg@abs32@lo +; GFX10-NEXT: s_mov_b32 s0, 3 +; GFX10-NEXT: s_mov_b32 s1, 4 +; GFX10-NEXT: v_writelane_b32 v40, s30, 0 +; GFX10-NEXT: s_mov_b32 s2, 5 +; GFX10-NEXT: s_mov_b32 s3, 6 ; GFX10-NEXT: s_addk_i32 s32, 0x200 -; GFX10-NEXT: v_writelane_b32 v40, s4, 0 -; GFX10-NEXT: s_mov_b32 s4, 3 -; GFX10-NEXT: v_writelane_b32 v40, s5, 1 -; GFX10-NEXT: s_mov_b32 s5, 4 -; GFX10-NEXT: v_writelane_b32 v40, s6, 2 -; GFX10-NEXT: s_mov_b32 s6, 5 -; GFX10-NEXT: v_writelane_b32 v40, s7, 3 -; GFX10-NEXT: s_mov_b32 s7, 6 -; GFX10-NEXT: v_writelane_b32 v40, s30, 4 -; GFX10-NEXT: v_writelane_b32 v40, s31, 5 +; GFX10-NEXT: v_writelane_b32 v40, s31, 1 ; GFX10-NEXT: s_swappc_b64 s[30:31], s[34:35] -; GFX10-NEXT: v_readlane_b32 s31, v40, 5 -; GFX10-NEXT: v_readlane_b32 s30, v40, 4 -; GFX10-NEXT: v_readlane_b32 s7, v40, 3 -; GFX10-NEXT: v_readlane_b32 s6, v40, 2 -; GFX10-NEXT: v_readlane_b32 s5, v40, 1 -; GFX10-NEXT: v_readlane_b32 s4, v40, 0 -; GFX10-NEXT: v_readlane_b32 s34, v40, 6 +; GFX10-NEXT: v_readlane_b32 s31, v40, 1 +; GFX10-NEXT: v_readlane_b32 s30, v40, 0 +; GFX10-NEXT: v_readlane_b32 s34, v40, 2 ; GFX10-NEXT: s_or_saveexec_b32 s35, -1 ; GFX10-NEXT: buffer_load_dword v40, off, s[0:3], s33 ; 4-byte Folded Reload ; GFX10-NEXT: s_waitcnt_depctr 0xffe3 @@ -13532,29 +13066,21 @@ define amdgpu_gfx void @test_call_external_void_func_v3i32_i32_inreg(i32) #0 { ; GFX11-NEXT: s_or_saveexec_b32 s1, -1 ; GFX11-NEXT: scratch_store_b32 off, v40, s33 ; 4-byte Folded Spill ; GFX11-NEXT: s_mov_b32 exec_lo, s1 -; GFX11-NEXT: v_writelane_b32 v40, s0, 6 -; GFX11-NEXT: s_mov_b32 s1, external_void_func_v3i32_i32_inreg@abs32@hi -; GFX11-NEXT: s_mov_b32 s0, external_void_func_v3i32_i32_inreg@abs32@lo +; GFX11-NEXT: v_writelane_b32 v40, s0, 2 +; GFX11-NEXT: s_mov_b32 s35, external_void_func_v3i32_i32_inreg@abs32@hi +; GFX11-NEXT: s_mov_b32 s34, external_void_func_v3i32_i32_inreg@abs32@lo +; GFX11-NEXT: s_mov_b32 s0, 3 +; GFX11-NEXT: s_mov_b32 s1, 4 +; GFX11-NEXT: v_writelane_b32 v40, s30, 0 +; GFX11-NEXT: s_mov_b32 s2, 5 +; GFX11-NEXT: s_mov_b32 s3, 6 ; GFX11-NEXT: s_add_i32 s32, s32, 16 -; GFX11-NEXT: v_writelane_b32 v40, s4, 0 -; GFX11-NEXT: s_mov_b32 s4, 3 -; GFX11-NEXT: v_writelane_b32 v40, s5, 1 -; GFX11-NEXT: s_mov_b32 s5, 4 -; GFX11-NEXT: v_writelane_b32 v40, s6, 2 -; GFX11-NEXT: s_mov_b32 s6, 5 -; GFX11-NEXT: v_writelane_b32 v40, s7, 3 -; GFX11-NEXT: s_mov_b32 s7, 6 -; GFX11-NEXT: v_writelane_b32 v40, s30, 4 -; GFX11-NEXT: v_writelane_b32 v40, s31, 5 -; GFX11-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX11-NEXT: v_writelane_b32 v40, s31, 1 +; GFX11-NEXT: s_swappc_b64 s[30:31], s[34:35] ; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_1) -; GFX11-NEXT: v_readlane_b32 s31, v40, 5 -; GFX11-NEXT: v_readlane_b32 s30, v40, 4 -; GFX11-NEXT: v_readlane_b32 s7, v40, 3 -; GFX11-NEXT: v_readlane_b32 s6, v40, 2 -; GFX11-NEXT: v_readlane_b32 s5, v40, 1 -; GFX11-NEXT: v_readlane_b32 s4, v40, 0 -; GFX11-NEXT: v_readlane_b32 s0, v40, 6 +; GFX11-NEXT: v_readlane_b32 s31, v40, 1 +; GFX11-NEXT: v_readlane_b32 s30, v40, 0 +; GFX11-NEXT: v_readlane_b32 s0, v40, 2 ; GFX11-NEXT: s_or_saveexec_b32 s1, -1 ; GFX11-NEXT: scratch_load_b32 v40, off, s33 ; 4-byte Folded Reload ; GFX11-NEXT: s_mov_b32 exec_lo, s1 @@ -13572,28 +13098,20 @@ define amdgpu_gfx void @test_call_external_void_func_v3i32_i32_inreg(i32) #0 { ; GFX10-SCRATCH-NEXT: scratch_store_dword off, v40, s33 ; 4-byte Folded Spill ; GFX10-SCRATCH-NEXT: s_waitcnt_depctr 0xffe3 ; GFX10-SCRATCH-NEXT: s_mov_b32 exec_lo, s1 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s0, 6 -; GFX10-SCRATCH-NEXT: s_mov_b32 s1, external_void_func_v3i32_i32_inreg@abs32@hi -; GFX10-SCRATCH-NEXT: s_mov_b32 s0, external_void_func_v3i32_i32_inreg@abs32@lo +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s0, 2 +; GFX10-SCRATCH-NEXT: s_mov_b32 s35, external_void_func_v3i32_i32_inreg@abs32@hi +; GFX10-SCRATCH-NEXT: s_mov_b32 s34, external_void_func_v3i32_i32_inreg@abs32@lo +; GFX10-SCRATCH-NEXT: s_mov_b32 s0, 3 +; GFX10-SCRATCH-NEXT: s_mov_b32 s1, 4 +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s30, 0 +; GFX10-SCRATCH-NEXT: s_mov_b32 s2, 5 +; GFX10-SCRATCH-NEXT: s_mov_b32 s3, 6 ; GFX10-SCRATCH-NEXT: s_add_i32 s32, s32, 16 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s4, 0 -; GFX10-SCRATCH-NEXT: s_mov_b32 s4, 3 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s5, 1 -; GFX10-SCRATCH-NEXT: s_mov_b32 s5, 4 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s6, 2 -; GFX10-SCRATCH-NEXT: s_mov_b32 s6, 5 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s7, 3 -; GFX10-SCRATCH-NEXT: s_mov_b32 s7, 6 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s30, 4 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s31, 5 -; GFX10-SCRATCH-NEXT: s_swappc_b64 s[30:31], s[0:1] -; GFX10-SCRATCH-NEXT: v_readlane_b32 s31, v40, 5 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s30, v40, 4 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s7, v40, 3 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s6, v40, 2 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s5, v40, 1 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s4, v40, 0 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s0, v40, 6 +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s31, 1 +; GFX10-SCRATCH-NEXT: s_swappc_b64 s[30:31], s[34:35] +; GFX10-SCRATCH-NEXT: v_readlane_b32 s31, v40, 1 +; GFX10-SCRATCH-NEXT: v_readlane_b32 s30, v40, 0 +; GFX10-SCRATCH-NEXT: v_readlane_b32 s0, v40, 2 ; GFX10-SCRATCH-NEXT: s_or_saveexec_b32 s1, -1 ; GFX10-SCRATCH-NEXT: scratch_load_dword v40, off, s33 ; 4-byte Folded Reload ; GFX10-SCRATCH-NEXT: s_waitcnt_depctr 0xffe3 @@ -13615,25 +13133,22 @@ define amdgpu_gfx void @test_call_external_void_func_v4i32_inreg() #0 { ; GFX9-NEXT: s_or_saveexec_b64 s[36:37], -1 ; GFX9-NEXT: buffer_store_dword v40, off, s[0:3], s33 ; 4-byte Folded Spill ; GFX9-NEXT: s_mov_b64 exec, s[36:37] -; GFX9-NEXT: v_writelane_b32 v40, s34, 6 -; GFX9-NEXT: v_writelane_b32 v40, s4, 0 -; GFX9-NEXT: v_writelane_b32 v40, s5, 1 -; GFX9-NEXT: v_writelane_b32 v40, s6, 2 -; GFX9-NEXT: v_writelane_b32 v40, s7, 3 -; GFX9-NEXT: s_load_dwordx4 s[4:7], s[34:35], 0x0 -; GFX9-NEXT: v_writelane_b32 v40, s30, 4 +; GFX9-NEXT: s_load_dwordx4 s[36:39], s[34:35], 0x0 +; GFX9-NEXT: v_writelane_b32 v40, s34, 2 +; GFX9-NEXT: v_writelane_b32 v40, s30, 0 ; GFX9-NEXT: s_mov_b32 s35, external_void_func_v4i32_inreg@abs32@hi ; GFX9-NEXT: s_mov_b32 s34, external_void_func_v4i32_inreg@abs32@lo +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: s_mov_b32 s0, s36 +; GFX9-NEXT: s_mov_b32 s1, s37 +; GFX9-NEXT: s_mov_b32 s2, s38 +; GFX9-NEXT: s_mov_b32 s3, s39 ; GFX9-NEXT: s_addk_i32 s32, 0x400 -; GFX9-NEXT: v_writelane_b32 v40, s31, 5 +; GFX9-NEXT: v_writelane_b32 v40, s31, 1 ; GFX9-NEXT: s_swappc_b64 s[30:31], s[34:35] -; GFX9-NEXT: v_readlane_b32 s31, v40, 5 -; GFX9-NEXT: v_readlane_b32 s30, v40, 4 -; GFX9-NEXT: v_readlane_b32 s7, v40, 3 -; GFX9-NEXT: v_readlane_b32 s6, v40, 2 -; GFX9-NEXT: v_readlane_b32 s5, v40, 1 -; GFX9-NEXT: v_readlane_b32 s4, v40, 0 -; GFX9-NEXT: v_readlane_b32 s34, v40, 6 +; GFX9-NEXT: v_readlane_b32 s31, v40, 1 +; GFX9-NEXT: v_readlane_b32 s30, v40, 0 +; GFX9-NEXT: v_readlane_b32 s34, v40, 2 ; GFX9-NEXT: s_or_saveexec_b64 s[36:37], -1 ; GFX9-NEXT: buffer_load_dword v40, off, s[0:3], s33 ; 4-byte Folded Reload ; GFX9-NEXT: s_mov_b64 exec, s[36:37] @@ -13651,25 +13166,22 @@ define amdgpu_gfx void @test_call_external_void_func_v4i32_inreg() #0 { ; GFX10-NEXT: buffer_store_dword v40, off, s[0:3], s33 ; 4-byte Folded Spill ; GFX10-NEXT: s_waitcnt_depctr 0xffe3 ; GFX10-NEXT: s_mov_b32 exec_lo, s35 -; GFX10-NEXT: v_writelane_b32 v40, s34, 6 -; GFX10-NEXT: s_addk_i32 s32, 0x200 -; GFX10-NEXT: v_writelane_b32 v40, s4, 0 -; GFX10-NEXT: v_writelane_b32 v40, s5, 1 -; GFX10-NEXT: v_writelane_b32 v40, s6, 2 -; GFX10-NEXT: v_writelane_b32 v40, s7, 3 -; GFX10-NEXT: s_load_dwordx4 s[4:7], s[34:35], 0x0 +; GFX10-NEXT: s_load_dwordx4 s[36:39], s[34:35], 0x0 +; GFX10-NEXT: v_writelane_b32 v40, s34, 2 ; GFX10-NEXT: s_mov_b32 s35, external_void_func_v4i32_inreg@abs32@hi ; GFX10-NEXT: s_mov_b32 s34, external_void_func_v4i32_inreg@abs32@lo -; GFX10-NEXT: v_writelane_b32 v40, s30, 4 -; GFX10-NEXT: v_writelane_b32 v40, s31, 5 +; GFX10-NEXT: s_addk_i32 s32, 0x200 +; GFX10-NEXT: v_writelane_b32 v40, s30, 0 +; GFX10-NEXT: v_writelane_b32 v40, s31, 1 +; GFX10-NEXT: s_waitcnt lgkmcnt(0) +; GFX10-NEXT: s_mov_b32 s0, s36 +; GFX10-NEXT: s_mov_b32 s1, s37 +; GFX10-NEXT: s_mov_b32 s2, s38 +; GFX10-NEXT: s_mov_b32 s3, s39 ; GFX10-NEXT: s_swappc_b64 s[30:31], s[34:35] -; GFX10-NEXT: v_readlane_b32 s31, v40, 5 -; GFX10-NEXT: v_readlane_b32 s30, v40, 4 -; GFX10-NEXT: v_readlane_b32 s7, v40, 3 -; GFX10-NEXT: v_readlane_b32 s6, v40, 2 -; GFX10-NEXT: v_readlane_b32 s5, v40, 1 -; GFX10-NEXT: v_readlane_b32 s4, v40, 0 -; GFX10-NEXT: v_readlane_b32 s34, v40, 6 +; GFX10-NEXT: v_readlane_b32 s31, v40, 1 +; GFX10-NEXT: v_readlane_b32 s30, v40, 0 +; GFX10-NEXT: v_readlane_b32 s34, v40, 2 ; GFX10-NEXT: s_or_saveexec_b32 s35, -1 ; GFX10-NEXT: buffer_load_dword v40, off, s[0:3], s33 ; 4-byte Folded Reload ; GFX10-NEXT: s_waitcnt_depctr 0xffe3 @@ -13687,26 +13199,18 @@ define amdgpu_gfx void @test_call_external_void_func_v4i32_inreg() #0 { ; GFX11-NEXT: s_or_saveexec_b32 s1, -1 ; GFX11-NEXT: scratch_store_b32 off, v40, s33 ; 4-byte Folded Spill ; GFX11-NEXT: s_mov_b32 exec_lo, s1 -; GFX11-NEXT: v_writelane_b32 v40, s0, 6 +; GFX11-NEXT: v_writelane_b32 v40, s0, 2 +; GFX11-NEXT: s_load_b128 s[0:3], s[0:1], 0x0 +; GFX11-NEXT: s_mov_b32 s35, external_void_func_v4i32_inreg@abs32@hi +; GFX11-NEXT: s_mov_b32 s34, external_void_func_v4i32_inreg@abs32@lo ; GFX11-NEXT: s_add_i32 s32, s32, 16 -; GFX11-NEXT: v_writelane_b32 v40, s4, 0 -; GFX11-NEXT: v_writelane_b32 v40, s5, 1 -; GFX11-NEXT: v_writelane_b32 v40, s6, 2 -; GFX11-NEXT: v_writelane_b32 v40, s7, 3 -; GFX11-NEXT: s_load_b128 s[4:7], s[0:1], 0x0 -; GFX11-NEXT: s_mov_b32 s1, external_void_func_v4i32_inreg@abs32@hi -; GFX11-NEXT: s_mov_b32 s0, external_void_func_v4i32_inreg@abs32@lo -; GFX11-NEXT: v_writelane_b32 v40, s30, 4 -; GFX11-NEXT: v_writelane_b32 v40, s31, 5 -; GFX11-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX11-NEXT: v_writelane_b32 v40, s30, 0 +; GFX11-NEXT: v_writelane_b32 v40, s31, 1 +; GFX11-NEXT: s_swappc_b64 s[30:31], s[34:35] ; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_1) -; GFX11-NEXT: v_readlane_b32 s31, v40, 5 -; GFX11-NEXT: v_readlane_b32 s30, v40, 4 -; GFX11-NEXT: v_readlane_b32 s7, v40, 3 -; GFX11-NEXT: v_readlane_b32 s6, v40, 2 -; GFX11-NEXT: v_readlane_b32 s5, v40, 1 -; GFX11-NEXT: v_readlane_b32 s4, v40, 0 -; GFX11-NEXT: v_readlane_b32 s0, v40, 6 +; GFX11-NEXT: v_readlane_b32 s31, v40, 1 +; GFX11-NEXT: v_readlane_b32 s30, v40, 0 +; GFX11-NEXT: v_readlane_b32 s0, v40, 2 ; GFX11-NEXT: s_or_saveexec_b32 s1, -1 ; GFX11-NEXT: scratch_load_b32 v40, off, s33 ; 4-byte Folded Reload ; GFX11-NEXT: s_mov_b32 exec_lo, s1 @@ -13724,25 +13228,17 @@ define amdgpu_gfx void @test_call_external_void_func_v4i32_inreg() #0 { ; GFX10-SCRATCH-NEXT: scratch_store_dword off, v40, s33 ; 4-byte Folded Spill ; GFX10-SCRATCH-NEXT: s_waitcnt_depctr 0xffe3 ; GFX10-SCRATCH-NEXT: s_mov_b32 exec_lo, s1 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s0, 6 +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s0, 2 +; GFX10-SCRATCH-NEXT: s_load_dwordx4 s[0:3], s[0:1], 0x0 +; GFX10-SCRATCH-NEXT: s_mov_b32 s35, external_void_func_v4i32_inreg@abs32@hi +; GFX10-SCRATCH-NEXT: s_mov_b32 s34, external_void_func_v4i32_inreg@abs32@lo ; GFX10-SCRATCH-NEXT: s_add_i32 s32, s32, 16 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s4, 0 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s5, 1 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s6, 2 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s7, 3 -; GFX10-SCRATCH-NEXT: s_load_dwordx4 s[4:7], s[0:1], 0x0 -; GFX10-SCRATCH-NEXT: s_mov_b32 s1, external_void_func_v4i32_inreg@abs32@hi -; GFX10-SCRATCH-NEXT: s_mov_b32 s0, external_void_func_v4i32_inreg@abs32@lo -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s30, 4 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s31, 5 -; GFX10-SCRATCH-NEXT: s_swappc_b64 s[30:31], s[0:1] -; GFX10-SCRATCH-NEXT: v_readlane_b32 s31, v40, 5 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s30, v40, 4 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s7, v40, 3 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s6, v40, 2 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s5, v40, 1 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s4, v40, 0 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s0, v40, 6 +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s30, 0 +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s31, 1 +; GFX10-SCRATCH-NEXT: s_swappc_b64 s[30:31], s[34:35] +; GFX10-SCRATCH-NEXT: v_readlane_b32 s31, v40, 1 +; GFX10-SCRATCH-NEXT: v_readlane_b32 s30, v40, 0 +; GFX10-SCRATCH-NEXT: v_readlane_b32 s0, v40, 2 ; GFX10-SCRATCH-NEXT: s_or_saveexec_b32 s1, -1 ; GFX10-SCRATCH-NEXT: scratch_load_dword v40, off, s33 ; 4-byte Folded Reload ; GFX10-SCRATCH-NEXT: s_waitcnt_depctr 0xffe3 @@ -13765,28 +13261,20 @@ define amdgpu_gfx void @test_call_external_void_func_v4i32_imm_inreg() #0 { ; GFX9-NEXT: s_or_saveexec_b64 s[36:37], -1 ; GFX9-NEXT: buffer_store_dword v40, off, s[0:3], s33 ; 4-byte Folded Spill ; GFX9-NEXT: s_mov_b64 exec, s[36:37] -; GFX9-NEXT: v_writelane_b32 v40, s34, 6 -; GFX9-NEXT: v_writelane_b32 v40, s4, 0 -; GFX9-NEXT: v_writelane_b32 v40, s5, 1 -; GFX9-NEXT: v_writelane_b32 v40, s6, 2 -; GFX9-NEXT: v_writelane_b32 v40, s7, 3 -; GFX9-NEXT: v_writelane_b32 v40, s30, 4 +; GFX9-NEXT: v_writelane_b32 v40, s34, 2 +; GFX9-NEXT: v_writelane_b32 v40, s30, 0 ; GFX9-NEXT: s_mov_b32 s35, external_void_func_v4i32_inreg@abs32@hi ; GFX9-NEXT: s_mov_b32 s34, external_void_func_v4i32_inreg@abs32@lo -; GFX9-NEXT: s_mov_b32 s4, 1 -; GFX9-NEXT: s_mov_b32 s5, 2 -; GFX9-NEXT: s_mov_b32 s6, 3 -; GFX9-NEXT: s_mov_b32 s7, 4 +; GFX9-NEXT: s_mov_b32 s0, 1 +; GFX9-NEXT: s_mov_b32 s1, 2 +; GFX9-NEXT: s_mov_b32 s2, 3 +; GFX9-NEXT: s_mov_b32 s3, 4 ; GFX9-NEXT: s_addk_i32 s32, 0x400 -; GFX9-NEXT: v_writelane_b32 v40, s31, 5 +; GFX9-NEXT: v_writelane_b32 v40, s31, 1 ; GFX9-NEXT: s_swappc_b64 s[30:31], s[34:35] -; GFX9-NEXT: v_readlane_b32 s31, v40, 5 -; GFX9-NEXT: v_readlane_b32 s30, v40, 4 -; GFX9-NEXT: v_readlane_b32 s7, v40, 3 -; GFX9-NEXT: v_readlane_b32 s6, v40, 2 -; GFX9-NEXT: v_readlane_b32 s5, v40, 1 -; GFX9-NEXT: v_readlane_b32 s4, v40, 0 -; GFX9-NEXT: v_readlane_b32 s34, v40, 6 +; GFX9-NEXT: v_readlane_b32 s31, v40, 1 +; GFX9-NEXT: v_readlane_b32 s30, v40, 0 +; GFX9-NEXT: v_readlane_b32 s34, v40, 2 ; GFX9-NEXT: s_or_saveexec_b64 s[36:37], -1 ; GFX9-NEXT: buffer_load_dword v40, off, s[0:3], s33 ; 4-byte Folded Reload ; GFX9-NEXT: s_mov_b64 exec, s[36:37] @@ -13804,28 +13292,20 @@ define amdgpu_gfx void @test_call_external_void_func_v4i32_imm_inreg() #0 { ; GFX10-NEXT: buffer_store_dword v40, off, s[0:3], s33 ; 4-byte Folded Spill ; GFX10-NEXT: s_waitcnt_depctr 0xffe3 ; GFX10-NEXT: s_mov_b32 exec_lo, s35 -; GFX10-NEXT: v_writelane_b32 v40, s34, 6 +; GFX10-NEXT: v_writelane_b32 v40, s34, 2 ; GFX10-NEXT: s_mov_b32 s35, external_void_func_v4i32_inreg@abs32@hi ; GFX10-NEXT: s_mov_b32 s34, external_void_func_v4i32_inreg@abs32@lo +; GFX10-NEXT: s_mov_b32 s0, 1 +; GFX10-NEXT: s_mov_b32 s1, 2 +; GFX10-NEXT: v_writelane_b32 v40, s30, 0 +; GFX10-NEXT: s_mov_b32 s2, 3 +; GFX10-NEXT: s_mov_b32 s3, 4 ; GFX10-NEXT: s_addk_i32 s32, 0x200 -; GFX10-NEXT: v_writelane_b32 v40, s4, 0 -; GFX10-NEXT: s_mov_b32 s4, 1 -; GFX10-NEXT: v_writelane_b32 v40, s5, 1 -; GFX10-NEXT: s_mov_b32 s5, 2 -; GFX10-NEXT: v_writelane_b32 v40, s6, 2 -; GFX10-NEXT: s_mov_b32 s6, 3 -; GFX10-NEXT: v_writelane_b32 v40, s7, 3 -; GFX10-NEXT: s_mov_b32 s7, 4 -; GFX10-NEXT: v_writelane_b32 v40, s30, 4 -; GFX10-NEXT: v_writelane_b32 v40, s31, 5 +; GFX10-NEXT: v_writelane_b32 v40, s31, 1 ; GFX10-NEXT: s_swappc_b64 s[30:31], s[34:35] -; GFX10-NEXT: v_readlane_b32 s31, v40, 5 -; GFX10-NEXT: v_readlane_b32 s30, v40, 4 -; GFX10-NEXT: v_readlane_b32 s7, v40, 3 -; GFX10-NEXT: v_readlane_b32 s6, v40, 2 -; GFX10-NEXT: v_readlane_b32 s5, v40, 1 -; GFX10-NEXT: v_readlane_b32 s4, v40, 0 -; GFX10-NEXT: v_readlane_b32 s34, v40, 6 +; GFX10-NEXT: v_readlane_b32 s31, v40, 1 +; GFX10-NEXT: v_readlane_b32 s30, v40, 0 +; GFX10-NEXT: v_readlane_b32 s34, v40, 2 ; GFX10-NEXT: s_or_saveexec_b32 s35, -1 ; GFX10-NEXT: buffer_load_dword v40, off, s[0:3], s33 ; 4-byte Folded Reload ; GFX10-NEXT: s_waitcnt_depctr 0xffe3 @@ -13843,29 +13323,21 @@ define amdgpu_gfx void @test_call_external_void_func_v4i32_imm_inreg() #0 { ; GFX11-NEXT: s_or_saveexec_b32 s1, -1 ; GFX11-NEXT: scratch_store_b32 off, v40, s33 ; 4-byte Folded Spill ; GFX11-NEXT: s_mov_b32 exec_lo, s1 -; GFX11-NEXT: v_writelane_b32 v40, s0, 6 -; GFX11-NEXT: s_mov_b32 s1, external_void_func_v4i32_inreg@abs32@hi -; GFX11-NEXT: s_mov_b32 s0, external_void_func_v4i32_inreg@abs32@lo +; GFX11-NEXT: v_writelane_b32 v40, s0, 2 +; GFX11-NEXT: s_mov_b32 s35, external_void_func_v4i32_inreg@abs32@hi +; GFX11-NEXT: s_mov_b32 s34, external_void_func_v4i32_inreg@abs32@lo +; GFX11-NEXT: s_mov_b32 s0, 1 +; GFX11-NEXT: s_mov_b32 s1, 2 +; GFX11-NEXT: v_writelane_b32 v40, s30, 0 +; GFX11-NEXT: s_mov_b32 s2, 3 +; GFX11-NEXT: s_mov_b32 s3, 4 ; GFX11-NEXT: s_add_i32 s32, s32, 16 -; GFX11-NEXT: v_writelane_b32 v40, s4, 0 -; GFX11-NEXT: s_mov_b32 s4, 1 -; GFX11-NEXT: v_writelane_b32 v40, s5, 1 -; GFX11-NEXT: s_mov_b32 s5, 2 -; GFX11-NEXT: v_writelane_b32 v40, s6, 2 -; GFX11-NEXT: s_mov_b32 s6, 3 -; GFX11-NEXT: v_writelane_b32 v40, s7, 3 -; GFX11-NEXT: s_mov_b32 s7, 4 -; GFX11-NEXT: v_writelane_b32 v40, s30, 4 -; GFX11-NEXT: v_writelane_b32 v40, s31, 5 -; GFX11-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX11-NEXT: v_writelane_b32 v40, s31, 1 +; GFX11-NEXT: s_swappc_b64 s[30:31], s[34:35] ; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_1) -; GFX11-NEXT: v_readlane_b32 s31, v40, 5 -; GFX11-NEXT: v_readlane_b32 s30, v40, 4 -; GFX11-NEXT: v_readlane_b32 s7, v40, 3 -; GFX11-NEXT: v_readlane_b32 s6, v40, 2 -; GFX11-NEXT: v_readlane_b32 s5, v40, 1 -; GFX11-NEXT: v_readlane_b32 s4, v40, 0 -; GFX11-NEXT: v_readlane_b32 s0, v40, 6 +; GFX11-NEXT: v_readlane_b32 s31, v40, 1 +; GFX11-NEXT: v_readlane_b32 s30, v40, 0 +; GFX11-NEXT: v_readlane_b32 s0, v40, 2 ; GFX11-NEXT: s_or_saveexec_b32 s1, -1 ; GFX11-NEXT: scratch_load_b32 v40, off, s33 ; 4-byte Folded Reload ; GFX11-NEXT: s_mov_b32 exec_lo, s1 @@ -13883,28 +13355,20 @@ define amdgpu_gfx void @test_call_external_void_func_v4i32_imm_inreg() #0 { ; GFX10-SCRATCH-NEXT: scratch_store_dword off, v40, s33 ; 4-byte Folded Spill ; GFX10-SCRATCH-NEXT: s_waitcnt_depctr 0xffe3 ; GFX10-SCRATCH-NEXT: s_mov_b32 exec_lo, s1 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s0, 6 -; GFX10-SCRATCH-NEXT: s_mov_b32 s1, external_void_func_v4i32_inreg@abs32@hi -; GFX10-SCRATCH-NEXT: s_mov_b32 s0, external_void_func_v4i32_inreg@abs32@lo +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s0, 2 +; GFX10-SCRATCH-NEXT: s_mov_b32 s35, external_void_func_v4i32_inreg@abs32@hi +; GFX10-SCRATCH-NEXT: s_mov_b32 s34, external_void_func_v4i32_inreg@abs32@lo +; GFX10-SCRATCH-NEXT: s_mov_b32 s0, 1 +; GFX10-SCRATCH-NEXT: s_mov_b32 s1, 2 +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s30, 0 +; GFX10-SCRATCH-NEXT: s_mov_b32 s2, 3 +; GFX10-SCRATCH-NEXT: s_mov_b32 s3, 4 ; GFX10-SCRATCH-NEXT: s_add_i32 s32, s32, 16 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s4, 0 -; GFX10-SCRATCH-NEXT: s_mov_b32 s4, 1 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s5, 1 -; GFX10-SCRATCH-NEXT: s_mov_b32 s5, 2 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s6, 2 -; GFX10-SCRATCH-NEXT: s_mov_b32 s6, 3 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s7, 3 -; GFX10-SCRATCH-NEXT: s_mov_b32 s7, 4 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s30, 4 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s31, 5 -; GFX10-SCRATCH-NEXT: s_swappc_b64 s[30:31], s[0:1] -; GFX10-SCRATCH-NEXT: v_readlane_b32 s31, v40, 5 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s30, v40, 4 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s7, v40, 3 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s6, v40, 2 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s5, v40, 1 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s4, v40, 0 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s0, v40, 6 +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s31, 1 +; GFX10-SCRATCH-NEXT: s_swappc_b64 s[30:31], s[34:35] +; GFX10-SCRATCH-NEXT: v_readlane_b32 s31, v40, 1 +; GFX10-SCRATCH-NEXT: v_readlane_b32 s30, v40, 0 +; GFX10-SCRATCH-NEXT: v_readlane_b32 s0, v40, 2 ; GFX10-SCRATCH-NEXT: s_or_saveexec_b32 s1, -1 ; GFX10-SCRATCH-NEXT: scratch_load_dword v40, off, s33 ; 4-byte Folded Reload ; GFX10-SCRATCH-NEXT: s_waitcnt_depctr 0xffe3 @@ -13926,31 +13390,23 @@ define amdgpu_gfx void @test_call_external_void_func_v5i32_imm_inreg() #0 { ; GFX9-NEXT: s_or_saveexec_b64 s[36:37], -1 ; GFX9-NEXT: buffer_store_dword v40, off, s[0:3], s33 ; 4-byte Folded Spill ; GFX9-NEXT: s_mov_b64 exec, s[36:37] -; GFX9-NEXT: v_writelane_b32 v40, s34, 7 +; GFX9-NEXT: v_writelane_b32 v40, s34, 3 ; GFX9-NEXT: v_writelane_b32 v40, s4, 0 -; GFX9-NEXT: v_writelane_b32 v40, s5, 1 -; GFX9-NEXT: v_writelane_b32 v40, s6, 2 -; GFX9-NEXT: v_writelane_b32 v40, s7, 3 -; GFX9-NEXT: v_writelane_b32 v40, s8, 4 -; GFX9-NEXT: v_writelane_b32 v40, s30, 5 +; GFX9-NEXT: v_writelane_b32 v40, s30, 1 ; GFX9-NEXT: s_mov_b32 s35, external_void_func_v5i32_inreg@abs32@hi ; GFX9-NEXT: s_mov_b32 s34, external_void_func_v5i32_inreg@abs32@lo -; GFX9-NEXT: s_mov_b32 s4, 1 -; GFX9-NEXT: s_mov_b32 s5, 2 -; GFX9-NEXT: s_mov_b32 s6, 3 -; GFX9-NEXT: s_mov_b32 s7, 4 -; GFX9-NEXT: s_mov_b32 s8, 5 +; GFX9-NEXT: s_mov_b32 s0, 1 +; GFX9-NEXT: s_mov_b32 s1, 2 +; GFX9-NEXT: s_mov_b32 s2, 3 +; GFX9-NEXT: s_mov_b32 s3, 4 +; GFX9-NEXT: s_mov_b32 s4, 5 ; GFX9-NEXT: s_addk_i32 s32, 0x400 -; GFX9-NEXT: v_writelane_b32 v40, s31, 6 +; GFX9-NEXT: v_writelane_b32 v40, s31, 2 ; GFX9-NEXT: s_swappc_b64 s[30:31], s[34:35] -; GFX9-NEXT: v_readlane_b32 s31, v40, 6 -; GFX9-NEXT: v_readlane_b32 s30, v40, 5 -; GFX9-NEXT: v_readlane_b32 s8, v40, 4 -; GFX9-NEXT: v_readlane_b32 s7, v40, 3 -; GFX9-NEXT: v_readlane_b32 s6, v40, 2 -; GFX9-NEXT: v_readlane_b32 s5, v40, 1 +; GFX9-NEXT: v_readlane_b32 s31, v40, 2 +; GFX9-NEXT: v_readlane_b32 s30, v40, 1 ; GFX9-NEXT: v_readlane_b32 s4, v40, 0 -; GFX9-NEXT: v_readlane_b32 s34, v40, 7 +; GFX9-NEXT: v_readlane_b32 s34, v40, 3 ; GFX9-NEXT: s_or_saveexec_b64 s[36:37], -1 ; GFX9-NEXT: buffer_load_dword v40, off, s[0:3], s33 ; 4-byte Folded Reload ; GFX9-NEXT: s_mov_b64 exec, s[36:37] @@ -13965,34 +13421,26 @@ define amdgpu_gfx void @test_call_external_void_func_v5i32_imm_inreg() #0 { ; GFX10-NEXT: s_mov_b32 s34, s33 ; GFX10-NEXT: s_mov_b32 s33, s32 ; GFX10-NEXT: s_or_saveexec_b32 s35, -1 -; GFX10-NEXT: buffer_store_dword v40, off, s[0:3], s33 ; 4-byte Folded Spill -; GFX10-NEXT: s_waitcnt_depctr 0xffe3 -; GFX10-NEXT: s_mov_b32 exec_lo, s35 -; GFX10-NEXT: v_writelane_b32 v40, s34, 7 -; GFX10-NEXT: s_mov_b32 s35, external_void_func_v5i32_inreg@abs32@hi -; GFX10-NEXT: s_mov_b32 s34, external_void_func_v5i32_inreg@abs32@lo -; GFX10-NEXT: s_addk_i32 s32, 0x200 -; GFX10-NEXT: v_writelane_b32 v40, s4, 0 -; GFX10-NEXT: s_mov_b32 s4, 1 -; GFX10-NEXT: v_writelane_b32 v40, s5, 1 -; GFX10-NEXT: s_mov_b32 s5, 2 -; GFX10-NEXT: v_writelane_b32 v40, s6, 2 -; GFX10-NEXT: s_mov_b32 s6, 3 -; GFX10-NEXT: v_writelane_b32 v40, s7, 3 -; GFX10-NEXT: s_mov_b32 s7, 4 -; GFX10-NEXT: v_writelane_b32 v40, s8, 4 -; GFX10-NEXT: s_mov_b32 s8, 5 -; GFX10-NEXT: v_writelane_b32 v40, s30, 5 -; GFX10-NEXT: v_writelane_b32 v40, s31, 6 +; GFX10-NEXT: buffer_store_dword v40, off, s[0:3], s33 ; 4-byte Folded Spill +; GFX10-NEXT: s_waitcnt_depctr 0xffe3 +; GFX10-NEXT: s_mov_b32 exec_lo, s35 +; GFX10-NEXT: v_writelane_b32 v40, s34, 3 +; GFX10-NEXT: s_mov_b32 s35, external_void_func_v5i32_inreg@abs32@hi +; GFX10-NEXT: s_mov_b32 s34, external_void_func_v5i32_inreg@abs32@lo +; GFX10-NEXT: s_mov_b32 s0, 1 +; GFX10-NEXT: s_mov_b32 s1, 2 +; GFX10-NEXT: v_writelane_b32 v40, s4, 0 +; GFX10-NEXT: s_mov_b32 s2, 3 +; GFX10-NEXT: s_mov_b32 s3, 4 +; GFX10-NEXT: s_mov_b32 s4, 5 +; GFX10-NEXT: s_addk_i32 s32, 0x200 +; GFX10-NEXT: v_writelane_b32 v40, s30, 1 +; GFX10-NEXT: v_writelane_b32 v40, s31, 2 ; GFX10-NEXT: s_swappc_b64 s[30:31], s[34:35] -; GFX10-NEXT: v_readlane_b32 s31, v40, 6 -; GFX10-NEXT: v_readlane_b32 s30, v40, 5 -; GFX10-NEXT: v_readlane_b32 s8, v40, 4 -; GFX10-NEXT: v_readlane_b32 s7, v40, 3 -; GFX10-NEXT: v_readlane_b32 s6, v40, 2 -; GFX10-NEXT: v_readlane_b32 s5, v40, 1 +; GFX10-NEXT: v_readlane_b32 s31, v40, 2 +; GFX10-NEXT: v_readlane_b32 s30, v40, 1 ; GFX10-NEXT: v_readlane_b32 s4, v40, 0 -; GFX10-NEXT: v_readlane_b32 s34, v40, 7 +; GFX10-NEXT: v_readlane_b32 s34, v40, 3 ; GFX10-NEXT: s_or_saveexec_b32 s35, -1 ; GFX10-NEXT: buffer_load_dword v40, off, s[0:3], s33 ; 4-byte Folded Reload ; GFX10-NEXT: s_waitcnt_depctr 0xffe3 @@ -14010,32 +13458,24 @@ define amdgpu_gfx void @test_call_external_void_func_v5i32_imm_inreg() #0 { ; GFX11-NEXT: s_or_saveexec_b32 s1, -1 ; GFX11-NEXT: scratch_store_b32 off, v40, s33 ; 4-byte Folded Spill ; GFX11-NEXT: s_mov_b32 exec_lo, s1 -; GFX11-NEXT: v_writelane_b32 v40, s0, 7 -; GFX11-NEXT: s_mov_b32 s1, external_void_func_v5i32_inreg@abs32@hi -; GFX11-NEXT: s_mov_b32 s0, external_void_func_v5i32_inreg@abs32@lo -; GFX11-NEXT: s_add_i32 s32, s32, 16 +; GFX11-NEXT: v_writelane_b32 v40, s0, 3 +; GFX11-NEXT: s_mov_b32 s35, external_void_func_v5i32_inreg@abs32@hi +; GFX11-NEXT: s_mov_b32 s34, external_void_func_v5i32_inreg@abs32@lo +; GFX11-NEXT: s_mov_b32 s0, 1 +; GFX11-NEXT: s_mov_b32 s1, 2 ; GFX11-NEXT: v_writelane_b32 v40, s4, 0 -; GFX11-NEXT: s_mov_b32 s4, 1 -; GFX11-NEXT: v_writelane_b32 v40, s5, 1 -; GFX11-NEXT: s_mov_b32 s5, 2 -; GFX11-NEXT: v_writelane_b32 v40, s6, 2 -; GFX11-NEXT: s_mov_b32 s6, 3 -; GFX11-NEXT: v_writelane_b32 v40, s7, 3 -; GFX11-NEXT: s_mov_b32 s7, 4 -; GFX11-NEXT: v_writelane_b32 v40, s8, 4 -; GFX11-NEXT: s_mov_b32 s8, 5 -; GFX11-NEXT: v_writelane_b32 v40, s30, 5 -; GFX11-NEXT: v_writelane_b32 v40, s31, 6 -; GFX11-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX11-NEXT: s_mov_b32 s2, 3 +; GFX11-NEXT: s_mov_b32 s3, 4 +; GFX11-NEXT: s_mov_b32 s4, 5 +; GFX11-NEXT: s_add_i32 s32, s32, 16 +; GFX11-NEXT: v_writelane_b32 v40, s30, 1 +; GFX11-NEXT: v_writelane_b32 v40, s31, 2 +; GFX11-NEXT: s_swappc_b64 s[30:31], s[34:35] ; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_1) -; GFX11-NEXT: v_readlane_b32 s31, v40, 6 -; GFX11-NEXT: v_readlane_b32 s30, v40, 5 -; GFX11-NEXT: v_readlane_b32 s8, v40, 4 -; GFX11-NEXT: v_readlane_b32 s7, v40, 3 -; GFX11-NEXT: v_readlane_b32 s6, v40, 2 -; GFX11-NEXT: v_readlane_b32 s5, v40, 1 +; GFX11-NEXT: v_readlane_b32 s31, v40, 2 +; GFX11-NEXT: v_readlane_b32 s30, v40, 1 ; GFX11-NEXT: v_readlane_b32 s4, v40, 0 -; GFX11-NEXT: v_readlane_b32 s0, v40, 7 +; GFX11-NEXT: v_readlane_b32 s0, v40, 3 ; GFX11-NEXT: s_or_saveexec_b32 s1, -1 ; GFX11-NEXT: scratch_load_b32 v40, off, s33 ; 4-byte Folded Reload ; GFX11-NEXT: s_mov_b32 exec_lo, s1 @@ -14053,31 +13493,23 @@ define amdgpu_gfx void @test_call_external_void_func_v5i32_imm_inreg() #0 { ; GFX10-SCRATCH-NEXT: scratch_store_dword off, v40, s33 ; 4-byte Folded Spill ; GFX10-SCRATCH-NEXT: s_waitcnt_depctr 0xffe3 ; GFX10-SCRATCH-NEXT: s_mov_b32 exec_lo, s1 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s0, 7 -; GFX10-SCRATCH-NEXT: s_mov_b32 s1, external_void_func_v5i32_inreg@abs32@hi -; GFX10-SCRATCH-NEXT: s_mov_b32 s0, external_void_func_v5i32_inreg@abs32@lo -; GFX10-SCRATCH-NEXT: s_add_i32 s32, s32, 16 +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s0, 3 +; GFX10-SCRATCH-NEXT: s_mov_b32 s35, external_void_func_v5i32_inreg@abs32@hi +; GFX10-SCRATCH-NEXT: s_mov_b32 s34, external_void_func_v5i32_inreg@abs32@lo +; GFX10-SCRATCH-NEXT: s_mov_b32 s0, 1 +; GFX10-SCRATCH-NEXT: s_mov_b32 s1, 2 ; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s4, 0 -; GFX10-SCRATCH-NEXT: s_mov_b32 s4, 1 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s5, 1 -; GFX10-SCRATCH-NEXT: s_mov_b32 s5, 2 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s6, 2 -; GFX10-SCRATCH-NEXT: s_mov_b32 s6, 3 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s7, 3 -; GFX10-SCRATCH-NEXT: s_mov_b32 s7, 4 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s8, 4 -; GFX10-SCRATCH-NEXT: s_mov_b32 s8, 5 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s30, 5 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s31, 6 -; GFX10-SCRATCH-NEXT: s_swappc_b64 s[30:31], s[0:1] -; GFX10-SCRATCH-NEXT: v_readlane_b32 s31, v40, 6 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s30, v40, 5 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s8, v40, 4 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s7, v40, 3 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s6, v40, 2 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s5, v40, 1 +; GFX10-SCRATCH-NEXT: s_mov_b32 s2, 3 +; GFX10-SCRATCH-NEXT: s_mov_b32 s3, 4 +; GFX10-SCRATCH-NEXT: s_mov_b32 s4, 5 +; GFX10-SCRATCH-NEXT: s_add_i32 s32, s32, 16 +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s30, 1 +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s31, 2 +; GFX10-SCRATCH-NEXT: s_swappc_b64 s[30:31], s[34:35] +; GFX10-SCRATCH-NEXT: v_readlane_b32 s31, v40, 2 +; GFX10-SCRATCH-NEXT: v_readlane_b32 s30, v40, 1 ; GFX10-SCRATCH-NEXT: v_readlane_b32 s4, v40, 0 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s0, v40, 7 +; GFX10-SCRATCH-NEXT: v_readlane_b32 s0, v40, 3 ; GFX10-SCRATCH-NEXT: s_or_saveexec_b32 s1, -1 ; GFX10-SCRATCH-NEXT: scratch_load_dword v40, off, s33 ; 4-byte Folded Reload ; GFX10-SCRATCH-NEXT: s_waitcnt_depctr 0xffe3 @@ -14099,35 +13531,36 @@ define amdgpu_gfx void @test_call_external_void_func_v8i32_inreg() #0 { ; GFX9-NEXT: s_or_saveexec_b64 s[36:37], -1 ; GFX9-NEXT: buffer_store_dword v40, off, s[0:3], s33 ; 4-byte Folded Spill ; GFX9-NEXT: s_mov_b64 exec, s[36:37] -; GFX9-NEXT: v_writelane_b32 v40, s34, 10 +; GFX9-NEXT: v_writelane_b32 v40, s34, 6 +; GFX9-NEXT: s_load_dwordx2 s[34:35], s[34:35], 0x0 ; GFX9-NEXT: v_writelane_b32 v40, s4, 0 ; GFX9-NEXT: v_writelane_b32 v40, s5, 1 ; GFX9-NEXT: v_writelane_b32 v40, s6, 2 -; GFX9-NEXT: s_load_dwordx2 s[34:35], s[34:35], 0x0 ; GFX9-NEXT: v_writelane_b32 v40, s7, 3 -; GFX9-NEXT: v_writelane_b32 v40, s8, 4 -; GFX9-NEXT: v_writelane_b32 v40, s9, 5 -; GFX9-NEXT: v_writelane_b32 v40, s10, 6 -; GFX9-NEXT: v_writelane_b32 v40, s11, 7 ; GFX9-NEXT: s_waitcnt lgkmcnt(0) -; GFX9-NEXT: s_load_dwordx8 s[4:11], s[34:35], 0x0 -; GFX9-NEXT: v_writelane_b32 v40, s30, 8 +; GFX9-NEXT: s_load_dwordx8 s[36:43], s[34:35], 0x0 +; GFX9-NEXT: v_writelane_b32 v40, s30, 4 ; GFX9-NEXT: s_mov_b32 s35, external_void_func_v8i32_inreg@abs32@hi ; GFX9-NEXT: s_mov_b32 s34, external_void_func_v8i32_inreg@abs32@lo ; GFX9-NEXT: s_addk_i32 s32, 0x400 -; GFX9-NEXT: v_writelane_b32 v40, s31, 9 +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: s_mov_b32 s0, s36 +; GFX9-NEXT: s_mov_b32 s1, s37 +; GFX9-NEXT: s_mov_b32 s2, s38 +; GFX9-NEXT: s_mov_b32 s3, s39 +; GFX9-NEXT: s_mov_b32 s4, s40 +; GFX9-NEXT: s_mov_b32 s5, s41 +; GFX9-NEXT: s_mov_b32 s6, s42 +; GFX9-NEXT: s_mov_b32 s7, s43 +; GFX9-NEXT: v_writelane_b32 v40, s31, 5 ; GFX9-NEXT: s_swappc_b64 s[30:31], s[34:35] -; GFX9-NEXT: v_readlane_b32 s31, v40, 9 -; GFX9-NEXT: v_readlane_b32 s30, v40, 8 -; GFX9-NEXT: v_readlane_b32 s11, v40, 7 -; GFX9-NEXT: v_readlane_b32 s10, v40, 6 -; GFX9-NEXT: v_readlane_b32 s9, v40, 5 -; GFX9-NEXT: v_readlane_b32 s8, v40, 4 +; GFX9-NEXT: v_readlane_b32 s31, v40, 5 +; GFX9-NEXT: v_readlane_b32 s30, v40, 4 ; GFX9-NEXT: v_readlane_b32 s7, v40, 3 ; GFX9-NEXT: v_readlane_b32 s6, v40, 2 ; GFX9-NEXT: v_readlane_b32 s5, v40, 1 ; GFX9-NEXT: v_readlane_b32 s4, v40, 0 -; GFX9-NEXT: v_readlane_b32 s34, v40, 10 +; GFX9-NEXT: v_readlane_b32 s34, v40, 6 ; GFX9-NEXT: s_or_saveexec_b64 s[36:37], -1 ; GFX9-NEXT: buffer_load_dword v40, off, s[0:3], s33 ; 4-byte Folded Reload ; GFX9-NEXT: s_mov_b64 exec, s[36:37] @@ -14145,35 +13578,36 @@ define amdgpu_gfx void @test_call_external_void_func_v8i32_inreg() #0 { ; GFX10-NEXT: buffer_store_dword v40, off, s[0:3], s33 ; 4-byte Folded Spill ; GFX10-NEXT: s_waitcnt_depctr 0xffe3 ; GFX10-NEXT: s_mov_b32 exec_lo, s35 -; GFX10-NEXT: v_writelane_b32 v40, s34, 10 +; GFX10-NEXT: v_writelane_b32 v40, s34, 6 ; GFX10-NEXT: s_load_dwordx2 s[34:35], s[34:35], 0x0 ; GFX10-NEXT: s_addk_i32 s32, 0x200 ; GFX10-NEXT: v_writelane_b32 v40, s4, 0 ; GFX10-NEXT: v_writelane_b32 v40, s5, 1 ; GFX10-NEXT: v_writelane_b32 v40, s6, 2 ; GFX10-NEXT: v_writelane_b32 v40, s7, 3 -; GFX10-NEXT: v_writelane_b32 v40, s8, 4 -; GFX10-NEXT: v_writelane_b32 v40, s9, 5 -; GFX10-NEXT: v_writelane_b32 v40, s10, 6 -; GFX10-NEXT: v_writelane_b32 v40, s11, 7 ; GFX10-NEXT: s_waitcnt lgkmcnt(0) -; GFX10-NEXT: s_load_dwordx8 s[4:11], s[34:35], 0x0 +; GFX10-NEXT: s_load_dwordx8 s[36:43], s[34:35], 0x0 ; GFX10-NEXT: s_mov_b32 s35, external_void_func_v8i32_inreg@abs32@hi ; GFX10-NEXT: s_mov_b32 s34, external_void_func_v8i32_inreg@abs32@lo -; GFX10-NEXT: v_writelane_b32 v40, s30, 8 -; GFX10-NEXT: v_writelane_b32 v40, s31, 9 +; GFX10-NEXT: v_writelane_b32 v40, s30, 4 +; GFX10-NEXT: v_writelane_b32 v40, s31, 5 +; GFX10-NEXT: s_waitcnt lgkmcnt(0) +; GFX10-NEXT: s_mov_b32 s0, s36 +; GFX10-NEXT: s_mov_b32 s1, s37 +; GFX10-NEXT: s_mov_b32 s2, s38 +; GFX10-NEXT: s_mov_b32 s3, s39 +; GFX10-NEXT: s_mov_b32 s4, s40 +; GFX10-NEXT: s_mov_b32 s5, s41 +; GFX10-NEXT: s_mov_b32 s6, s42 +; GFX10-NEXT: s_mov_b32 s7, s43 ; GFX10-NEXT: s_swappc_b64 s[30:31], s[34:35] -; GFX10-NEXT: v_readlane_b32 s31, v40, 9 -; GFX10-NEXT: v_readlane_b32 s30, v40, 8 -; GFX10-NEXT: v_readlane_b32 s11, v40, 7 -; GFX10-NEXT: v_readlane_b32 s10, v40, 6 -; GFX10-NEXT: v_readlane_b32 s9, v40, 5 -; GFX10-NEXT: v_readlane_b32 s8, v40, 4 +; GFX10-NEXT: v_readlane_b32 s31, v40, 5 +; GFX10-NEXT: v_readlane_b32 s30, v40, 4 ; GFX10-NEXT: v_readlane_b32 s7, v40, 3 ; GFX10-NEXT: v_readlane_b32 s6, v40, 2 ; GFX10-NEXT: v_readlane_b32 s5, v40, 1 ; GFX10-NEXT: v_readlane_b32 s4, v40, 0 -; GFX10-NEXT: v_readlane_b32 s34, v40, 10 +; GFX10-NEXT: v_readlane_b32 s34, v40, 6 ; GFX10-NEXT: s_or_saveexec_b32 s35, -1 ; GFX10-NEXT: buffer_load_dword v40, off, s[0:3], s33 ; 4-byte Folded Reload ; GFX10-NEXT: s_waitcnt_depctr 0xffe3 @@ -14191,36 +13625,28 @@ define amdgpu_gfx void @test_call_external_void_func_v8i32_inreg() #0 { ; GFX11-NEXT: s_or_saveexec_b32 s1, -1 ; GFX11-NEXT: scratch_store_b32 off, v40, s33 ; 4-byte Folded Spill ; GFX11-NEXT: s_mov_b32 exec_lo, s1 -; GFX11-NEXT: v_writelane_b32 v40, s0, 10 +; GFX11-NEXT: v_writelane_b32 v40, s0, 6 ; GFX11-NEXT: s_load_b64 s[0:1], s[0:1], 0x0 +; GFX11-NEXT: s_mov_b32 s35, external_void_func_v8i32_inreg@abs32@hi +; GFX11-NEXT: s_mov_b32 s34, external_void_func_v8i32_inreg@abs32@lo ; GFX11-NEXT: s_add_i32 s32, s32, 16 ; GFX11-NEXT: v_writelane_b32 v40, s4, 0 ; GFX11-NEXT: v_writelane_b32 v40, s5, 1 ; GFX11-NEXT: v_writelane_b32 v40, s6, 2 ; GFX11-NEXT: v_writelane_b32 v40, s7, 3 -; GFX11-NEXT: v_writelane_b32 v40, s8, 4 -; GFX11-NEXT: v_writelane_b32 v40, s9, 5 -; GFX11-NEXT: v_writelane_b32 v40, s10, 6 -; GFX11-NEXT: v_writelane_b32 v40, s11, 7 ; GFX11-NEXT: s_waitcnt lgkmcnt(0) -; GFX11-NEXT: s_load_b256 s[4:11], s[0:1], 0x0 -; GFX11-NEXT: s_mov_b32 s1, external_void_func_v8i32_inreg@abs32@hi -; GFX11-NEXT: s_mov_b32 s0, external_void_func_v8i32_inreg@abs32@lo -; GFX11-NEXT: v_writelane_b32 v40, s30, 8 -; GFX11-NEXT: v_writelane_b32 v40, s31, 9 -; GFX11-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX11-NEXT: s_load_b256 s[0:7], s[0:1], 0x0 +; GFX11-NEXT: v_writelane_b32 v40, s30, 4 +; GFX11-NEXT: v_writelane_b32 v40, s31, 5 +; GFX11-NEXT: s_swappc_b64 s[30:31], s[34:35] ; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_1) -; GFX11-NEXT: v_readlane_b32 s31, v40, 9 -; GFX11-NEXT: v_readlane_b32 s30, v40, 8 -; GFX11-NEXT: v_readlane_b32 s11, v40, 7 -; GFX11-NEXT: v_readlane_b32 s10, v40, 6 -; GFX11-NEXT: v_readlane_b32 s9, v40, 5 -; GFX11-NEXT: v_readlane_b32 s8, v40, 4 +; GFX11-NEXT: v_readlane_b32 s31, v40, 5 +; GFX11-NEXT: v_readlane_b32 s30, v40, 4 ; GFX11-NEXT: v_readlane_b32 s7, v40, 3 ; GFX11-NEXT: v_readlane_b32 s6, v40, 2 ; GFX11-NEXT: v_readlane_b32 s5, v40, 1 ; GFX11-NEXT: v_readlane_b32 s4, v40, 0 -; GFX11-NEXT: v_readlane_b32 s0, v40, 10 +; GFX11-NEXT: v_readlane_b32 s0, v40, 6 ; GFX11-NEXT: s_or_saveexec_b32 s1, -1 ; GFX11-NEXT: scratch_load_b32 v40, off, s33 ; 4-byte Folded Reload ; GFX11-NEXT: s_mov_b32 exec_lo, s1 @@ -14238,35 +13664,27 @@ define amdgpu_gfx void @test_call_external_void_func_v8i32_inreg() #0 { ; GFX10-SCRATCH-NEXT: scratch_store_dword off, v40, s33 ; 4-byte Folded Spill ; GFX10-SCRATCH-NEXT: s_waitcnt_depctr 0xffe3 ; GFX10-SCRATCH-NEXT: s_mov_b32 exec_lo, s1 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s0, 10 +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s0, 6 ; GFX10-SCRATCH-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x0 +; GFX10-SCRATCH-NEXT: s_mov_b32 s35, external_void_func_v8i32_inreg@abs32@hi +; GFX10-SCRATCH-NEXT: s_mov_b32 s34, external_void_func_v8i32_inreg@abs32@lo ; GFX10-SCRATCH-NEXT: s_add_i32 s32, s32, 16 ; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s4, 0 ; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s5, 1 ; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s6, 2 ; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s7, 3 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s8, 4 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s9, 5 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s10, 6 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s11, 7 ; GFX10-SCRATCH-NEXT: s_waitcnt lgkmcnt(0) -; GFX10-SCRATCH-NEXT: s_load_dwordx8 s[4:11], s[0:1], 0x0 -; GFX10-SCRATCH-NEXT: s_mov_b32 s1, external_void_func_v8i32_inreg@abs32@hi -; GFX10-SCRATCH-NEXT: s_mov_b32 s0, external_void_func_v8i32_inreg@abs32@lo -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s30, 8 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s31, 9 -; GFX10-SCRATCH-NEXT: s_swappc_b64 s[30:31], s[0:1] -; GFX10-SCRATCH-NEXT: v_readlane_b32 s31, v40, 9 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s30, v40, 8 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s11, v40, 7 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s10, v40, 6 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s9, v40, 5 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s8, v40, 4 +; GFX10-SCRATCH-NEXT: s_load_dwordx8 s[0:7], s[0:1], 0x0 +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s30, 4 +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s31, 5 +; GFX10-SCRATCH-NEXT: s_swappc_b64 s[30:31], s[34:35] +; GFX10-SCRATCH-NEXT: v_readlane_b32 s31, v40, 5 +; GFX10-SCRATCH-NEXT: v_readlane_b32 s30, v40, 4 ; GFX10-SCRATCH-NEXT: v_readlane_b32 s7, v40, 3 ; GFX10-SCRATCH-NEXT: v_readlane_b32 s6, v40, 2 ; GFX10-SCRATCH-NEXT: v_readlane_b32 s5, v40, 1 ; GFX10-SCRATCH-NEXT: v_readlane_b32 s4, v40, 0 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s0, v40, 10 +; GFX10-SCRATCH-NEXT: v_readlane_b32 s0, v40, 6 ; GFX10-SCRATCH-NEXT: s_or_saveexec_b32 s1, -1 ; GFX10-SCRATCH-NEXT: scratch_load_dword v40, off, s33 ; 4-byte Folded Reload ; GFX10-SCRATCH-NEXT: s_waitcnt_depctr 0xffe3 @@ -14290,40 +13708,32 @@ define amdgpu_gfx void @test_call_external_void_func_v8i32_imm_inreg() #0 { ; GFX9-NEXT: s_or_saveexec_b64 s[36:37], -1 ; GFX9-NEXT: buffer_store_dword v40, off, s[0:3], s33 ; 4-byte Folded Spill ; GFX9-NEXT: s_mov_b64 exec, s[36:37] -; GFX9-NEXT: v_writelane_b32 v40, s34, 10 +; GFX9-NEXT: v_writelane_b32 v40, s34, 6 ; GFX9-NEXT: v_writelane_b32 v40, s4, 0 ; GFX9-NEXT: v_writelane_b32 v40, s5, 1 ; GFX9-NEXT: v_writelane_b32 v40, s6, 2 ; GFX9-NEXT: v_writelane_b32 v40, s7, 3 -; GFX9-NEXT: v_writelane_b32 v40, s8, 4 -; GFX9-NEXT: v_writelane_b32 v40, s9, 5 -; GFX9-NEXT: v_writelane_b32 v40, s10, 6 -; GFX9-NEXT: v_writelane_b32 v40, s11, 7 -; GFX9-NEXT: v_writelane_b32 v40, s30, 8 +; GFX9-NEXT: v_writelane_b32 v40, s30, 4 ; GFX9-NEXT: s_mov_b32 s35, external_void_func_v8i32_inreg@abs32@hi ; GFX9-NEXT: s_mov_b32 s34, external_void_func_v8i32_inreg@abs32@lo -; GFX9-NEXT: s_mov_b32 s4, 1 -; GFX9-NEXT: s_mov_b32 s5, 2 -; GFX9-NEXT: s_mov_b32 s6, 3 -; GFX9-NEXT: s_mov_b32 s7, 4 -; GFX9-NEXT: s_mov_b32 s8, 5 -; GFX9-NEXT: s_mov_b32 s9, 6 -; GFX9-NEXT: s_mov_b32 s10, 7 -; GFX9-NEXT: s_mov_b32 s11, 8 +; GFX9-NEXT: s_mov_b32 s0, 1 +; GFX9-NEXT: s_mov_b32 s1, 2 +; GFX9-NEXT: s_mov_b32 s2, 3 +; GFX9-NEXT: s_mov_b32 s3, 4 +; GFX9-NEXT: s_mov_b32 s4, 5 +; GFX9-NEXT: s_mov_b32 s5, 6 +; GFX9-NEXT: s_mov_b32 s6, 7 +; GFX9-NEXT: s_mov_b32 s7, 8 ; GFX9-NEXT: s_addk_i32 s32, 0x400 -; GFX9-NEXT: v_writelane_b32 v40, s31, 9 +; GFX9-NEXT: v_writelane_b32 v40, s31, 5 ; GFX9-NEXT: s_swappc_b64 s[30:31], s[34:35] -; GFX9-NEXT: v_readlane_b32 s31, v40, 9 -; GFX9-NEXT: v_readlane_b32 s30, v40, 8 -; GFX9-NEXT: v_readlane_b32 s11, v40, 7 -; GFX9-NEXT: v_readlane_b32 s10, v40, 6 -; GFX9-NEXT: v_readlane_b32 s9, v40, 5 -; GFX9-NEXT: v_readlane_b32 s8, v40, 4 +; GFX9-NEXT: v_readlane_b32 s31, v40, 5 +; GFX9-NEXT: v_readlane_b32 s30, v40, 4 ; GFX9-NEXT: v_readlane_b32 s7, v40, 3 ; GFX9-NEXT: v_readlane_b32 s6, v40, 2 ; GFX9-NEXT: v_readlane_b32 s5, v40, 1 ; GFX9-NEXT: v_readlane_b32 s4, v40, 0 -; GFX9-NEXT: v_readlane_b32 s34, v40, 10 +; GFX9-NEXT: v_readlane_b32 s34, v40, 6 ; GFX9-NEXT: s_or_saveexec_b64 s[36:37], -1 ; GFX9-NEXT: buffer_load_dword v40, off, s[0:3], s33 ; 4-byte Folded Reload ; GFX9-NEXT: s_mov_b64 exec, s[36:37] @@ -14341,40 +13751,32 @@ define amdgpu_gfx void @test_call_external_void_func_v8i32_imm_inreg() #0 { ; GFX10-NEXT: buffer_store_dword v40, off, s[0:3], s33 ; 4-byte Folded Spill ; GFX10-NEXT: s_waitcnt_depctr 0xffe3 ; GFX10-NEXT: s_mov_b32 exec_lo, s35 -; GFX10-NEXT: v_writelane_b32 v40, s34, 10 +; GFX10-NEXT: v_writelane_b32 v40, s34, 6 ; GFX10-NEXT: s_mov_b32 s35, external_void_func_v8i32_inreg@abs32@hi ; GFX10-NEXT: s_mov_b32 s34, external_void_func_v8i32_inreg@abs32@lo -; GFX10-NEXT: s_addk_i32 s32, 0x200 +; GFX10-NEXT: s_mov_b32 s0, 1 +; GFX10-NEXT: s_mov_b32 s1, 2 ; GFX10-NEXT: v_writelane_b32 v40, s4, 0 -; GFX10-NEXT: s_mov_b32 s4, 1 +; GFX10-NEXT: s_mov_b32 s2, 3 +; GFX10-NEXT: s_mov_b32 s3, 4 +; GFX10-NEXT: s_mov_b32 s4, 5 +; GFX10-NEXT: s_addk_i32 s32, 0x200 ; GFX10-NEXT: v_writelane_b32 v40, s5, 1 -; GFX10-NEXT: s_mov_b32 s5, 2 +; GFX10-NEXT: s_mov_b32 s5, 6 ; GFX10-NEXT: v_writelane_b32 v40, s6, 2 -; GFX10-NEXT: s_mov_b32 s6, 3 +; GFX10-NEXT: s_mov_b32 s6, 7 ; GFX10-NEXT: v_writelane_b32 v40, s7, 3 -; GFX10-NEXT: s_mov_b32 s7, 4 -; GFX10-NEXT: v_writelane_b32 v40, s8, 4 -; GFX10-NEXT: s_mov_b32 s8, 5 -; GFX10-NEXT: v_writelane_b32 v40, s9, 5 -; GFX10-NEXT: s_mov_b32 s9, 6 -; GFX10-NEXT: v_writelane_b32 v40, s10, 6 -; GFX10-NEXT: s_mov_b32 s10, 7 -; GFX10-NEXT: v_writelane_b32 v40, s11, 7 -; GFX10-NEXT: s_mov_b32 s11, 8 -; GFX10-NEXT: v_writelane_b32 v40, s30, 8 -; GFX10-NEXT: v_writelane_b32 v40, s31, 9 +; GFX10-NEXT: s_mov_b32 s7, 8 +; GFX10-NEXT: v_writelane_b32 v40, s30, 4 +; GFX10-NEXT: v_writelane_b32 v40, s31, 5 ; GFX10-NEXT: s_swappc_b64 s[30:31], s[34:35] -; GFX10-NEXT: v_readlane_b32 s31, v40, 9 -; GFX10-NEXT: v_readlane_b32 s30, v40, 8 -; GFX10-NEXT: v_readlane_b32 s11, v40, 7 -; GFX10-NEXT: v_readlane_b32 s10, v40, 6 -; GFX10-NEXT: v_readlane_b32 s9, v40, 5 -; GFX10-NEXT: v_readlane_b32 s8, v40, 4 +; GFX10-NEXT: v_readlane_b32 s31, v40, 5 +; GFX10-NEXT: v_readlane_b32 s30, v40, 4 ; GFX10-NEXT: v_readlane_b32 s7, v40, 3 ; GFX10-NEXT: v_readlane_b32 s6, v40, 2 ; GFX10-NEXT: v_readlane_b32 s5, v40, 1 ; GFX10-NEXT: v_readlane_b32 s4, v40, 0 -; GFX10-NEXT: v_readlane_b32 s34, v40, 10 +; GFX10-NEXT: v_readlane_b32 s34, v40, 6 ; GFX10-NEXT: s_or_saveexec_b32 s35, -1 ; GFX10-NEXT: buffer_load_dword v40, off, s[0:3], s33 ; 4-byte Folded Reload ; GFX10-NEXT: s_waitcnt_depctr 0xffe3 @@ -14392,41 +13794,33 @@ define amdgpu_gfx void @test_call_external_void_func_v8i32_imm_inreg() #0 { ; GFX11-NEXT: s_or_saveexec_b32 s1, -1 ; GFX11-NEXT: scratch_store_b32 off, v40, s33 ; 4-byte Folded Spill ; GFX11-NEXT: s_mov_b32 exec_lo, s1 -; GFX11-NEXT: v_writelane_b32 v40, s0, 10 -; GFX11-NEXT: s_mov_b32 s1, external_void_func_v8i32_inreg@abs32@hi -; GFX11-NEXT: s_mov_b32 s0, external_void_func_v8i32_inreg@abs32@lo -; GFX11-NEXT: s_add_i32 s32, s32, 16 +; GFX11-NEXT: v_writelane_b32 v40, s0, 6 +; GFX11-NEXT: s_mov_b32 s35, external_void_func_v8i32_inreg@abs32@hi +; GFX11-NEXT: s_mov_b32 s34, external_void_func_v8i32_inreg@abs32@lo +; GFX11-NEXT: s_mov_b32 s0, 1 +; GFX11-NEXT: s_mov_b32 s1, 2 ; GFX11-NEXT: v_writelane_b32 v40, s4, 0 -; GFX11-NEXT: s_mov_b32 s4, 1 +; GFX11-NEXT: s_mov_b32 s2, 3 +; GFX11-NEXT: s_mov_b32 s3, 4 +; GFX11-NEXT: s_mov_b32 s4, 5 +; GFX11-NEXT: s_add_i32 s32, s32, 16 ; GFX11-NEXT: v_writelane_b32 v40, s5, 1 -; GFX11-NEXT: s_mov_b32 s5, 2 +; GFX11-NEXT: s_mov_b32 s5, 6 ; GFX11-NEXT: v_writelane_b32 v40, s6, 2 -; GFX11-NEXT: s_mov_b32 s6, 3 +; GFX11-NEXT: s_mov_b32 s6, 7 ; GFX11-NEXT: v_writelane_b32 v40, s7, 3 -; GFX11-NEXT: s_mov_b32 s7, 4 -; GFX11-NEXT: v_writelane_b32 v40, s8, 4 -; GFX11-NEXT: s_mov_b32 s8, 5 -; GFX11-NEXT: v_writelane_b32 v40, s9, 5 -; GFX11-NEXT: s_mov_b32 s9, 6 -; GFX11-NEXT: v_writelane_b32 v40, s10, 6 -; GFX11-NEXT: s_mov_b32 s10, 7 -; GFX11-NEXT: v_writelane_b32 v40, s11, 7 -; GFX11-NEXT: s_mov_b32 s11, 8 -; GFX11-NEXT: v_writelane_b32 v40, s30, 8 -; GFX11-NEXT: v_writelane_b32 v40, s31, 9 -; GFX11-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX11-NEXT: s_mov_b32 s7, 8 +; GFX11-NEXT: v_writelane_b32 v40, s30, 4 +; GFX11-NEXT: v_writelane_b32 v40, s31, 5 +; GFX11-NEXT: s_swappc_b64 s[30:31], s[34:35] ; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_1) -; GFX11-NEXT: v_readlane_b32 s31, v40, 9 -; GFX11-NEXT: v_readlane_b32 s30, v40, 8 -; GFX11-NEXT: v_readlane_b32 s11, v40, 7 -; GFX11-NEXT: v_readlane_b32 s10, v40, 6 -; GFX11-NEXT: v_readlane_b32 s9, v40, 5 -; GFX11-NEXT: v_readlane_b32 s8, v40, 4 +; GFX11-NEXT: v_readlane_b32 s31, v40, 5 +; GFX11-NEXT: v_readlane_b32 s30, v40, 4 ; GFX11-NEXT: v_readlane_b32 s7, v40, 3 ; GFX11-NEXT: v_readlane_b32 s6, v40, 2 ; GFX11-NEXT: v_readlane_b32 s5, v40, 1 ; GFX11-NEXT: v_readlane_b32 s4, v40, 0 -; GFX11-NEXT: v_readlane_b32 s0, v40, 10 +; GFX11-NEXT: v_readlane_b32 s0, v40, 6 ; GFX11-NEXT: s_or_saveexec_b32 s1, -1 ; GFX11-NEXT: scratch_load_b32 v40, off, s33 ; 4-byte Folded Reload ; GFX11-NEXT: s_mov_b32 exec_lo, s1 @@ -14444,40 +13838,32 @@ define amdgpu_gfx void @test_call_external_void_func_v8i32_imm_inreg() #0 { ; GFX10-SCRATCH-NEXT: scratch_store_dword off, v40, s33 ; 4-byte Folded Spill ; GFX10-SCRATCH-NEXT: s_waitcnt_depctr 0xffe3 ; GFX10-SCRATCH-NEXT: s_mov_b32 exec_lo, s1 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s0, 10 -; GFX10-SCRATCH-NEXT: s_mov_b32 s1, external_void_func_v8i32_inreg@abs32@hi -; GFX10-SCRATCH-NEXT: s_mov_b32 s0, external_void_func_v8i32_inreg@abs32@lo -; GFX10-SCRATCH-NEXT: s_add_i32 s32, s32, 16 +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s0, 6 +; GFX10-SCRATCH-NEXT: s_mov_b32 s35, external_void_func_v8i32_inreg@abs32@hi +; GFX10-SCRATCH-NEXT: s_mov_b32 s34, external_void_func_v8i32_inreg@abs32@lo +; GFX10-SCRATCH-NEXT: s_mov_b32 s0, 1 +; GFX10-SCRATCH-NEXT: s_mov_b32 s1, 2 ; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s4, 0 -; GFX10-SCRATCH-NEXT: s_mov_b32 s4, 1 +; GFX10-SCRATCH-NEXT: s_mov_b32 s2, 3 +; GFX10-SCRATCH-NEXT: s_mov_b32 s3, 4 +; GFX10-SCRATCH-NEXT: s_mov_b32 s4, 5 +; GFX10-SCRATCH-NEXT: s_add_i32 s32, s32, 16 ; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s5, 1 -; GFX10-SCRATCH-NEXT: s_mov_b32 s5, 2 +; GFX10-SCRATCH-NEXT: s_mov_b32 s5, 6 ; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s6, 2 -; GFX10-SCRATCH-NEXT: s_mov_b32 s6, 3 +; GFX10-SCRATCH-NEXT: s_mov_b32 s6, 7 ; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s7, 3 -; GFX10-SCRATCH-NEXT: s_mov_b32 s7, 4 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s8, 4 -; GFX10-SCRATCH-NEXT: s_mov_b32 s8, 5 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s9, 5 -; GFX10-SCRATCH-NEXT: s_mov_b32 s9, 6 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s10, 6 -; GFX10-SCRATCH-NEXT: s_mov_b32 s10, 7 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s11, 7 -; GFX10-SCRATCH-NEXT: s_mov_b32 s11, 8 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s30, 8 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s31, 9 -; GFX10-SCRATCH-NEXT: s_swappc_b64 s[30:31], s[0:1] -; GFX10-SCRATCH-NEXT: v_readlane_b32 s31, v40, 9 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s30, v40, 8 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s11, v40, 7 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s10, v40, 6 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s9, v40, 5 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s8, v40, 4 +; GFX10-SCRATCH-NEXT: s_mov_b32 s7, 8 +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s30, 4 +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s31, 5 +; GFX10-SCRATCH-NEXT: s_swappc_b64 s[30:31], s[34:35] +; GFX10-SCRATCH-NEXT: v_readlane_b32 s31, v40, 5 +; GFX10-SCRATCH-NEXT: v_readlane_b32 s30, v40, 4 ; GFX10-SCRATCH-NEXT: v_readlane_b32 s7, v40, 3 ; GFX10-SCRATCH-NEXT: v_readlane_b32 s6, v40, 2 ; GFX10-SCRATCH-NEXT: v_readlane_b32 s5, v40, 1 ; GFX10-SCRATCH-NEXT: v_readlane_b32 s4, v40, 0 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s0, v40, 10 +; GFX10-SCRATCH-NEXT: v_readlane_b32 s0, v40, 6 ; GFX10-SCRATCH-NEXT: s_or_saveexec_b32 s1, -1 ; GFX10-SCRATCH-NEXT: scratch_load_dword v40, off, s33 ; 4-byte Folded Reload ; GFX10-SCRATCH-NEXT: s_waitcnt_depctr 0xffe3 @@ -14499,38 +13885,47 @@ define amdgpu_gfx void @test_call_external_void_func_v16i32_inreg() #0 { ; GFX9-NEXT: s_or_saveexec_b64 s[36:37], -1 ; GFX9-NEXT: buffer_store_dword v40, off, s[0:3], s33 ; 4-byte Folded Spill ; GFX9-NEXT: s_mov_b64 exec, s[36:37] -; GFX9-NEXT: v_writelane_b32 v40, s34, 18 +; GFX9-NEXT: v_writelane_b32 v40, s34, 14 ; GFX9-NEXT: v_writelane_b32 v40, s4, 0 ; GFX9-NEXT: v_writelane_b32 v40, s5, 1 ; GFX9-NEXT: v_writelane_b32 v40, s6, 2 +; GFX9-NEXT: s_load_dwordx2 s[34:35], s[34:35], 0x0 ; GFX9-NEXT: v_writelane_b32 v40, s7, 3 ; GFX9-NEXT: v_writelane_b32 v40, s8, 4 ; GFX9-NEXT: v_writelane_b32 v40, s9, 5 ; GFX9-NEXT: v_writelane_b32 v40, s10, 6 ; GFX9-NEXT: v_writelane_b32 v40, s11, 7 +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: s_load_dwordx16 s[36:51], s[34:35], 0x0 ; GFX9-NEXT: v_writelane_b32 v40, s12, 8 ; GFX9-NEXT: v_writelane_b32 v40, s13, 9 ; GFX9-NEXT: v_writelane_b32 v40, s14, 10 -; GFX9-NEXT: s_load_dwordx2 s[34:35], s[34:35], 0x0 ; GFX9-NEXT: v_writelane_b32 v40, s15, 11 -; GFX9-NEXT: v_writelane_b32 v40, s16, 12 -; GFX9-NEXT: v_writelane_b32 v40, s17, 13 -; GFX9-NEXT: v_writelane_b32 v40, s18, 14 -; GFX9-NEXT: v_writelane_b32 v40, s19, 15 -; GFX9-NEXT: s_waitcnt lgkmcnt(0) -; GFX9-NEXT: s_load_dwordx16 s[4:19], s[34:35], 0x0 -; GFX9-NEXT: v_writelane_b32 v40, s30, 16 +; GFX9-NEXT: v_writelane_b32 v40, s30, 12 ; GFX9-NEXT: s_mov_b32 s35, external_void_func_v16i32_inreg@abs32@hi ; GFX9-NEXT: s_mov_b32 s34, external_void_func_v16i32_inreg@abs32@lo +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: s_mov_b32 s0, s36 +; GFX9-NEXT: s_mov_b32 s1, s37 +; GFX9-NEXT: s_mov_b32 s2, s38 +; GFX9-NEXT: s_mov_b32 s3, s39 +; GFX9-NEXT: s_mov_b32 s4, s40 +; GFX9-NEXT: s_mov_b32 s5, s41 +; GFX9-NEXT: s_mov_b32 s6, s42 +; GFX9-NEXT: s_mov_b32 s7, s43 +; GFX9-NEXT: s_mov_b32 s8, s44 +; GFX9-NEXT: s_mov_b32 s9, s45 +; GFX9-NEXT: s_mov_b32 s10, s46 +; GFX9-NEXT: s_mov_b32 s11, s47 +; GFX9-NEXT: s_mov_b32 s12, s48 +; GFX9-NEXT: s_mov_b32 s13, s49 +; GFX9-NEXT: s_mov_b32 s14, s50 +; GFX9-NEXT: s_mov_b32 s15, s51 ; GFX9-NEXT: s_addk_i32 s32, 0x400 -; GFX9-NEXT: v_writelane_b32 v40, s31, 17 +; GFX9-NEXT: v_writelane_b32 v40, s31, 13 ; GFX9-NEXT: s_swappc_b64 s[30:31], s[34:35] -; GFX9-NEXT: v_readlane_b32 s31, v40, 17 -; GFX9-NEXT: v_readlane_b32 s30, v40, 16 -; GFX9-NEXT: v_readlane_b32 s19, v40, 15 -; GFX9-NEXT: v_readlane_b32 s18, v40, 14 -; GFX9-NEXT: v_readlane_b32 s17, v40, 13 -; GFX9-NEXT: v_readlane_b32 s16, v40, 12 +; GFX9-NEXT: v_readlane_b32 s31, v40, 13 +; GFX9-NEXT: v_readlane_b32 s30, v40, 12 ; GFX9-NEXT: v_readlane_b32 s15, v40, 11 ; GFX9-NEXT: v_readlane_b32 s14, v40, 10 ; GFX9-NEXT: v_readlane_b32 s13, v40, 9 @@ -14543,7 +13938,7 @@ define amdgpu_gfx void @test_call_external_void_func_v16i32_inreg() #0 { ; GFX9-NEXT: v_readlane_b32 s6, v40, 2 ; GFX9-NEXT: v_readlane_b32 s5, v40, 1 ; GFX9-NEXT: v_readlane_b32 s4, v40, 0 -; GFX9-NEXT: v_readlane_b32 s34, v40, 18 +; GFX9-NEXT: v_readlane_b32 s34, v40, 14 ; GFX9-NEXT: s_or_saveexec_b64 s[36:37], -1 ; GFX9-NEXT: buffer_load_dword v40, off, s[0:3], s33 ; 4-byte Folded Reload ; GFX9-NEXT: s_mov_b64 exec, s[36:37] @@ -14561,38 +13956,47 @@ define amdgpu_gfx void @test_call_external_void_func_v16i32_inreg() #0 { ; GFX10-NEXT: buffer_store_dword v40, off, s[0:3], s33 ; 4-byte Folded Spill ; GFX10-NEXT: s_waitcnt_depctr 0xffe3 ; GFX10-NEXT: s_mov_b32 exec_lo, s35 -; GFX10-NEXT: v_writelane_b32 v40, s34, 18 +; GFX10-NEXT: v_writelane_b32 v40, s34, 14 ; GFX10-NEXT: s_load_dwordx2 s[34:35], s[34:35], 0x0 ; GFX10-NEXT: s_addk_i32 s32, 0x200 ; GFX10-NEXT: v_writelane_b32 v40, s4, 0 ; GFX10-NEXT: v_writelane_b32 v40, s5, 1 ; GFX10-NEXT: v_writelane_b32 v40, s6, 2 ; GFX10-NEXT: v_writelane_b32 v40, s7, 3 +; GFX10-NEXT: s_waitcnt lgkmcnt(0) +; GFX10-NEXT: s_load_dwordx16 s[36:51], s[34:35], 0x0 +; GFX10-NEXT: s_mov_b32 s35, external_void_func_v16i32_inreg@abs32@hi +; GFX10-NEXT: s_mov_b32 s34, external_void_func_v16i32_inreg@abs32@lo ; GFX10-NEXT: v_writelane_b32 v40, s8, 4 ; GFX10-NEXT: v_writelane_b32 v40, s9, 5 ; GFX10-NEXT: v_writelane_b32 v40, s10, 6 ; GFX10-NEXT: v_writelane_b32 v40, s11, 7 +; GFX10-NEXT: s_waitcnt lgkmcnt(0) +; GFX10-NEXT: s_mov_b32 s0, s36 +; GFX10-NEXT: s_mov_b32 s1, s37 +; GFX10-NEXT: s_mov_b32 s2, s38 +; GFX10-NEXT: s_mov_b32 s3, s39 ; GFX10-NEXT: v_writelane_b32 v40, s12, 8 +; GFX10-NEXT: s_mov_b32 s4, s40 +; GFX10-NEXT: s_mov_b32 s5, s41 +; GFX10-NEXT: s_mov_b32 s6, s42 +; GFX10-NEXT: s_mov_b32 s7, s43 ; GFX10-NEXT: v_writelane_b32 v40, s13, 9 +; GFX10-NEXT: s_mov_b32 s8, s44 +; GFX10-NEXT: s_mov_b32 s9, s45 +; GFX10-NEXT: s_mov_b32 s10, s46 +; GFX10-NEXT: s_mov_b32 s11, s47 ; GFX10-NEXT: v_writelane_b32 v40, s14, 10 +; GFX10-NEXT: s_mov_b32 s12, s48 +; GFX10-NEXT: s_mov_b32 s13, s49 +; GFX10-NEXT: s_mov_b32 s14, s50 ; GFX10-NEXT: v_writelane_b32 v40, s15, 11 -; GFX10-NEXT: v_writelane_b32 v40, s16, 12 -; GFX10-NEXT: v_writelane_b32 v40, s17, 13 -; GFX10-NEXT: v_writelane_b32 v40, s18, 14 -; GFX10-NEXT: v_writelane_b32 v40, s19, 15 -; GFX10-NEXT: s_waitcnt lgkmcnt(0) -; GFX10-NEXT: s_load_dwordx16 s[4:19], s[34:35], 0x0 -; GFX10-NEXT: s_mov_b32 s35, external_void_func_v16i32_inreg@abs32@hi -; GFX10-NEXT: s_mov_b32 s34, external_void_func_v16i32_inreg@abs32@lo -; GFX10-NEXT: v_writelane_b32 v40, s30, 16 -; GFX10-NEXT: v_writelane_b32 v40, s31, 17 +; GFX10-NEXT: s_mov_b32 s15, s51 +; GFX10-NEXT: v_writelane_b32 v40, s30, 12 +; GFX10-NEXT: v_writelane_b32 v40, s31, 13 ; GFX10-NEXT: s_swappc_b64 s[30:31], s[34:35] -; GFX10-NEXT: v_readlane_b32 s31, v40, 17 -; GFX10-NEXT: v_readlane_b32 s30, v40, 16 -; GFX10-NEXT: v_readlane_b32 s19, v40, 15 -; GFX10-NEXT: v_readlane_b32 s18, v40, 14 -; GFX10-NEXT: v_readlane_b32 s17, v40, 13 -; GFX10-NEXT: v_readlane_b32 s16, v40, 12 +; GFX10-NEXT: v_readlane_b32 s31, v40, 13 +; GFX10-NEXT: v_readlane_b32 s30, v40, 12 ; GFX10-NEXT: v_readlane_b32 s15, v40, 11 ; GFX10-NEXT: v_readlane_b32 s14, v40, 10 ; GFX10-NEXT: v_readlane_b32 s13, v40, 9 @@ -14605,7 +14009,7 @@ define amdgpu_gfx void @test_call_external_void_func_v16i32_inreg() #0 { ; GFX10-NEXT: v_readlane_b32 s6, v40, 2 ; GFX10-NEXT: v_readlane_b32 s5, v40, 1 ; GFX10-NEXT: v_readlane_b32 s4, v40, 0 -; GFX10-NEXT: v_readlane_b32 s34, v40, 18 +; GFX10-NEXT: v_readlane_b32 s34, v40, 14 ; GFX10-NEXT: s_or_saveexec_b32 s35, -1 ; GFX10-NEXT: buffer_load_dword v40, off, s[0:3], s33 ; 4-byte Folded Reload ; GFX10-NEXT: s_waitcnt_depctr 0xffe3 @@ -14623,8 +14027,10 @@ define amdgpu_gfx void @test_call_external_void_func_v16i32_inreg() #0 { ; GFX11-NEXT: s_or_saveexec_b32 s1, -1 ; GFX11-NEXT: scratch_store_b32 off, v40, s33 ; 4-byte Folded Spill ; GFX11-NEXT: s_mov_b32 exec_lo, s1 -; GFX11-NEXT: v_writelane_b32 v40, s0, 18 +; GFX11-NEXT: v_writelane_b32 v40, s0, 14 ; GFX11-NEXT: s_load_b64 s[0:1], s[0:1], 0x0 +; GFX11-NEXT: s_mov_b32 s35, external_void_func_v16i32_inreg@abs32@hi +; GFX11-NEXT: s_mov_b32 s34, external_void_func_v16i32_inreg@abs32@lo ; GFX11-NEXT: s_add_i32 s32, s32, 16 ; GFX11-NEXT: v_writelane_b32 v40, s4, 0 ; GFX11-NEXT: v_writelane_b32 v40, s5, 1 @@ -14638,24 +14044,14 @@ define amdgpu_gfx void @test_call_external_void_func_v16i32_inreg() #0 { ; GFX11-NEXT: v_writelane_b32 v40, s13, 9 ; GFX11-NEXT: v_writelane_b32 v40, s14, 10 ; GFX11-NEXT: v_writelane_b32 v40, s15, 11 -; GFX11-NEXT: v_writelane_b32 v40, s16, 12 -; GFX11-NEXT: v_writelane_b32 v40, s17, 13 -; GFX11-NEXT: v_writelane_b32 v40, s18, 14 -; GFX11-NEXT: v_writelane_b32 v40, s19, 15 ; GFX11-NEXT: s_waitcnt lgkmcnt(0) -; GFX11-NEXT: s_load_b512 s[4:19], s[0:1], 0x0 -; GFX11-NEXT: s_mov_b32 s1, external_void_func_v16i32_inreg@abs32@hi -; GFX11-NEXT: s_mov_b32 s0, external_void_func_v16i32_inreg@abs32@lo -; GFX11-NEXT: v_writelane_b32 v40, s30, 16 -; GFX11-NEXT: v_writelane_b32 v40, s31, 17 -; GFX11-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX11-NEXT: s_load_b512 s[0:15], s[0:1], 0x0 +; GFX11-NEXT: v_writelane_b32 v40, s30, 12 +; GFX11-NEXT: v_writelane_b32 v40, s31, 13 +; GFX11-NEXT: s_swappc_b64 s[30:31], s[34:35] ; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_1) -; GFX11-NEXT: v_readlane_b32 s31, v40, 17 -; GFX11-NEXT: v_readlane_b32 s30, v40, 16 -; GFX11-NEXT: v_readlane_b32 s19, v40, 15 -; GFX11-NEXT: v_readlane_b32 s18, v40, 14 -; GFX11-NEXT: v_readlane_b32 s17, v40, 13 -; GFX11-NEXT: v_readlane_b32 s16, v40, 12 +; GFX11-NEXT: v_readlane_b32 s31, v40, 13 +; GFX11-NEXT: v_readlane_b32 s30, v40, 12 ; GFX11-NEXT: v_readlane_b32 s15, v40, 11 ; GFX11-NEXT: v_readlane_b32 s14, v40, 10 ; GFX11-NEXT: v_readlane_b32 s13, v40, 9 @@ -14668,7 +14064,7 @@ define amdgpu_gfx void @test_call_external_void_func_v16i32_inreg() #0 { ; GFX11-NEXT: v_readlane_b32 s6, v40, 2 ; GFX11-NEXT: v_readlane_b32 s5, v40, 1 ; GFX11-NEXT: v_readlane_b32 s4, v40, 0 -; GFX11-NEXT: v_readlane_b32 s0, v40, 18 +; GFX11-NEXT: v_readlane_b32 s0, v40, 14 ; GFX11-NEXT: s_or_saveexec_b32 s1, -1 ; GFX11-NEXT: scratch_load_b32 v40, off, s33 ; 4-byte Folded Reload ; GFX11-NEXT: s_mov_b32 exec_lo, s1 @@ -14686,8 +14082,10 @@ define amdgpu_gfx void @test_call_external_void_func_v16i32_inreg() #0 { ; GFX10-SCRATCH-NEXT: scratch_store_dword off, v40, s33 ; 4-byte Folded Spill ; GFX10-SCRATCH-NEXT: s_waitcnt_depctr 0xffe3 ; GFX10-SCRATCH-NEXT: s_mov_b32 exec_lo, s1 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s0, 18 +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s0, 14 ; GFX10-SCRATCH-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x0 +; GFX10-SCRATCH-NEXT: s_mov_b32 s35, external_void_func_v16i32_inreg@abs32@hi +; GFX10-SCRATCH-NEXT: s_mov_b32 s34, external_void_func_v16i32_inreg@abs32@lo ; GFX10-SCRATCH-NEXT: s_add_i32 s32, s32, 16 ; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s4, 0 ; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s5, 1 @@ -14701,23 +14099,13 @@ define amdgpu_gfx void @test_call_external_void_func_v16i32_inreg() #0 { ; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s13, 9 ; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s14, 10 ; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s15, 11 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s16, 12 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s17, 13 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s18, 14 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s19, 15 ; GFX10-SCRATCH-NEXT: s_waitcnt lgkmcnt(0) -; GFX10-SCRATCH-NEXT: s_load_dwordx16 s[4:19], s[0:1], 0x0 -; GFX10-SCRATCH-NEXT: s_mov_b32 s1, external_void_func_v16i32_inreg@abs32@hi -; GFX10-SCRATCH-NEXT: s_mov_b32 s0, external_void_func_v16i32_inreg@abs32@lo -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s30, 16 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s31, 17 -; GFX10-SCRATCH-NEXT: s_swappc_b64 s[30:31], s[0:1] -; GFX10-SCRATCH-NEXT: v_readlane_b32 s31, v40, 17 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s30, v40, 16 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s19, v40, 15 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s18, v40, 14 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s17, v40, 13 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s16, v40, 12 +; GFX10-SCRATCH-NEXT: s_load_dwordx16 s[0:15], s[0:1], 0x0 +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s30, 12 +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s31, 13 +; GFX10-SCRATCH-NEXT: s_swappc_b64 s[30:31], s[34:35] +; GFX10-SCRATCH-NEXT: v_readlane_b32 s31, v40, 13 +; GFX10-SCRATCH-NEXT: v_readlane_b32 s30, v40, 12 ; GFX10-SCRATCH-NEXT: v_readlane_b32 s15, v40, 11 ; GFX10-SCRATCH-NEXT: v_readlane_b32 s14, v40, 10 ; GFX10-SCRATCH-NEXT: v_readlane_b32 s13, v40, 9 @@ -14730,7 +14118,7 @@ define amdgpu_gfx void @test_call_external_void_func_v16i32_inreg() #0 { ; GFX10-SCRATCH-NEXT: v_readlane_b32 s6, v40, 2 ; GFX10-SCRATCH-NEXT: v_readlane_b32 s5, v40, 1 ; GFX10-SCRATCH-NEXT: v_readlane_b32 s4, v40, 0 -; GFX10-SCRATCH-NEXT: v_readlane_b32 s0, v40, 18 +; GFX10-SCRATCH-NEXT: v_readlane_b32 s0, v40, 14 ; GFX10-SCRATCH-NEXT: s_or_saveexec_b32 s1, -1 ; GFX10-SCRATCH-NEXT: scratch_load_dword v40, off, s33 ; 4-byte Folded Reload ; GFX10-SCRATCH-NEXT: s_waitcnt_depctr 0xffe3 @@ -14771,49 +14159,47 @@ define amdgpu_gfx void @test_call_external_void_func_v32i32_inreg() #0 { ; GFX9-NEXT: v_writelane_b32 v40, s17, 13 ; GFX9-NEXT: v_writelane_b32 v40, s18, 14 ; GFX9-NEXT: v_writelane_b32 v40, s19, 15 -; GFX9-NEXT: s_load_dwordx2 s[34:35], s[34:35], 0x0 ; GFX9-NEXT: v_writelane_b32 v40, s20, 16 ; GFX9-NEXT: v_writelane_b32 v40, s21, 17 ; GFX9-NEXT: v_writelane_b32 v40, s22, 18 ; GFX9-NEXT: v_writelane_b32 v40, s23, 19 ; GFX9-NEXT: v_writelane_b32 v40, s24, 20 -; GFX9-NEXT: s_waitcnt lgkmcnt(0) -; GFX9-NEXT: s_load_dwordx16 s[36:51], s[34:35], 0x40 -; GFX9-NEXT: s_load_dwordx16 s[4:19], s[34:35], 0x0 ; GFX9-NEXT: v_writelane_b32 v40, s25, 21 ; GFX9-NEXT: v_writelane_b32 v40, s26, 22 +; GFX9-NEXT: s_load_dwordx2 s[34:35], s[34:35], 0x0 ; GFX9-NEXT: v_writelane_b32 v40, s27, 23 -; GFX9-NEXT: s_addk_i32 s32, 0x400 ; GFX9-NEXT: v_writelane_b32 v40, s28, 24 +; GFX9-NEXT: v_writelane_b32 v40, s29, 25 +; GFX9-NEXT: v_writelane_b32 v40, s30, 26 +; GFX9-NEXT: v_writelane_b32 v40, s31, 27 +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: s_load_dwordx16 s[16:31], s[34:35], 0x40 +; GFX9-NEXT: s_load_dwordx16 s[36:51], s[34:35], 0x0 +; GFX9-NEXT: s_addk_i32 s32, 0x400 +; GFX9-NEXT: s_mov_b32 s53, external_void_func_v32i32_inreg@abs32@hi +; GFX9-NEXT: s_mov_b32 s52, external_void_func_v32i32_inreg@abs32@lo ; GFX9-NEXT: s_waitcnt lgkmcnt(0) -; GFX9-NEXT: v_mov_b32_e32 v0, s46 -; GFX9-NEXT: v_writelane_b32 v40, s29, 25 -; GFX9-NEXT: v_mov_b32_e32 v1, s47 -; GFX9-NEXT: v_mov_b32_e32 v2, s48 -; GFX9-NEXT: v_mov_b32_e32 v3, s49 +; GFX9-NEXT: v_mov_b32_e32 v0, s30 +; GFX9-NEXT: v_mov_b32_e32 v1, s31 ; GFX9-NEXT: buffer_store_dword v0, off, s[0:3], s32 ; GFX9-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:4 -; GFX9-NEXT: buffer_store_dword v2, off, s[0:3], s32 offset:8 -; GFX9-NEXT: buffer_store_dword v3, off, s[0:3], s32 offset:12 -; GFX9-NEXT: v_mov_b32_e32 v0, s50 -; GFX9-NEXT: v_writelane_b32 v40, s30, 26 -; GFX9-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:16 -; GFX9-NEXT: v_mov_b32_e32 v0, s51 -; GFX9-NEXT: s_mov_b32 s35, external_void_func_v32i32_inreg@abs32@hi -; GFX9-NEXT: s_mov_b32 s34, external_void_func_v32i32_inreg@abs32@lo -; GFX9-NEXT: s_mov_b32 s20, s36 -; GFX9-NEXT: s_mov_b32 s21, s37 -; GFX9-NEXT: s_mov_b32 s22, s38 -; GFX9-NEXT: s_mov_b32 s23, s39 -; GFX9-NEXT: s_mov_b32 s24, s40 -; GFX9-NEXT: s_mov_b32 s25, s41 -; GFX9-NEXT: s_mov_b32 s26, s42 -; GFX9-NEXT: s_mov_b32 s27, s43 -; GFX9-NEXT: s_mov_b32 s28, s44 -; GFX9-NEXT: s_mov_b32 s29, s45 -; GFX9-NEXT: v_writelane_b32 v40, s31, 27 -; GFX9-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:20 -; GFX9-NEXT: s_swappc_b64 s[30:31], s[34:35] +; GFX9-NEXT: s_mov_b32 s0, s36 +; GFX9-NEXT: s_mov_b32 s1, s37 +; GFX9-NEXT: s_mov_b32 s2, s38 +; GFX9-NEXT: s_mov_b32 s3, s39 +; GFX9-NEXT: s_mov_b32 s4, s40 +; GFX9-NEXT: s_mov_b32 s5, s41 +; GFX9-NEXT: s_mov_b32 s6, s42 +; GFX9-NEXT: s_mov_b32 s7, s43 +; GFX9-NEXT: s_mov_b32 s8, s44 +; GFX9-NEXT: s_mov_b32 s9, s45 +; GFX9-NEXT: s_mov_b32 s10, s46 +; GFX9-NEXT: s_mov_b32 s11, s47 +; GFX9-NEXT: s_mov_b32 s12, s48 +; GFX9-NEXT: s_mov_b32 s13, s49 +; GFX9-NEXT: s_mov_b32 s14, s50 +; GFX9-NEXT: s_mov_b32 s15, s51 +; GFX9-NEXT: s_swappc_b64 s[30:31], s[52:53] ; GFX9-NEXT: v_readlane_b32 s31, v40, 27 ; GFX9-NEXT: v_readlane_b32 s30, v40, 26 ; GFX9-NEXT: v_readlane_b32 s29, v40, 25 @@ -14879,47 +14265,46 @@ define amdgpu_gfx void @test_call_external_void_func_v32i32_inreg() #0 { ; GFX10-NEXT: v_writelane_b32 v40, s17, 13 ; GFX10-NEXT: v_writelane_b32 v40, s18, 14 ; GFX10-NEXT: v_writelane_b32 v40, s19, 15 -; GFX10-NEXT: s_waitcnt lgkmcnt(0) -; GFX10-NEXT: s_clause 0x1 -; GFX10-NEXT: s_load_dwordx16 s[36:51], s[34:35], 0x40 -; GFX10-NEXT: s_load_dwordx16 s[4:19], s[34:35], 0x0 -; GFX10-NEXT: s_mov_b32 s35, external_void_func_v32i32_inreg@abs32@hi -; GFX10-NEXT: s_mov_b32 s34, external_void_func_v32i32_inreg@abs32@lo ; GFX10-NEXT: v_writelane_b32 v40, s20, 16 ; GFX10-NEXT: v_writelane_b32 v40, s21, 17 ; GFX10-NEXT: v_writelane_b32 v40, s22, 18 -; GFX10-NEXT: s_waitcnt lgkmcnt(0) -; GFX10-NEXT: v_mov_b32_e32 v0, s46 ; GFX10-NEXT: v_writelane_b32 v40, s23, 19 -; GFX10-NEXT: v_mov_b32_e32 v1, s47 -; GFX10-NEXT: v_mov_b32_e32 v2, s48 -; GFX10-NEXT: v_mov_b32_e32 v3, s49 -; GFX10-NEXT: s_mov_b32 s20, s36 ; GFX10-NEXT: v_writelane_b32 v40, s24, 20 -; GFX10-NEXT: s_mov_b32 s21, s37 -; GFX10-NEXT: s_mov_b32 s22, s38 -; GFX10-NEXT: s_mov_b32 s23, s39 -; GFX10-NEXT: s_mov_b32 s24, s40 ; GFX10-NEXT: v_writelane_b32 v40, s25, 21 -; GFX10-NEXT: s_mov_b32 s25, s41 -; GFX10-NEXT: v_mov_b32_e32 v4, s50 -; GFX10-NEXT: v_mov_b32_e32 v5, s51 -; GFX10-NEXT: buffer_store_dword v0, off, s[0:3], s32 -; GFX10-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:4 -; GFX10-NEXT: buffer_store_dword v2, off, s[0:3], s32 offset:8 -; GFX10-NEXT: buffer_store_dword v3, off, s[0:3], s32 offset:12 -; GFX10-NEXT: buffer_store_dword v4, off, s[0:3], s32 offset:16 -; GFX10-NEXT: buffer_store_dword v5, off, s[0:3], s32 offset:20 ; GFX10-NEXT: v_writelane_b32 v40, s26, 22 -; GFX10-NEXT: s_mov_b32 s26, s42 ; GFX10-NEXT: v_writelane_b32 v40, s27, 23 -; GFX10-NEXT: s_mov_b32 s27, s43 ; GFX10-NEXT: v_writelane_b32 v40, s28, 24 -; GFX10-NEXT: s_mov_b32 s28, s44 ; GFX10-NEXT: v_writelane_b32 v40, s29, 25 -; GFX10-NEXT: s_mov_b32 s29, s45 ; GFX10-NEXT: v_writelane_b32 v40, s30, 26 ; GFX10-NEXT: v_writelane_b32 v40, s31, 27 +; GFX10-NEXT: s_waitcnt lgkmcnt(0) +; GFX10-NEXT: s_clause 0x1 +; GFX10-NEXT: s_load_dwordx16 s[16:31], s[34:35], 0x40 +; GFX10-NEXT: s_load_dwordx16 s[36:51], s[34:35], 0x0 +; GFX10-NEXT: s_mov_b32 s35, external_void_func_v32i32_inreg@abs32@hi +; GFX10-NEXT: s_mov_b32 s34, external_void_func_v32i32_inreg@abs32@lo +; GFX10-NEXT: s_waitcnt lgkmcnt(0) +; GFX10-NEXT: v_mov_b32_e32 v0, s30 +; GFX10-NEXT: v_mov_b32_e32 v1, s31 +; GFX10-NEXT: s_mov_b32 s4, s40 +; GFX10-NEXT: s_mov_b32 s5, s41 +; GFX10-NEXT: buffer_store_dword v0, off, s[0:3], s32 +; GFX10-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:4 +; GFX10-NEXT: s_mov_b32 s6, s42 +; GFX10-NEXT: s_mov_b32 s7, s43 +; GFX10-NEXT: s_mov_b32 s8, s44 +; GFX10-NEXT: s_mov_b32 s9, s45 +; GFX10-NEXT: s_mov_b32 s10, s46 +; GFX10-NEXT: s_mov_b32 s11, s47 +; GFX10-NEXT: s_mov_b32 s12, s48 +; GFX10-NEXT: s_mov_b32 s13, s49 +; GFX10-NEXT: s_mov_b32 s14, s50 +; GFX10-NEXT: s_mov_b32 s15, s51 +; GFX10-NEXT: s_waitcnt_depctr 0xffe3 +; GFX10-NEXT: s_mov_b32 s0, s36 +; GFX10-NEXT: s_mov_b32 s1, s37 +; GFX10-NEXT: s_mov_b32 s2, s38 +; GFX10-NEXT: s_mov_b32 s3, s39 ; GFX10-NEXT: s_swappc_b64 s[30:31], s[34:35] ; GFX10-NEXT: v_readlane_b32 s31, v40, 27 ; GFX10-NEXT: v_readlane_b32 s30, v40, 26 @@ -14970,8 +14355,8 @@ define amdgpu_gfx void @test_call_external_void_func_v32i32_inreg() #0 { ; GFX11-NEXT: v_writelane_b32 v40, s0, 28 ; GFX11-NEXT: s_load_b64 s[0:1], s[0:1], 0x0 ; GFX11-NEXT: s_add_i32 s32, s32, 16 -; GFX11-NEXT: s_delay_alu instid0(SALU_CYCLE_1) -; GFX11-NEXT: s_add_i32 s2, s32, 16 +; GFX11-NEXT: s_mov_b32 s35, external_void_func_v32i32_inreg@abs32@hi +; GFX11-NEXT: s_mov_b32 s34, external_void_func_v32i32_inreg@abs32@lo ; GFX11-NEXT: v_writelane_b32 v40, s4, 0 ; GFX11-NEXT: v_writelane_b32 v40, s5, 1 ; GFX11-NEXT: v_writelane_b32 v40, s6, 2 @@ -14988,42 +14373,26 @@ define amdgpu_gfx void @test_call_external_void_func_v32i32_inreg() #0 { ; GFX11-NEXT: v_writelane_b32 v40, s17, 13 ; GFX11-NEXT: v_writelane_b32 v40, s18, 14 ; GFX11-NEXT: v_writelane_b32 v40, s19, 15 -; GFX11-NEXT: s_waitcnt lgkmcnt(0) -; GFX11-NEXT: s_clause 0x1 -; GFX11-NEXT: s_load_b512 s[36:51], s[0:1], 0x40 -; GFX11-NEXT: s_load_b512 s[4:19], s[0:1], 0x0 -; GFX11-NEXT: s_mov_b32 s1, external_void_func_v32i32_inreg@abs32@hi -; GFX11-NEXT: s_mov_b32 s0, external_void_func_v32i32_inreg@abs32@lo ; GFX11-NEXT: v_writelane_b32 v40, s20, 16 ; GFX11-NEXT: v_writelane_b32 v40, s21, 17 ; GFX11-NEXT: v_writelane_b32 v40, s22, 18 -; GFX11-NEXT: s_waitcnt lgkmcnt(0) -; GFX11-NEXT: v_dual_mov_b32 v4, s50 :: v_dual_mov_b32 v5, s51 ; GFX11-NEXT: v_writelane_b32 v40, s23, 19 -; GFX11-NEXT: v_dual_mov_b32 v0, s46 :: v_dual_mov_b32 v1, s47 -; GFX11-NEXT: v_dual_mov_b32 v2, s48 :: v_dual_mov_b32 v3, s49 ; GFX11-NEXT: v_writelane_b32 v40, s24, 20 -; GFX11-NEXT: s_mov_b32 s20, s36 -; GFX11-NEXT: s_mov_b32 s21, s37 -; GFX11-NEXT: s_mov_b32 s22, s38 -; GFX11-NEXT: s_mov_b32 s23, s39 ; GFX11-NEXT: v_writelane_b32 v40, s25, 21 -; GFX11-NEXT: s_mov_b32 s24, s40 -; GFX11-NEXT: s_mov_b32 s25, s41 -; GFX11-NEXT: scratch_store_b64 off, v[4:5], s2 -; GFX11-NEXT: scratch_store_b128 off, v[0:3], s32 ; GFX11-NEXT: v_writelane_b32 v40, s26, 22 -; GFX11-NEXT: s_mov_b32 s26, s42 ; GFX11-NEXT: v_writelane_b32 v40, s27, 23 -; GFX11-NEXT: s_mov_b32 s27, s43 ; GFX11-NEXT: v_writelane_b32 v40, s28, 24 -; GFX11-NEXT: s_mov_b32 s28, s44 ; GFX11-NEXT: v_writelane_b32 v40, s29, 25 -; GFX11-NEXT: s_mov_b32 s29, s45 ; GFX11-NEXT: v_writelane_b32 v40, s30, 26 ; GFX11-NEXT: v_writelane_b32 v40, s31, 27 -; GFX11-NEXT: s_swappc_b64 s[30:31], s[0:1] -; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX11-NEXT: s_waitcnt lgkmcnt(0) +; GFX11-NEXT: s_clause 0x1 +; GFX11-NEXT: s_load_b512 s[16:31], s[0:1], 0x40 +; GFX11-NEXT: s_load_b512 s[0:15], s[0:1], 0x0 +; GFX11-NEXT: s_waitcnt lgkmcnt(0) +; GFX11-NEXT: v_dual_mov_b32 v0, s30 :: v_dual_mov_b32 v1, s31 +; GFX11-NEXT: scratch_store_b64 off, v[0:1], s32 +; GFX11-NEXT: s_swappc_b64 s[30:31], s[34:35] ; GFX11-NEXT: v_readlane_b32 s31, v40, 27 ; GFX11-NEXT: v_readlane_b32 s30, v40, 26 ; GFX11-NEXT: v_readlane_b32 s29, v40, 25 @@ -15071,9 +14440,8 @@ define amdgpu_gfx void @test_call_external_void_func_v32i32_inreg() #0 { ; GFX10-SCRATCH-NEXT: s_waitcnt_depctr 0xffe3 ; GFX10-SCRATCH-NEXT: s_mov_b32 exec_lo, s1 ; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s0, 28 -; GFX10-SCRATCH-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x0 +; GFX10-SCRATCH-NEXT: s_load_dwordx2 s[34:35], s[0:1], 0x0 ; GFX10-SCRATCH-NEXT: s_add_i32 s32, s32, 16 -; GFX10-SCRATCH-NEXT: s_add_i32 s2, s32, 16 ; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s4, 0 ; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s5, 1 ; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s6, 2 @@ -15090,44 +14458,29 @@ define amdgpu_gfx void @test_call_external_void_func_v32i32_inreg() #0 { ; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s17, 13 ; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s18, 14 ; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s19, 15 -; GFX10-SCRATCH-NEXT: s_waitcnt lgkmcnt(0) -; GFX10-SCRATCH-NEXT: s_clause 0x1 -; GFX10-SCRATCH-NEXT: s_load_dwordx16 s[36:51], s[0:1], 0x40 -; GFX10-SCRATCH-NEXT: s_load_dwordx16 s[4:19], s[0:1], 0x0 -; GFX10-SCRATCH-NEXT: s_mov_b32 s1, external_void_func_v32i32_inreg@abs32@hi -; GFX10-SCRATCH-NEXT: s_mov_b32 s0, external_void_func_v32i32_inreg@abs32@lo ; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s20, 16 ; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s21, 17 ; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s22, 18 -; GFX10-SCRATCH-NEXT: s_waitcnt lgkmcnt(0) -; GFX10-SCRATCH-NEXT: v_mov_b32_e32 v4, s50 ; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s23, 19 -; GFX10-SCRATCH-NEXT: v_mov_b32_e32 v5, s51 -; GFX10-SCRATCH-NEXT: v_mov_b32_e32 v0, s46 -; GFX10-SCRATCH-NEXT: v_mov_b32_e32 v1, s47 -; GFX10-SCRATCH-NEXT: v_mov_b32_e32 v2, s48 ; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s24, 20 -; GFX10-SCRATCH-NEXT: v_mov_b32_e32 v3, s49 -; GFX10-SCRATCH-NEXT: s_mov_b32 s20, s36 -; GFX10-SCRATCH-NEXT: s_mov_b32 s21, s37 -; GFX10-SCRATCH-NEXT: s_mov_b32 s22, s38 ; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s25, 21 -; GFX10-SCRATCH-NEXT: s_mov_b32 s23, s39 -; GFX10-SCRATCH-NEXT: s_mov_b32 s24, s40 -; GFX10-SCRATCH-NEXT: s_mov_b32 s25, s41 -; GFX10-SCRATCH-NEXT: scratch_store_dwordx2 off, v[4:5], s2 -; GFX10-SCRATCH-NEXT: scratch_store_dwordx4 off, v[0:3], s32 ; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s26, 22 -; GFX10-SCRATCH-NEXT: s_mov_b32 s26, s42 ; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s27, 23 -; GFX10-SCRATCH-NEXT: s_mov_b32 s27, s43 ; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s28, 24 -; GFX10-SCRATCH-NEXT: s_mov_b32 s28, s44 ; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s29, 25 -; GFX10-SCRATCH-NEXT: s_mov_b32 s29, s45 ; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s30, 26 ; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s31, 27 -; GFX10-SCRATCH-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX10-SCRATCH-NEXT: s_waitcnt lgkmcnt(0) +; GFX10-SCRATCH-NEXT: s_clause 0x1 +; GFX10-SCRATCH-NEXT: s_load_dwordx16 s[16:31], s[34:35], 0x40 +; GFX10-SCRATCH-NEXT: s_load_dwordx16 s[0:15], s[34:35], 0x0 +; GFX10-SCRATCH-NEXT: s_mov_b32 s35, external_void_func_v32i32_inreg@abs32@hi +; GFX10-SCRATCH-NEXT: s_mov_b32 s34, external_void_func_v32i32_inreg@abs32@lo +; GFX10-SCRATCH-NEXT: s_waitcnt lgkmcnt(0) +; GFX10-SCRATCH-NEXT: v_mov_b32_e32 v0, s30 +; GFX10-SCRATCH-NEXT: v_mov_b32_e32 v1, s31 +; GFX10-SCRATCH-NEXT: scratch_store_dwordx2 off, v[0:1], s32 +; GFX10-SCRATCH-NEXT: s_swappc_b64 s[30:31], s[34:35] ; GFX10-SCRATCH-NEXT: v_readlane_b32 s31, v40, 27 ; GFX10-SCRATCH-NEXT: v_readlane_b32 s30, v40, 26 ; GFX10-SCRATCH-NEXT: v_readlane_b32 s29, v40, 25 @@ -15196,55 +14549,53 @@ define amdgpu_gfx void @test_call_external_void_func_v32i32_i32_inreg(i32) #0 { ; GFX9-NEXT: v_writelane_b32 v40, s16, 12 ; GFX9-NEXT: v_writelane_b32 v40, s17, 13 ; GFX9-NEXT: v_writelane_b32 v40, s18, 14 -; GFX9-NEXT: s_load_dwordx2 s[34:35], s[34:35], 0x0 ; GFX9-NEXT: v_writelane_b32 v40, s19, 15 ; GFX9-NEXT: v_writelane_b32 v40, s20, 16 ; GFX9-NEXT: v_writelane_b32 v40, s21, 17 ; GFX9-NEXT: v_writelane_b32 v40, s22, 18 ; GFX9-NEXT: v_writelane_b32 v40, s23, 19 -; GFX9-NEXT: s_waitcnt lgkmcnt(0) -; GFX9-NEXT: s_load_dword s52, s[34:35], 0x0 -; GFX9-NEXT: ; kill: killed $sgpr34_sgpr35 -; GFX9-NEXT: ; kill: killed $sgpr34_sgpr35 -; GFX9-NEXT: s_load_dwordx16 s[36:51], s[34:35], 0x40 -; GFX9-NEXT: s_load_dwordx16 s[4:19], s[34:35], 0x0 ; GFX9-NEXT: v_writelane_b32 v40, s24, 20 +; GFX9-NEXT: s_load_dwordx2 s[34:35], s[34:35], 0x0 ; GFX9-NEXT: v_writelane_b32 v40, s25, 21 -; GFX9-NEXT: s_addk_i32 s32, 0x400 ; GFX9-NEXT: v_writelane_b32 v40, s26, 22 -; GFX9-NEXT: s_waitcnt lgkmcnt(0) -; GFX9-NEXT: v_mov_b32_e32 v0, s52 ; GFX9-NEXT: v_writelane_b32 v40, s27, 23 -; GFX9-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:24 -; GFX9-NEXT: v_mov_b32_e32 v0, s46 ; GFX9-NEXT: v_writelane_b32 v40, s28, 24 -; GFX9-NEXT: v_mov_b32_e32 v1, s47 -; GFX9-NEXT: v_mov_b32_e32 v2, s48 -; GFX9-NEXT: buffer_store_dword v0, off, s[0:3], s32 -; GFX9-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:4 -; GFX9-NEXT: buffer_store_dword v2, off, s[0:3], s32 offset:8 -; GFX9-NEXT: v_mov_b32_e32 v0, s49 ; GFX9-NEXT: v_writelane_b32 v40, s29, 25 -; GFX9-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:12 -; GFX9-NEXT: v_mov_b32_e32 v0, s50 +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: s_load_dword s52, s[34:35], 0x0 ; GFX9-NEXT: v_writelane_b32 v40, s30, 26 -; GFX9-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:16 -; GFX9-NEXT: v_mov_b32_e32 v0, s51 -; GFX9-NEXT: s_mov_b32 s35, external_void_func_v32i32_i32_inreg@abs32@hi -; GFX9-NEXT: s_mov_b32 s34, external_void_func_v32i32_i32_inreg@abs32@lo -; GFX9-NEXT: s_mov_b32 s20, s36 -; GFX9-NEXT: s_mov_b32 s21, s37 -; GFX9-NEXT: s_mov_b32 s22, s38 -; GFX9-NEXT: s_mov_b32 s23, s39 -; GFX9-NEXT: s_mov_b32 s24, s40 -; GFX9-NEXT: s_mov_b32 s25, s41 -; GFX9-NEXT: s_mov_b32 s26, s42 -; GFX9-NEXT: s_mov_b32 s27, s43 -; GFX9-NEXT: s_mov_b32 s28, s44 -; GFX9-NEXT: s_mov_b32 s29, s45 ; GFX9-NEXT: v_writelane_b32 v40, s31, 27 -; GFX9-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:20 -; GFX9-NEXT: s_swappc_b64 s[30:31], s[34:35] +; GFX9-NEXT: s_load_dwordx16 s[16:31], s[34:35], 0x40 +; GFX9-NEXT: s_load_dwordx16 s[36:51], s[34:35], 0x0 +; GFX9-NEXT: s_addk_i32 s32, 0x400 +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: v_mov_b32_e32 v0, s52 +; GFX9-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:8 +; GFX9-NEXT: v_mov_b32_e32 v0, s30 +; GFX9-NEXT: s_mov_b32 s53, external_void_func_v32i32_i32_inreg@abs32@hi +; GFX9-NEXT: v_mov_b32_e32 v1, s31 +; GFX9-NEXT: buffer_store_dword v0, off, s[0:3], s32 +; GFX9-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:4 +; GFX9-NEXT: s_mov_b32 s52, external_void_func_v32i32_i32_inreg@abs32@lo +; GFX9-NEXT: s_mov_b32 s0, s36 +; GFX9-NEXT: s_mov_b32 s1, s37 +; GFX9-NEXT: s_mov_b32 s2, s38 +; GFX9-NEXT: s_mov_b32 s3, s39 +; GFX9-NEXT: s_mov_b32 s4, s40 +; GFX9-NEXT: s_mov_b32 s5, s41 +; GFX9-NEXT: s_mov_b32 s6, s42 +; GFX9-NEXT: s_mov_b32 s7, s43 +; GFX9-NEXT: s_mov_b32 s8, s44 +; GFX9-NEXT: s_mov_b32 s9, s45 +; GFX9-NEXT: s_mov_b32 s10, s46 +; GFX9-NEXT: s_mov_b32 s11, s47 +; GFX9-NEXT: s_mov_b32 s12, s48 +; GFX9-NEXT: s_mov_b32 s13, s49 +; GFX9-NEXT: s_mov_b32 s14, s50 +; GFX9-NEXT: s_mov_b32 s15, s51 +; GFX9-NEXT: ; kill: killed $sgpr34_sgpr35 +; GFX9-NEXT: ; kill: killed $sgpr34_sgpr35 +; GFX9-NEXT: s_swappc_b64 s[30:31], s[52:53] ; GFX9-NEXT: v_readlane_b32 s31, v40, 27 ; GFX9-NEXT: v_readlane_b32 s30, v40, 26 ; GFX9-NEXT: v_readlane_b32 s29, v40, 25 @@ -15310,52 +14661,51 @@ define amdgpu_gfx void @test_call_external_void_func_v32i32_i32_inreg(i32) #0 { ; GFX10-NEXT: v_writelane_b32 v40, s17, 13 ; GFX10-NEXT: v_writelane_b32 v40, s18, 14 ; GFX10-NEXT: v_writelane_b32 v40, s19, 15 -; GFX10-NEXT: s_waitcnt lgkmcnt(0) -; GFX10-NEXT: s_clause 0x2 -; GFX10-NEXT: s_load_dword s52, s[34:35], 0x0 -; GFX10-NEXT: ; meta instruction -; GFX10-NEXT: ; meta instruction -; GFX10-NEXT: s_load_dwordx16 s[36:51], s[34:35], 0x40 -; GFX10-NEXT: s_load_dwordx16 s[4:19], s[34:35], 0x0 -; GFX10-NEXT: s_mov_b32 s35, external_void_func_v32i32_i32_inreg@abs32@hi -; GFX10-NEXT: s_mov_b32 s34, external_void_func_v32i32_i32_inreg@abs32@lo ; GFX10-NEXT: v_writelane_b32 v40, s20, 16 ; GFX10-NEXT: v_writelane_b32 v40, s21, 17 ; GFX10-NEXT: v_writelane_b32 v40, s22, 18 -; GFX10-NEXT: s_waitcnt lgkmcnt(0) -; GFX10-NEXT: v_mov_b32_e32 v0, s52 -; GFX10-NEXT: v_mov_b32_e32 v1, s47 ; GFX10-NEXT: v_writelane_b32 v40, s23, 19 -; GFX10-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:24 -; GFX10-NEXT: v_mov_b32_e32 v0, s46 -; GFX10-NEXT: v_mov_b32_e32 v2, s48 -; GFX10-NEXT: v_mov_b32_e32 v3, s49 ; GFX10-NEXT: v_writelane_b32 v40, s24, 20 -; GFX10-NEXT: s_mov_b32 s20, s36 -; GFX10-NEXT: s_mov_b32 s21, s37 -; GFX10-NEXT: s_mov_b32 s22, s38 -; GFX10-NEXT: s_mov_b32 s23, s39 ; GFX10-NEXT: v_writelane_b32 v40, s25, 21 -; GFX10-NEXT: s_mov_b32 s24, s40 -; GFX10-NEXT: s_mov_b32 s25, s41 -; GFX10-NEXT: v_mov_b32_e32 v4, s50 -; GFX10-NEXT: v_mov_b32_e32 v5, s51 ; GFX10-NEXT: v_writelane_b32 v40, s26, 22 -; GFX10-NEXT: s_mov_b32 s26, s42 -; GFX10-NEXT: buffer_store_dword v0, off, s[0:3], s32 -; GFX10-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:4 -; GFX10-NEXT: buffer_store_dword v2, off, s[0:3], s32 offset:8 -; GFX10-NEXT: buffer_store_dword v3, off, s[0:3], s32 offset:12 -; GFX10-NEXT: buffer_store_dword v4, off, s[0:3], s32 offset:16 -; GFX10-NEXT: buffer_store_dword v5, off, s[0:3], s32 offset:20 ; GFX10-NEXT: v_writelane_b32 v40, s27, 23 -; GFX10-NEXT: s_mov_b32 s27, s43 ; GFX10-NEXT: v_writelane_b32 v40, s28, 24 -; GFX10-NEXT: s_mov_b32 s28, s44 ; GFX10-NEXT: v_writelane_b32 v40, s29, 25 -; GFX10-NEXT: s_mov_b32 s29, s45 ; GFX10-NEXT: v_writelane_b32 v40, s30, 26 ; GFX10-NEXT: v_writelane_b32 v40, s31, 27 +; GFX10-NEXT: s_waitcnt lgkmcnt(0) +; GFX10-NEXT: s_clause 0x2 +; GFX10-NEXT: s_load_dword s52, s[34:35], 0x0 +; GFX10-NEXT: ; meta instruction +; GFX10-NEXT: ; meta instruction +; GFX10-NEXT: s_load_dwordx16 s[16:31], s[34:35], 0x40 +; GFX10-NEXT: s_load_dwordx16 s[36:51], s[34:35], 0x0 +; GFX10-NEXT: s_mov_b32 s35, external_void_func_v32i32_i32_inreg@abs32@hi +; GFX10-NEXT: s_mov_b32 s34, external_void_func_v32i32_i32_inreg@abs32@lo +; GFX10-NEXT: s_waitcnt lgkmcnt(0) +; GFX10-NEXT: v_mov_b32_e32 v0, s52 +; GFX10-NEXT: v_mov_b32_e32 v1, s30 +; GFX10-NEXT: v_mov_b32_e32 v2, s31 +; GFX10-NEXT: s_mov_b32 s4, s40 +; GFX10-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:8 +; GFX10-NEXT: buffer_store_dword v1, off, s[0:3], s32 +; GFX10-NEXT: buffer_store_dword v2, off, s[0:3], s32 offset:4 +; GFX10-NEXT: s_mov_b32 s5, s41 +; GFX10-NEXT: s_mov_b32 s6, s42 +; GFX10-NEXT: s_mov_b32 s7, s43 +; GFX10-NEXT: s_mov_b32 s8, s44 +; GFX10-NEXT: s_mov_b32 s9, s45 +; GFX10-NEXT: s_mov_b32 s10, s46 +; GFX10-NEXT: s_mov_b32 s11, s47 +; GFX10-NEXT: s_mov_b32 s12, s48 +; GFX10-NEXT: s_mov_b32 s13, s49 +; GFX10-NEXT: s_mov_b32 s14, s50 +; GFX10-NEXT: s_mov_b32 s15, s51 +; GFX10-NEXT: s_waitcnt_depctr 0xffe3 +; GFX10-NEXT: s_mov_b32 s0, s36 +; GFX10-NEXT: s_mov_b32 s1, s37 +; GFX10-NEXT: s_mov_b32 s2, s38 +; GFX10-NEXT: s_mov_b32 s3, s39 ; GFX10-NEXT: s_swappc_b64 s[30:31], s[34:35] ; GFX10-NEXT: v_readlane_b32 s31, v40, 27 ; GFX10-NEXT: v_readlane_b32 s30, v40, 26 @@ -15406,8 +14756,8 @@ define amdgpu_gfx void @test_call_external_void_func_v32i32_i32_inreg(i32) #0 { ; GFX11-NEXT: v_writelane_b32 v40, s0, 28 ; GFX11-NEXT: s_load_b64 s[0:1], s[0:1], 0x0 ; GFX11-NEXT: s_add_i32 s32, s32, 16 -; GFX11-NEXT: s_delay_alu instid0(SALU_CYCLE_1) -; GFX11-NEXT: s_add_i32 s3, s32, 16 +; GFX11-NEXT: s_mov_b32 s35, external_void_func_v32i32_i32_inreg@abs32@hi +; GFX11-NEXT: s_add_i32 s36, s32, 8 ; GFX11-NEXT: v_writelane_b32 v40, s4, 0 ; GFX11-NEXT: v_writelane_b32 v40, s5, 1 ; GFX11-NEXT: v_writelane_b32 v40, s6, 2 @@ -15424,46 +14774,30 @@ define amdgpu_gfx void @test_call_external_void_func_v32i32_i32_inreg(i32) #0 { ; GFX11-NEXT: v_writelane_b32 v40, s17, 13 ; GFX11-NEXT: v_writelane_b32 v40, s18, 14 ; GFX11-NEXT: v_writelane_b32 v40, s19, 15 -; GFX11-NEXT: s_waitcnt lgkmcnt(0) -; GFX11-NEXT: s_clause 0x2 -; GFX11-NEXT: s_load_b32 s2, s[0:1], 0x0 -; GFX11-NEXT: s_load_b512 s[36:51], s[0:1], 0x40 -; GFX11-NEXT: s_load_b512 s[4:19], s[0:1], 0x0 -; GFX11-NEXT: s_mov_b32 s1, external_void_func_v32i32_i32_inreg@abs32@hi -; GFX11-NEXT: s_mov_b32 s0, external_void_func_v32i32_i32_inreg@abs32@lo ; GFX11-NEXT: v_writelane_b32 v40, s20, 16 ; GFX11-NEXT: v_writelane_b32 v40, s21, 17 ; GFX11-NEXT: v_writelane_b32 v40, s22, 18 -; GFX11-NEXT: s_waitcnt lgkmcnt(0) -; GFX11-NEXT: v_dual_mov_b32 v6, s2 :: v_dual_mov_b32 v5, s51 ; GFX11-NEXT: v_writelane_b32 v40, s23, 19 -; GFX11-NEXT: v_dual_mov_b32 v4, s50 :: v_dual_mov_b32 v1, s47 -; GFX11-NEXT: v_dual_mov_b32 v0, s46 :: v_dual_mov_b32 v3, s49 ; GFX11-NEXT: v_writelane_b32 v40, s24, 20 -; GFX11-NEXT: v_mov_b32_e32 v2, s48 -; GFX11-NEXT: s_add_i32 s2, s32, 24 -; GFX11-NEXT: s_mov_b32 s20, s36 -; GFX11-NEXT: s_mov_b32 s21, s37 ; GFX11-NEXT: v_writelane_b32 v40, s25, 21 -; GFX11-NEXT: s_mov_b32 s22, s38 -; GFX11-NEXT: s_mov_b32 s23, s39 -; GFX11-NEXT: s_mov_b32 s24, s40 -; GFX11-NEXT: s_mov_b32 s25, s41 ; GFX11-NEXT: v_writelane_b32 v40, s26, 22 -; GFX11-NEXT: s_mov_b32 s26, s42 -; GFX11-NEXT: scratch_store_b32 off, v6, s2 -; GFX11-NEXT: scratch_store_b64 off, v[4:5], s3 -; GFX11-NEXT: scratch_store_b128 off, v[0:3], s32 ; GFX11-NEXT: v_writelane_b32 v40, s27, 23 -; GFX11-NEXT: s_mov_b32 s27, s43 ; GFX11-NEXT: v_writelane_b32 v40, s28, 24 -; GFX11-NEXT: s_mov_b32 s28, s44 ; GFX11-NEXT: v_writelane_b32 v40, s29, 25 -; GFX11-NEXT: s_mov_b32 s29, s45 ; GFX11-NEXT: v_writelane_b32 v40, s30, 26 ; GFX11-NEXT: v_writelane_b32 v40, s31, 27 -; GFX11-NEXT: s_swappc_b64 s[30:31], s[0:1] -; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX11-NEXT: s_waitcnt lgkmcnt(0) +; GFX11-NEXT: s_clause 0x2 +; GFX11-NEXT: s_load_b32 s34, s[0:1], 0x0 +; GFX11-NEXT: s_load_b512 s[16:31], s[0:1], 0x40 +; GFX11-NEXT: s_load_b512 s[0:15], s[0:1], 0x0 +; GFX11-NEXT: s_waitcnt lgkmcnt(0) +; GFX11-NEXT: v_dual_mov_b32 v2, s34 :: v_dual_mov_b32 v1, s31 +; GFX11-NEXT: v_mov_b32_e32 v0, s30 +; GFX11-NEXT: s_mov_b32 s34, external_void_func_v32i32_i32_inreg@abs32@lo +; GFX11-NEXT: scratch_store_b32 off, v2, s36 +; GFX11-NEXT: scratch_store_b64 off, v[0:1], s32 +; GFX11-NEXT: s_swappc_b64 s[30:31], s[34:35] ; GFX11-NEXT: v_readlane_b32 s31, v40, 27 ; GFX11-NEXT: v_readlane_b32 s30, v40, 26 ; GFX11-NEXT: v_readlane_b32 s29, v40, 25 @@ -15511,13 +14845,17 @@ define amdgpu_gfx void @test_call_external_void_func_v32i32_i32_inreg(i32) #0 { ; GFX10-SCRATCH-NEXT: s_waitcnt_depctr 0xffe3 ; GFX10-SCRATCH-NEXT: s_mov_b32 exec_lo, s1 ; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s0, 28 -; GFX10-SCRATCH-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x0 +; GFX10-SCRATCH-NEXT: s_clause 0x1 +; GFX10-SCRATCH-NEXT: s_load_dwordx2 s[34:35], s[0:1], 0x0 +; GFX10-SCRATCH-NEXT: s_load_dword s36, s[0:1], 0x0 ; GFX10-SCRATCH-NEXT: s_add_i32 s32, s32, 16 -; GFX10-SCRATCH-NEXT: s_add_i32 s3, s32, 16 ; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s4, 0 ; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s5, 1 ; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s6, 2 ; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s7, 3 +; GFX10-SCRATCH-NEXT: s_waitcnt lgkmcnt(0) +; GFX10-SCRATCH-NEXT: v_mov_b32_e32 v2, s36 +; GFX10-SCRATCH-NEXT: s_add_i32 s36, s32, 8 ; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s8, 4 ; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s9, 5 ; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s10, 6 @@ -15530,50 +14868,29 @@ define amdgpu_gfx void @test_call_external_void_func_v32i32_i32_inreg(i32) #0 { ; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s17, 13 ; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s18, 14 ; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s19, 15 -; GFX10-SCRATCH-NEXT: s_waitcnt lgkmcnt(0) -; GFX10-SCRATCH-NEXT: s_clause 0x2 -; GFX10-SCRATCH-NEXT: s_load_dword s2, s[0:1], 0x0 -; GFX10-SCRATCH-NEXT: ; meta instruction -; GFX10-SCRATCH-NEXT: ; meta instruction -; GFX10-SCRATCH-NEXT: s_load_dwordx16 s[36:51], s[0:1], 0x40 -; GFX10-SCRATCH-NEXT: s_load_dwordx16 s[4:19], s[0:1], 0x0 -; GFX10-SCRATCH-NEXT: s_mov_b32 s1, external_void_func_v32i32_i32_inreg@abs32@hi -; GFX10-SCRATCH-NEXT: s_mov_b32 s0, external_void_func_v32i32_i32_inreg@abs32@lo ; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s20, 16 ; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s21, 17 ; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s22, 18 -; GFX10-SCRATCH-NEXT: s_waitcnt lgkmcnt(0) -; GFX10-SCRATCH-NEXT: v_mov_b32_e32 v6, s2 -; GFX10-SCRATCH-NEXT: s_add_i32 s2, s32, 24 -; GFX10-SCRATCH-NEXT: v_mov_b32_e32 v4, s50 ; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s23, 19 -; GFX10-SCRATCH-NEXT: v_mov_b32_e32 v5, s51 -; GFX10-SCRATCH-NEXT: v_mov_b32_e32 v0, s46 -; GFX10-SCRATCH-NEXT: v_mov_b32_e32 v1, s47 -; GFX10-SCRATCH-NEXT: v_mov_b32_e32 v2, s48 ; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s24, 20 -; GFX10-SCRATCH-NEXT: v_mov_b32_e32 v3, s49 -; GFX10-SCRATCH-NEXT: s_mov_b32 s20, s36 -; GFX10-SCRATCH-NEXT: s_mov_b32 s21, s37 -; GFX10-SCRATCH-NEXT: s_mov_b32 s22, s38 ; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s25, 21 -; GFX10-SCRATCH-NEXT: s_mov_b32 s23, s39 -; GFX10-SCRATCH-NEXT: s_mov_b32 s24, s40 -; GFX10-SCRATCH-NEXT: s_mov_b32 s25, s41 -; GFX10-SCRATCH-NEXT: scratch_store_dword off, v6, s2 -; GFX10-SCRATCH-NEXT: scratch_store_dwordx2 off, v[4:5], s3 -; GFX10-SCRATCH-NEXT: scratch_store_dwordx4 off, v[0:3], s32 ; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s26, 22 -; GFX10-SCRATCH-NEXT: s_mov_b32 s26, s42 ; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s27, 23 -; GFX10-SCRATCH-NEXT: s_mov_b32 s27, s43 ; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s28, 24 -; GFX10-SCRATCH-NEXT: s_mov_b32 s28, s44 ; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s29, 25 -; GFX10-SCRATCH-NEXT: s_mov_b32 s29, s45 ; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s30, 26 ; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s31, 27 -; GFX10-SCRATCH-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX10-SCRATCH-NEXT: s_clause 0x1 +; GFX10-SCRATCH-NEXT: s_load_dwordx16 s[16:31], s[34:35], 0x40 +; GFX10-SCRATCH-NEXT: s_load_dwordx16 s[0:15], s[34:35], 0x0 +; GFX10-SCRATCH-NEXT: s_mov_b32 s35, external_void_func_v32i32_i32_inreg@abs32@hi +; GFX10-SCRATCH-NEXT: s_mov_b32 s34, external_void_func_v32i32_i32_inreg@abs32@lo +; GFX10-SCRATCH-NEXT: s_waitcnt lgkmcnt(0) +; GFX10-SCRATCH-NEXT: v_mov_b32_e32 v0, s30 +; GFX10-SCRATCH-NEXT: v_mov_b32_e32 v1, s31 +; GFX10-SCRATCH-NEXT: scratch_store_dword off, v2, s36 +; GFX10-SCRATCH-NEXT: scratch_store_dwordx2 off, v[0:1], s32 +; GFX10-SCRATCH-NEXT: s_swappc_b64 s[30:31], s[34:35] ; GFX10-SCRATCH-NEXT: v_readlane_b32 s31, v40, 27 ; GFX10-SCRATCH-NEXT: v_readlane_b32 s30, v40, 26 ; GFX10-SCRATCH-NEXT: v_readlane_b32 s29, v40, 25 @@ -17397,6 +16714,7 @@ define amdgpu_gfx void @test_call_external_void_func_bf16_inreg(i16 inreg %arg) ; GFX9-NEXT: v_writelane_b32 v40, s30, 0 ; GFX9-NEXT: s_mov_b32 s35, external_void_func_bf16@abs32@hi ; GFX9-NEXT: s_mov_b32 s34, external_void_func_bf16@abs32@lo +; GFX9-NEXT: s_mov_b32 s0, s4 ; GFX9-NEXT: s_addk_i32 s32, 0x400 ; GFX9-NEXT: v_writelane_b32 v40, s31, 1 ; GFX9-NEXT: s_swappc_b64 s[30:31], s[34:35] @@ -17423,6 +16741,7 @@ define amdgpu_gfx void @test_call_external_void_func_bf16_inreg(i16 inreg %arg) ; GFX10-NEXT: v_writelane_b32 v40, s34, 2 ; GFX10-NEXT: s_mov_b32 s35, external_void_func_bf16@abs32@hi ; GFX10-NEXT: s_mov_b32 s34, external_void_func_bf16@abs32@lo +; GFX10-NEXT: s_mov_b32 s0, s4 ; GFX10-NEXT: s_addk_i32 s32, 0x200 ; GFX10-NEXT: v_writelane_b32 v40, s30, 0 ; GFX10-NEXT: v_writelane_b32 v40, s31, 1 @@ -17442,18 +16761,18 @@ define amdgpu_gfx void @test_call_external_void_func_bf16_inreg(i16 inreg %arg) ; GFX11-LABEL: test_call_external_void_func_bf16_inreg: ; GFX11: ; %bb.0: ; GFX11-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GFX11-NEXT: s_mov_b32 s0, s33 +; GFX11-NEXT: s_mov_b32 s1, s33 ; GFX11-NEXT: s_mov_b32 s33, s32 -; GFX11-NEXT: s_or_saveexec_b32 s1, -1 +; GFX11-NEXT: s_or_saveexec_b32 s2, -1 ; GFX11-NEXT: scratch_store_b32 off, v40, s33 ; 4-byte Folded Spill -; GFX11-NEXT: s_mov_b32 exec_lo, s1 -; GFX11-NEXT: v_writelane_b32 v40, s0, 2 -; GFX11-NEXT: s_mov_b32 s1, external_void_func_bf16@abs32@hi -; GFX11-NEXT: s_mov_b32 s0, external_void_func_bf16@abs32@lo +; GFX11-NEXT: s_mov_b32 exec_lo, s2 +; GFX11-NEXT: v_writelane_b32 v40, s1, 2 +; GFX11-NEXT: s_mov_b32 s3, external_void_func_bf16@abs32@hi +; GFX11-NEXT: s_mov_b32 s2, external_void_func_bf16@abs32@lo ; GFX11-NEXT: s_add_i32 s32, s32, 16 ; GFX11-NEXT: v_writelane_b32 v40, s30, 0 ; GFX11-NEXT: v_writelane_b32 v40, s31, 1 -; GFX11-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX11-NEXT: s_swappc_b64 s[30:31], s[2:3] ; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_1) ; GFX11-NEXT: v_readlane_b32 s31, v40, 1 ; GFX11-NEXT: v_readlane_b32 s30, v40, 0 @@ -17469,19 +16788,19 @@ define amdgpu_gfx void @test_call_external_void_func_bf16_inreg(i16 inreg %arg) ; GFX10-SCRATCH-LABEL: test_call_external_void_func_bf16_inreg: ; GFX10-SCRATCH: ; %bb.0: ; GFX10-SCRATCH-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GFX10-SCRATCH-NEXT: s_mov_b32 s0, s33 +; GFX10-SCRATCH-NEXT: s_mov_b32 s1, s33 ; GFX10-SCRATCH-NEXT: s_mov_b32 s33, s32 -; GFX10-SCRATCH-NEXT: s_or_saveexec_b32 s1, -1 +; GFX10-SCRATCH-NEXT: s_or_saveexec_b32 s2, -1 ; GFX10-SCRATCH-NEXT: scratch_store_dword off, v40, s33 ; 4-byte Folded Spill ; GFX10-SCRATCH-NEXT: s_waitcnt_depctr 0xffe3 -; GFX10-SCRATCH-NEXT: s_mov_b32 exec_lo, s1 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s0, 2 -; GFX10-SCRATCH-NEXT: s_mov_b32 s1, external_void_func_bf16@abs32@hi -; GFX10-SCRATCH-NEXT: s_mov_b32 s0, external_void_func_bf16@abs32@lo +; GFX10-SCRATCH-NEXT: s_mov_b32 exec_lo, s2 +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s1, 2 +; GFX10-SCRATCH-NEXT: s_mov_b32 s3, external_void_func_bf16@abs32@hi +; GFX10-SCRATCH-NEXT: s_mov_b32 s2, external_void_func_bf16@abs32@lo ; GFX10-SCRATCH-NEXT: s_add_i32 s32, s32, 16 ; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s30, 0 ; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s31, 1 -; GFX10-SCRATCH-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX10-SCRATCH-NEXT: s_swappc_b64 s[30:31], s[2:3] ; GFX10-SCRATCH-NEXT: v_readlane_b32 s31, v40, 1 ; GFX10-SCRATCH-NEXT: v_readlane_b32 s30, v40, 0 ; GFX10-SCRATCH-NEXT: v_readlane_b32 s0, v40, 2 @@ -17511,6 +16830,7 @@ define amdgpu_gfx void @test_call_external_void_func_v1bf16_inreg(i16 inreg %arg ; GFX9-NEXT: v_writelane_b32 v40, s30, 0 ; GFX9-NEXT: s_mov_b32 s35, external_void_func_v1bf16@abs32@hi ; GFX9-NEXT: s_mov_b32 s34, external_void_func_v1bf16@abs32@lo +; GFX9-NEXT: s_mov_b32 s0, s4 ; GFX9-NEXT: s_addk_i32 s32, 0x400 ; GFX9-NEXT: v_writelane_b32 v40, s31, 1 ; GFX9-NEXT: s_swappc_b64 s[30:31], s[34:35] @@ -17537,6 +16857,7 @@ define amdgpu_gfx void @test_call_external_void_func_v1bf16_inreg(i16 inreg %arg ; GFX10-NEXT: v_writelane_b32 v40, s34, 2 ; GFX10-NEXT: s_mov_b32 s35, external_void_func_v1bf16@abs32@hi ; GFX10-NEXT: s_mov_b32 s34, external_void_func_v1bf16@abs32@lo +; GFX10-NEXT: s_mov_b32 s0, s4 ; GFX10-NEXT: s_addk_i32 s32, 0x200 ; GFX10-NEXT: v_writelane_b32 v40, s30, 0 ; GFX10-NEXT: v_writelane_b32 v40, s31, 1 @@ -17556,18 +16877,18 @@ define amdgpu_gfx void @test_call_external_void_func_v1bf16_inreg(i16 inreg %arg ; GFX11-LABEL: test_call_external_void_func_v1bf16_inreg: ; GFX11: ; %bb.0: ; GFX11-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GFX11-NEXT: s_mov_b32 s0, s33 +; GFX11-NEXT: s_mov_b32 s1, s33 ; GFX11-NEXT: s_mov_b32 s33, s32 -; GFX11-NEXT: s_or_saveexec_b32 s1, -1 +; GFX11-NEXT: s_or_saveexec_b32 s2, -1 ; GFX11-NEXT: scratch_store_b32 off, v40, s33 ; 4-byte Folded Spill -; GFX11-NEXT: s_mov_b32 exec_lo, s1 -; GFX11-NEXT: v_writelane_b32 v40, s0, 2 -; GFX11-NEXT: s_mov_b32 s1, external_void_func_v1bf16@abs32@hi -; GFX11-NEXT: s_mov_b32 s0, external_void_func_v1bf16@abs32@lo +; GFX11-NEXT: s_mov_b32 exec_lo, s2 +; GFX11-NEXT: v_writelane_b32 v40, s1, 2 +; GFX11-NEXT: s_mov_b32 s3, external_void_func_v1bf16@abs32@hi +; GFX11-NEXT: s_mov_b32 s2, external_void_func_v1bf16@abs32@lo ; GFX11-NEXT: s_add_i32 s32, s32, 16 ; GFX11-NEXT: v_writelane_b32 v40, s30, 0 ; GFX11-NEXT: v_writelane_b32 v40, s31, 1 -; GFX11-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX11-NEXT: s_swappc_b64 s[30:31], s[2:3] ; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_1) ; GFX11-NEXT: v_readlane_b32 s31, v40, 1 ; GFX11-NEXT: v_readlane_b32 s30, v40, 0 @@ -17583,19 +16904,19 @@ define amdgpu_gfx void @test_call_external_void_func_v1bf16_inreg(i16 inreg %arg ; GFX10-SCRATCH-LABEL: test_call_external_void_func_v1bf16_inreg: ; GFX10-SCRATCH: ; %bb.0: ; GFX10-SCRATCH-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GFX10-SCRATCH-NEXT: s_mov_b32 s0, s33 +; GFX10-SCRATCH-NEXT: s_mov_b32 s1, s33 ; GFX10-SCRATCH-NEXT: s_mov_b32 s33, s32 -; GFX10-SCRATCH-NEXT: s_or_saveexec_b32 s1, -1 +; GFX10-SCRATCH-NEXT: s_or_saveexec_b32 s2, -1 ; GFX10-SCRATCH-NEXT: scratch_store_dword off, v40, s33 ; 4-byte Folded Spill ; GFX10-SCRATCH-NEXT: s_waitcnt_depctr 0xffe3 -; GFX10-SCRATCH-NEXT: s_mov_b32 exec_lo, s1 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s0, 2 -; GFX10-SCRATCH-NEXT: s_mov_b32 s1, external_void_func_v1bf16@abs32@hi -; GFX10-SCRATCH-NEXT: s_mov_b32 s0, external_void_func_v1bf16@abs32@lo +; GFX10-SCRATCH-NEXT: s_mov_b32 exec_lo, s2 +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s1, 2 +; GFX10-SCRATCH-NEXT: s_mov_b32 s3, external_void_func_v1bf16@abs32@hi +; GFX10-SCRATCH-NEXT: s_mov_b32 s2, external_void_func_v1bf16@abs32@lo ; GFX10-SCRATCH-NEXT: s_add_i32 s32, s32, 16 ; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s30, 0 ; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s31, 1 -; GFX10-SCRATCH-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX10-SCRATCH-NEXT: s_swappc_b64 s[30:31], s[2:3] ; GFX10-SCRATCH-NEXT: v_readlane_b32 s31, v40, 1 ; GFX10-SCRATCH-NEXT: v_readlane_b32 s30, v40, 0 ; GFX10-SCRATCH-NEXT: v_readlane_b32 s0, v40, 2 @@ -17625,6 +16946,7 @@ define amdgpu_gfx void @test_call_external_void_func_v2bf16_inreg(i32 inreg %arg ; GFX9-NEXT: v_writelane_b32 v40, s30, 0 ; GFX9-NEXT: s_mov_b32 s35, external_void_func_v2bf16@abs32@hi ; GFX9-NEXT: s_mov_b32 s34, external_void_func_v2bf16@abs32@lo +; GFX9-NEXT: s_mov_b32 s0, s4 ; GFX9-NEXT: s_addk_i32 s32, 0x400 ; GFX9-NEXT: v_writelane_b32 v40, s31, 1 ; GFX9-NEXT: s_swappc_b64 s[30:31], s[34:35] @@ -17651,6 +16973,7 @@ define amdgpu_gfx void @test_call_external_void_func_v2bf16_inreg(i32 inreg %arg ; GFX10-NEXT: v_writelane_b32 v40, s34, 2 ; GFX10-NEXT: s_mov_b32 s35, external_void_func_v2bf16@abs32@hi ; GFX10-NEXT: s_mov_b32 s34, external_void_func_v2bf16@abs32@lo +; GFX10-NEXT: s_mov_b32 s0, s4 ; GFX10-NEXT: s_addk_i32 s32, 0x200 ; GFX10-NEXT: v_writelane_b32 v40, s30, 0 ; GFX10-NEXT: v_writelane_b32 v40, s31, 1 @@ -17670,18 +16993,18 @@ define amdgpu_gfx void @test_call_external_void_func_v2bf16_inreg(i32 inreg %arg ; GFX11-LABEL: test_call_external_void_func_v2bf16_inreg: ; GFX11: ; %bb.0: ; GFX11-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GFX11-NEXT: s_mov_b32 s0, s33 +; GFX11-NEXT: s_mov_b32 s1, s33 ; GFX11-NEXT: s_mov_b32 s33, s32 -; GFX11-NEXT: s_or_saveexec_b32 s1, -1 +; GFX11-NEXT: s_or_saveexec_b32 s2, -1 ; GFX11-NEXT: scratch_store_b32 off, v40, s33 ; 4-byte Folded Spill -; GFX11-NEXT: s_mov_b32 exec_lo, s1 -; GFX11-NEXT: v_writelane_b32 v40, s0, 2 -; GFX11-NEXT: s_mov_b32 s1, external_void_func_v2bf16@abs32@hi -; GFX11-NEXT: s_mov_b32 s0, external_void_func_v2bf16@abs32@lo +; GFX11-NEXT: s_mov_b32 exec_lo, s2 +; GFX11-NEXT: v_writelane_b32 v40, s1, 2 +; GFX11-NEXT: s_mov_b32 s3, external_void_func_v2bf16@abs32@hi +; GFX11-NEXT: s_mov_b32 s2, external_void_func_v2bf16@abs32@lo ; GFX11-NEXT: s_add_i32 s32, s32, 16 ; GFX11-NEXT: v_writelane_b32 v40, s30, 0 ; GFX11-NEXT: v_writelane_b32 v40, s31, 1 -; GFX11-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX11-NEXT: s_swappc_b64 s[30:31], s[2:3] ; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_1) ; GFX11-NEXT: v_readlane_b32 s31, v40, 1 ; GFX11-NEXT: v_readlane_b32 s30, v40, 0 @@ -17697,19 +17020,19 @@ define amdgpu_gfx void @test_call_external_void_func_v2bf16_inreg(i32 inreg %arg ; GFX10-SCRATCH-LABEL: test_call_external_void_func_v2bf16_inreg: ; GFX10-SCRATCH: ; %bb.0: ; GFX10-SCRATCH-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GFX10-SCRATCH-NEXT: s_mov_b32 s0, s33 +; GFX10-SCRATCH-NEXT: s_mov_b32 s1, s33 ; GFX10-SCRATCH-NEXT: s_mov_b32 s33, s32 -; GFX10-SCRATCH-NEXT: s_or_saveexec_b32 s1, -1 +; GFX10-SCRATCH-NEXT: s_or_saveexec_b32 s2, -1 ; GFX10-SCRATCH-NEXT: scratch_store_dword off, v40, s33 ; 4-byte Folded Spill ; GFX10-SCRATCH-NEXT: s_waitcnt_depctr 0xffe3 -; GFX10-SCRATCH-NEXT: s_mov_b32 exec_lo, s1 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s0, 2 -; GFX10-SCRATCH-NEXT: s_mov_b32 s1, external_void_func_v2bf16@abs32@hi -; GFX10-SCRATCH-NEXT: s_mov_b32 s0, external_void_func_v2bf16@abs32@lo +; GFX10-SCRATCH-NEXT: s_mov_b32 exec_lo, s2 +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s1, 2 +; GFX10-SCRATCH-NEXT: s_mov_b32 s3, external_void_func_v2bf16@abs32@hi +; GFX10-SCRATCH-NEXT: s_mov_b32 s2, external_void_func_v2bf16@abs32@lo ; GFX10-SCRATCH-NEXT: s_add_i32 s32, s32, 16 ; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s30, 0 ; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s31, 1 -; GFX10-SCRATCH-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX10-SCRATCH-NEXT: s_swappc_b64 s[30:31], s[2:3] ; GFX10-SCRATCH-NEXT: v_readlane_b32 s31, v40, 1 ; GFX10-SCRATCH-NEXT: v_readlane_b32 s30, v40, 0 ; GFX10-SCRATCH-NEXT: v_readlane_b32 s0, v40, 2 @@ -17739,6 +17062,8 @@ define amdgpu_gfx void @test_call_external_void_func_v3bf16_inreg(<3 x i16> inre ; GFX9-NEXT: v_writelane_b32 v40, s30, 0 ; GFX9-NEXT: s_mov_b32 s35, external_void_func_v3bf16@abs32@hi ; GFX9-NEXT: s_mov_b32 s34, external_void_func_v3bf16@abs32@lo +; GFX9-NEXT: s_mov_b32 s1, s5 +; GFX9-NEXT: s_mov_b32 s0, s4 ; GFX9-NEXT: s_addk_i32 s32, 0x400 ; GFX9-NEXT: v_writelane_b32 v40, s31, 1 ; GFX9-NEXT: s_swappc_b64 s[30:31], s[34:35] @@ -17765,8 +17090,10 @@ define amdgpu_gfx void @test_call_external_void_func_v3bf16_inreg(<3 x i16> inre ; GFX10-NEXT: v_writelane_b32 v40, s34, 2 ; GFX10-NEXT: s_mov_b32 s35, external_void_func_v3bf16@abs32@hi ; GFX10-NEXT: s_mov_b32 s34, external_void_func_v3bf16@abs32@lo -; GFX10-NEXT: s_addk_i32 s32, 0x200 +; GFX10-NEXT: s_mov_b32 s1, s5 +; GFX10-NEXT: s_mov_b32 s0, s4 ; GFX10-NEXT: v_writelane_b32 v40, s30, 0 +; GFX10-NEXT: s_addk_i32 s32, 0x200 ; GFX10-NEXT: v_writelane_b32 v40, s31, 1 ; GFX10-NEXT: s_swappc_b64 s[30:31], s[34:35] ; GFX10-NEXT: v_readlane_b32 s31, v40, 1 @@ -17784,18 +17111,18 @@ define amdgpu_gfx void @test_call_external_void_func_v3bf16_inreg(<3 x i16> inre ; GFX11-LABEL: test_call_external_void_func_v3bf16_inreg: ; GFX11: ; %bb.0: ; GFX11-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GFX11-NEXT: s_mov_b32 s0, s33 +; GFX11-NEXT: s_mov_b32 s2, s33 ; GFX11-NEXT: s_mov_b32 s33, s32 -; GFX11-NEXT: s_or_saveexec_b32 s1, -1 +; GFX11-NEXT: s_or_saveexec_b32 s3, -1 ; GFX11-NEXT: scratch_store_b32 off, v40, s33 ; 4-byte Folded Spill -; GFX11-NEXT: s_mov_b32 exec_lo, s1 -; GFX11-NEXT: v_writelane_b32 v40, s0, 2 -; GFX11-NEXT: s_mov_b32 s1, external_void_func_v3bf16@abs32@hi -; GFX11-NEXT: s_mov_b32 s0, external_void_func_v3bf16@abs32@lo +; GFX11-NEXT: s_mov_b32 exec_lo, s3 +; GFX11-NEXT: v_writelane_b32 v40, s2, 2 +; GFX11-NEXT: s_mov_b32 s3, external_void_func_v3bf16@abs32@hi +; GFX11-NEXT: s_mov_b32 s2, external_void_func_v3bf16@abs32@lo ; GFX11-NEXT: s_add_i32 s32, s32, 16 ; GFX11-NEXT: v_writelane_b32 v40, s30, 0 ; GFX11-NEXT: v_writelane_b32 v40, s31, 1 -; GFX11-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX11-NEXT: s_swappc_b64 s[30:31], s[2:3] ; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_1) ; GFX11-NEXT: v_readlane_b32 s31, v40, 1 ; GFX11-NEXT: v_readlane_b32 s30, v40, 0 @@ -17811,19 +17138,19 @@ define amdgpu_gfx void @test_call_external_void_func_v3bf16_inreg(<3 x i16> inre ; GFX10-SCRATCH-LABEL: test_call_external_void_func_v3bf16_inreg: ; GFX10-SCRATCH: ; %bb.0: ; GFX10-SCRATCH-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GFX10-SCRATCH-NEXT: s_mov_b32 s0, s33 +; GFX10-SCRATCH-NEXT: s_mov_b32 s2, s33 ; GFX10-SCRATCH-NEXT: s_mov_b32 s33, s32 -; GFX10-SCRATCH-NEXT: s_or_saveexec_b32 s1, -1 +; GFX10-SCRATCH-NEXT: s_or_saveexec_b32 s3, -1 ; GFX10-SCRATCH-NEXT: scratch_store_dword off, v40, s33 ; 4-byte Folded Spill ; GFX10-SCRATCH-NEXT: s_waitcnt_depctr 0xffe3 -; GFX10-SCRATCH-NEXT: s_mov_b32 exec_lo, s1 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s0, 2 -; GFX10-SCRATCH-NEXT: s_mov_b32 s1, external_void_func_v3bf16@abs32@hi -; GFX10-SCRATCH-NEXT: s_mov_b32 s0, external_void_func_v3bf16@abs32@lo +; GFX10-SCRATCH-NEXT: s_mov_b32 exec_lo, s3 +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s2, 2 +; GFX10-SCRATCH-NEXT: s_mov_b32 s3, external_void_func_v3bf16@abs32@hi +; GFX10-SCRATCH-NEXT: s_mov_b32 s2, external_void_func_v3bf16@abs32@lo ; GFX10-SCRATCH-NEXT: s_add_i32 s32, s32, 16 ; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s30, 0 ; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s31, 1 -; GFX10-SCRATCH-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX10-SCRATCH-NEXT: s_swappc_b64 s[30:31], s[2:3] ; GFX10-SCRATCH-NEXT: v_readlane_b32 s31, v40, 1 ; GFX10-SCRATCH-NEXT: v_readlane_b32 s30, v40, 0 ; GFX10-SCRATCH-NEXT: v_readlane_b32 s0, v40, 2 @@ -17853,6 +17180,8 @@ define amdgpu_gfx void @test_call_external_void_func_v4bf16_inreg(<4 x i16> inre ; GFX9-NEXT: v_writelane_b32 v40, s30, 0 ; GFX9-NEXT: s_mov_b32 s35, external_void_func_v4bf16@abs32@hi ; GFX9-NEXT: s_mov_b32 s34, external_void_func_v4bf16@abs32@lo +; GFX9-NEXT: s_mov_b32 s1, s5 +; GFX9-NEXT: s_mov_b32 s0, s4 ; GFX9-NEXT: s_addk_i32 s32, 0x400 ; GFX9-NEXT: v_writelane_b32 v40, s31, 1 ; GFX9-NEXT: s_swappc_b64 s[30:31], s[34:35] @@ -17879,8 +17208,10 @@ define amdgpu_gfx void @test_call_external_void_func_v4bf16_inreg(<4 x i16> inre ; GFX10-NEXT: v_writelane_b32 v40, s34, 2 ; GFX10-NEXT: s_mov_b32 s35, external_void_func_v4bf16@abs32@hi ; GFX10-NEXT: s_mov_b32 s34, external_void_func_v4bf16@abs32@lo -; GFX10-NEXT: s_addk_i32 s32, 0x200 +; GFX10-NEXT: s_mov_b32 s1, s5 +; GFX10-NEXT: s_mov_b32 s0, s4 ; GFX10-NEXT: v_writelane_b32 v40, s30, 0 +; GFX10-NEXT: s_addk_i32 s32, 0x200 ; GFX10-NEXT: v_writelane_b32 v40, s31, 1 ; GFX10-NEXT: s_swappc_b64 s[30:31], s[34:35] ; GFX10-NEXT: v_readlane_b32 s31, v40, 1 @@ -17898,18 +17229,18 @@ define amdgpu_gfx void @test_call_external_void_func_v4bf16_inreg(<4 x i16> inre ; GFX11-LABEL: test_call_external_void_func_v4bf16_inreg: ; GFX11: ; %bb.0: ; GFX11-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GFX11-NEXT: s_mov_b32 s0, s33 +; GFX11-NEXT: s_mov_b32 s2, s33 ; GFX11-NEXT: s_mov_b32 s33, s32 -; GFX11-NEXT: s_or_saveexec_b32 s1, -1 +; GFX11-NEXT: s_or_saveexec_b32 s3, -1 ; GFX11-NEXT: scratch_store_b32 off, v40, s33 ; 4-byte Folded Spill -; GFX11-NEXT: s_mov_b32 exec_lo, s1 -; GFX11-NEXT: v_writelane_b32 v40, s0, 2 -; GFX11-NEXT: s_mov_b32 s1, external_void_func_v4bf16@abs32@hi -; GFX11-NEXT: s_mov_b32 s0, external_void_func_v4bf16@abs32@lo +; GFX11-NEXT: s_mov_b32 exec_lo, s3 +; GFX11-NEXT: v_writelane_b32 v40, s2, 2 +; GFX11-NEXT: s_mov_b32 s3, external_void_func_v4bf16@abs32@hi +; GFX11-NEXT: s_mov_b32 s2, external_void_func_v4bf16@abs32@lo ; GFX11-NEXT: s_add_i32 s32, s32, 16 ; GFX11-NEXT: v_writelane_b32 v40, s30, 0 ; GFX11-NEXT: v_writelane_b32 v40, s31, 1 -; GFX11-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX11-NEXT: s_swappc_b64 s[30:31], s[2:3] ; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_1) ; GFX11-NEXT: v_readlane_b32 s31, v40, 1 ; GFX11-NEXT: v_readlane_b32 s30, v40, 0 @@ -17925,19 +17256,19 @@ define amdgpu_gfx void @test_call_external_void_func_v4bf16_inreg(<4 x i16> inre ; GFX10-SCRATCH-LABEL: test_call_external_void_func_v4bf16_inreg: ; GFX10-SCRATCH: ; %bb.0: ; GFX10-SCRATCH-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GFX10-SCRATCH-NEXT: s_mov_b32 s0, s33 +; GFX10-SCRATCH-NEXT: s_mov_b32 s2, s33 ; GFX10-SCRATCH-NEXT: s_mov_b32 s33, s32 -; GFX10-SCRATCH-NEXT: s_or_saveexec_b32 s1, -1 +; GFX10-SCRATCH-NEXT: s_or_saveexec_b32 s3, -1 ; GFX10-SCRATCH-NEXT: scratch_store_dword off, v40, s33 ; 4-byte Folded Spill ; GFX10-SCRATCH-NEXT: s_waitcnt_depctr 0xffe3 -; GFX10-SCRATCH-NEXT: s_mov_b32 exec_lo, s1 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s0, 2 -; GFX10-SCRATCH-NEXT: s_mov_b32 s1, external_void_func_v4bf16@abs32@hi -; GFX10-SCRATCH-NEXT: s_mov_b32 s0, external_void_func_v4bf16@abs32@lo +; GFX10-SCRATCH-NEXT: s_mov_b32 exec_lo, s3 +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s2, 2 +; GFX10-SCRATCH-NEXT: s_mov_b32 s3, external_void_func_v4bf16@abs32@hi +; GFX10-SCRATCH-NEXT: s_mov_b32 s2, external_void_func_v4bf16@abs32@lo ; GFX10-SCRATCH-NEXT: s_add_i32 s32, s32, 16 ; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s30, 0 ; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s31, 1 -; GFX10-SCRATCH-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX10-SCRATCH-NEXT: s_swappc_b64 s[30:31], s[2:3] ; GFX10-SCRATCH-NEXT: v_readlane_b32 s31, v40, 1 ; GFX10-SCRATCH-NEXT: v_readlane_b32 s30, v40, 0 ; GFX10-SCRATCH-NEXT: v_readlane_b32 s0, v40, 2 @@ -17967,6 +17298,10 @@ define amdgpu_gfx void @test_call_external_void_func_v8bf16_inreg(<8 x i16> inre ; GFX9-NEXT: v_writelane_b32 v40, s30, 0 ; GFX9-NEXT: s_mov_b32 s35, external_void_func_v8bf16@abs32@hi ; GFX9-NEXT: s_mov_b32 s34, external_void_func_v8bf16@abs32@lo +; GFX9-NEXT: s_mov_b32 s3, s7 +; GFX9-NEXT: s_mov_b32 s2, s6 +; GFX9-NEXT: s_mov_b32 s1, s5 +; GFX9-NEXT: s_mov_b32 s0, s4 ; GFX9-NEXT: s_addk_i32 s32, 0x400 ; GFX9-NEXT: v_writelane_b32 v40, s31, 1 ; GFX9-NEXT: s_swappc_b64 s[30:31], s[34:35] @@ -17993,8 +17328,12 @@ define amdgpu_gfx void @test_call_external_void_func_v8bf16_inreg(<8 x i16> inre ; GFX10-NEXT: v_writelane_b32 v40, s34, 2 ; GFX10-NEXT: s_mov_b32 s35, external_void_func_v8bf16@abs32@hi ; GFX10-NEXT: s_mov_b32 s34, external_void_func_v8bf16@abs32@lo -; GFX10-NEXT: s_addk_i32 s32, 0x200 +; GFX10-NEXT: s_mov_b32 s3, s7 +; GFX10-NEXT: s_mov_b32 s2, s6 ; GFX10-NEXT: v_writelane_b32 v40, s30, 0 +; GFX10-NEXT: s_mov_b32 s1, s5 +; GFX10-NEXT: s_mov_b32 s0, s4 +; GFX10-NEXT: s_addk_i32 s32, 0x200 ; GFX10-NEXT: v_writelane_b32 v40, s31, 1 ; GFX10-NEXT: s_swappc_b64 s[30:31], s[34:35] ; GFX10-NEXT: v_readlane_b32 s31, v40, 1 @@ -18012,18 +17351,18 @@ define amdgpu_gfx void @test_call_external_void_func_v8bf16_inreg(<8 x i16> inre ; GFX11-LABEL: test_call_external_void_func_v8bf16_inreg: ; GFX11: ; %bb.0: ; GFX11-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GFX11-NEXT: s_mov_b32 s0, s33 +; GFX11-NEXT: s_mov_b32 s34, s33 ; GFX11-NEXT: s_mov_b32 s33, s32 -; GFX11-NEXT: s_or_saveexec_b32 s1, -1 +; GFX11-NEXT: s_or_saveexec_b32 s35, -1 ; GFX11-NEXT: scratch_store_b32 off, v40, s33 ; 4-byte Folded Spill -; GFX11-NEXT: s_mov_b32 exec_lo, s1 -; GFX11-NEXT: v_writelane_b32 v40, s0, 2 -; GFX11-NEXT: s_mov_b32 s1, external_void_func_v8bf16@abs32@hi -; GFX11-NEXT: s_mov_b32 s0, external_void_func_v8bf16@abs32@lo +; GFX11-NEXT: s_mov_b32 exec_lo, s35 +; GFX11-NEXT: v_writelane_b32 v40, s34, 2 +; GFX11-NEXT: s_mov_b32 s35, external_void_func_v8bf16@abs32@hi +; GFX11-NEXT: s_mov_b32 s34, external_void_func_v8bf16@abs32@lo ; GFX11-NEXT: s_add_i32 s32, s32, 16 ; GFX11-NEXT: v_writelane_b32 v40, s30, 0 ; GFX11-NEXT: v_writelane_b32 v40, s31, 1 -; GFX11-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX11-NEXT: s_swappc_b64 s[30:31], s[34:35] ; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_1) ; GFX11-NEXT: v_readlane_b32 s31, v40, 1 ; GFX11-NEXT: v_readlane_b32 s30, v40, 0 @@ -18039,19 +17378,19 @@ define amdgpu_gfx void @test_call_external_void_func_v8bf16_inreg(<8 x i16> inre ; GFX10-SCRATCH-LABEL: test_call_external_void_func_v8bf16_inreg: ; GFX10-SCRATCH: ; %bb.0: ; GFX10-SCRATCH-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GFX10-SCRATCH-NEXT: s_mov_b32 s0, s33 +; GFX10-SCRATCH-NEXT: s_mov_b32 s34, s33 ; GFX10-SCRATCH-NEXT: s_mov_b32 s33, s32 -; GFX10-SCRATCH-NEXT: s_or_saveexec_b32 s1, -1 +; GFX10-SCRATCH-NEXT: s_or_saveexec_b32 s35, -1 ; GFX10-SCRATCH-NEXT: scratch_store_dword off, v40, s33 ; 4-byte Folded Spill ; GFX10-SCRATCH-NEXT: s_waitcnt_depctr 0xffe3 -; GFX10-SCRATCH-NEXT: s_mov_b32 exec_lo, s1 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s0, 2 -; GFX10-SCRATCH-NEXT: s_mov_b32 s1, external_void_func_v8bf16@abs32@hi -; GFX10-SCRATCH-NEXT: s_mov_b32 s0, external_void_func_v8bf16@abs32@lo +; GFX10-SCRATCH-NEXT: s_mov_b32 exec_lo, s35 +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s34, 2 +; GFX10-SCRATCH-NEXT: s_mov_b32 s35, external_void_func_v8bf16@abs32@hi +; GFX10-SCRATCH-NEXT: s_mov_b32 s34, external_void_func_v8bf16@abs32@lo ; GFX10-SCRATCH-NEXT: s_add_i32 s32, s32, 16 ; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s30, 0 ; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s31, 1 -; GFX10-SCRATCH-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX10-SCRATCH-NEXT: s_swappc_b64 s[30:31], s[34:35] ; GFX10-SCRATCH-NEXT: v_readlane_b32 s31, v40, 1 ; GFX10-SCRATCH-NEXT: v_readlane_b32 s30, v40, 0 ; GFX10-SCRATCH-NEXT: v_readlane_b32 s0, v40, 2 @@ -18077,16 +17416,32 @@ define amdgpu_gfx void @test_call_external_void_func_v16bf16_inreg(<16 x i16> in ; GFX9-NEXT: s_or_saveexec_b64 s[36:37], -1 ; GFX9-NEXT: buffer_store_dword v40, off, s[0:3], s33 ; 4-byte Folded Spill ; GFX9-NEXT: s_mov_b64 exec, s[36:37] -; GFX9-NEXT: v_writelane_b32 v40, s34, 2 -; GFX9-NEXT: v_writelane_b32 v40, s30, 0 +; GFX9-NEXT: v_writelane_b32 v40, s34, 6 +; GFX9-NEXT: v_writelane_b32 v40, s4, 0 +; GFX9-NEXT: v_writelane_b32 v40, s5, 1 +; GFX9-NEXT: v_writelane_b32 v40, s6, 2 +; GFX9-NEXT: v_writelane_b32 v40, s7, 3 +; GFX9-NEXT: v_writelane_b32 v40, s30, 4 ; GFX9-NEXT: s_mov_b32 s35, external_void_func_v16bf16@abs32@hi ; GFX9-NEXT: s_mov_b32 s34, external_void_func_v16bf16@abs32@lo +; GFX9-NEXT: s_mov_b32 s3, s7 +; GFX9-NEXT: s_mov_b32 s2, s6 +; GFX9-NEXT: s_mov_b32 s1, s5 +; GFX9-NEXT: s_mov_b32 s0, s4 +; GFX9-NEXT: s_mov_b32 s4, s8 +; GFX9-NEXT: s_mov_b32 s5, s9 +; GFX9-NEXT: s_mov_b32 s6, s10 +; GFX9-NEXT: s_mov_b32 s7, s11 ; GFX9-NEXT: s_addk_i32 s32, 0x400 -; GFX9-NEXT: v_writelane_b32 v40, s31, 1 +; GFX9-NEXT: v_writelane_b32 v40, s31, 5 ; GFX9-NEXT: s_swappc_b64 s[30:31], s[34:35] -; GFX9-NEXT: v_readlane_b32 s31, v40, 1 -; GFX9-NEXT: v_readlane_b32 s30, v40, 0 -; GFX9-NEXT: v_readlane_b32 s34, v40, 2 +; GFX9-NEXT: v_readlane_b32 s31, v40, 5 +; GFX9-NEXT: v_readlane_b32 s30, v40, 4 +; GFX9-NEXT: v_readlane_b32 s7, v40, 3 +; GFX9-NEXT: v_readlane_b32 s6, v40, 2 +; GFX9-NEXT: v_readlane_b32 s5, v40, 1 +; GFX9-NEXT: v_readlane_b32 s4, v40, 0 +; GFX9-NEXT: v_readlane_b32 s34, v40, 6 ; GFX9-NEXT: s_or_saveexec_b64 s[36:37], -1 ; GFX9-NEXT: buffer_load_dword v40, off, s[0:3], s33 ; 4-byte Folded Reload ; GFX9-NEXT: s_mov_b64 exec, s[36:37] @@ -18104,16 +17459,32 @@ define amdgpu_gfx void @test_call_external_void_func_v16bf16_inreg(<16 x i16> in ; GFX10-NEXT: buffer_store_dword v40, off, s[0:3], s33 ; 4-byte Folded Spill ; GFX10-NEXT: s_waitcnt_depctr 0xffe3 ; GFX10-NEXT: s_mov_b32 exec_lo, s35 -; GFX10-NEXT: v_writelane_b32 v40, s34, 2 +; GFX10-NEXT: v_writelane_b32 v40, s34, 6 ; GFX10-NEXT: s_mov_b32 s35, external_void_func_v16bf16@abs32@hi ; GFX10-NEXT: s_mov_b32 s34, external_void_func_v16bf16@abs32@lo +; GFX10-NEXT: s_mov_b32 s3, s7 +; GFX10-NEXT: s_mov_b32 s2, s6 +; GFX10-NEXT: v_writelane_b32 v40, s4, 0 +; GFX10-NEXT: s_mov_b32 s1, s5 +; GFX10-NEXT: s_mov_b32 s0, s4 +; GFX10-NEXT: s_mov_b32 s4, s8 ; GFX10-NEXT: s_addk_i32 s32, 0x200 -; GFX10-NEXT: v_writelane_b32 v40, s30, 0 -; GFX10-NEXT: v_writelane_b32 v40, s31, 1 +; GFX10-NEXT: v_writelane_b32 v40, s5, 1 +; GFX10-NEXT: s_mov_b32 s5, s9 +; GFX10-NEXT: v_writelane_b32 v40, s6, 2 +; GFX10-NEXT: s_mov_b32 s6, s10 +; GFX10-NEXT: v_writelane_b32 v40, s7, 3 +; GFX10-NEXT: s_mov_b32 s7, s11 +; GFX10-NEXT: v_writelane_b32 v40, s30, 4 +; GFX10-NEXT: v_writelane_b32 v40, s31, 5 ; GFX10-NEXT: s_swappc_b64 s[30:31], s[34:35] -; GFX10-NEXT: v_readlane_b32 s31, v40, 1 -; GFX10-NEXT: v_readlane_b32 s30, v40, 0 -; GFX10-NEXT: v_readlane_b32 s34, v40, 2 +; GFX10-NEXT: v_readlane_b32 s31, v40, 5 +; GFX10-NEXT: v_readlane_b32 s30, v40, 4 +; GFX10-NEXT: v_readlane_b32 s7, v40, 3 +; GFX10-NEXT: v_readlane_b32 s6, v40, 2 +; GFX10-NEXT: v_readlane_b32 s5, v40, 1 +; GFX10-NEXT: v_readlane_b32 s4, v40, 0 +; GFX10-NEXT: v_readlane_b32 s34, v40, 6 ; GFX10-NEXT: s_or_saveexec_b32 s35, -1 ; GFX10-NEXT: buffer_load_dword v40, off, s[0:3], s33 ; 4-byte Folded Reload ; GFX10-NEXT: s_waitcnt_depctr 0xffe3 @@ -18126,18 +17497,18 @@ define amdgpu_gfx void @test_call_external_void_func_v16bf16_inreg(<16 x i16> in ; GFX11-LABEL: test_call_external_void_func_v16bf16_inreg: ; GFX11: ; %bb.0: ; GFX11-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GFX11-NEXT: s_mov_b32 s0, s33 +; GFX11-NEXT: s_mov_b32 s34, s33 ; GFX11-NEXT: s_mov_b32 s33, s32 -; GFX11-NEXT: s_or_saveexec_b32 s1, -1 +; GFX11-NEXT: s_or_saveexec_b32 s35, -1 ; GFX11-NEXT: scratch_store_b32 off, v40, s33 ; 4-byte Folded Spill -; GFX11-NEXT: s_mov_b32 exec_lo, s1 -; GFX11-NEXT: v_writelane_b32 v40, s0, 2 -; GFX11-NEXT: s_mov_b32 s1, external_void_func_v16bf16@abs32@hi -; GFX11-NEXT: s_mov_b32 s0, external_void_func_v16bf16@abs32@lo +; GFX11-NEXT: s_mov_b32 exec_lo, s35 +; GFX11-NEXT: v_writelane_b32 v40, s34, 2 +; GFX11-NEXT: s_mov_b32 s35, external_void_func_v16bf16@abs32@hi +; GFX11-NEXT: s_mov_b32 s34, external_void_func_v16bf16@abs32@lo ; GFX11-NEXT: s_add_i32 s32, s32, 16 ; GFX11-NEXT: v_writelane_b32 v40, s30, 0 ; GFX11-NEXT: v_writelane_b32 v40, s31, 1 -; GFX11-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX11-NEXT: s_swappc_b64 s[30:31], s[34:35] ; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_1) ; GFX11-NEXT: v_readlane_b32 s31, v40, 1 ; GFX11-NEXT: v_readlane_b32 s30, v40, 0 @@ -18153,19 +17524,19 @@ define amdgpu_gfx void @test_call_external_void_func_v16bf16_inreg(<16 x i16> in ; GFX10-SCRATCH-LABEL: test_call_external_void_func_v16bf16_inreg: ; GFX10-SCRATCH: ; %bb.0: ; GFX10-SCRATCH-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GFX10-SCRATCH-NEXT: s_mov_b32 s0, s33 +; GFX10-SCRATCH-NEXT: s_mov_b32 s34, s33 ; GFX10-SCRATCH-NEXT: s_mov_b32 s33, s32 -; GFX10-SCRATCH-NEXT: s_or_saveexec_b32 s1, -1 +; GFX10-SCRATCH-NEXT: s_or_saveexec_b32 s35, -1 ; GFX10-SCRATCH-NEXT: scratch_store_dword off, v40, s33 ; 4-byte Folded Spill ; GFX10-SCRATCH-NEXT: s_waitcnt_depctr 0xffe3 -; GFX10-SCRATCH-NEXT: s_mov_b32 exec_lo, s1 -; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s0, 2 -; GFX10-SCRATCH-NEXT: s_mov_b32 s1, external_void_func_v16bf16@abs32@hi -; GFX10-SCRATCH-NEXT: s_mov_b32 s0, external_void_func_v16bf16@abs32@lo +; GFX10-SCRATCH-NEXT: s_mov_b32 exec_lo, s35 +; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s34, 2 +; GFX10-SCRATCH-NEXT: s_mov_b32 s35, external_void_func_v16bf16@abs32@hi +; GFX10-SCRATCH-NEXT: s_mov_b32 s34, external_void_func_v16bf16@abs32@lo ; GFX10-SCRATCH-NEXT: s_add_i32 s32, s32, 16 ; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s30, 0 ; GFX10-SCRATCH-NEXT: v_writelane_b32 v40, s31, 1 -; GFX10-SCRATCH-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX10-SCRATCH-NEXT: s_swappc_b64 s[30:31], s[34:35] ; GFX10-SCRATCH-NEXT: v_readlane_b32 s31, v40, 1 ; GFX10-SCRATCH-NEXT: v_readlane_b32 s30, v40, 0 ; GFX10-SCRATCH-NEXT: v_readlane_b32 s0, v40, 2 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_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/indirect-call.ll b/llvm/test/CodeGen/AMDGPU/indirect-call.ll index 7799b9509ceb03d549774bb42759c6a768d0e470..25c684004446ff3bb9188f95674536a3471889c4 100644 --- a/llvm/test/CodeGen/AMDGPU/indirect-call.ll +++ b/llvm/test/CodeGen/AMDGPU/indirect-call.ll @@ -847,11 +847,11 @@ define void @test_indirect_call_vgpr_ptr_inreg_arg(ptr %fptr) { ; GCN-LABEL: test_indirect_call_vgpr_ptr_inreg_arg: ; GCN: ; %bb.0: ; GCN-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN-NEXT: s_mov_b32 s5, s33 +; GCN-NEXT: s_mov_b32 s10, s33 ; GCN-NEXT: s_mov_b32 s33, s32 -; GCN-NEXT: s_or_saveexec_b64 s[6:7], -1 +; GCN-NEXT: s_or_saveexec_b64 s[4:5], -1 ; GCN-NEXT: buffer_store_dword v40, off, s[0:3], s33 ; 4-byte Folded Spill -; GCN-NEXT: s_mov_b64 exec, s[6:7] +; GCN-NEXT: s_mov_b64 exec, s[4:5] ; GCN-NEXT: s_addk_i32 s32, 0x400 ; GCN-NEXT: v_writelane_b32 v40, s30, 0 ; GCN-NEXT: v_writelane_b32 v40, s31, 1 @@ -885,19 +885,19 @@ define void @test_indirect_call_vgpr_ptr_inreg_arg(ptr %fptr) { ; GCN-NEXT: v_writelane_b32 v40, s61, 29 ; GCN-NEXT: v_writelane_b32 v40, s62, 30 ; GCN-NEXT: v_writelane_b32 v40, s63, 31 -; GCN-NEXT: s_mov_b64 s[6:7], exec -; GCN-NEXT: s_movk_i32 s4, 0x7b +; GCN-NEXT: s_mov_b64 s[4:5], exec ; GCN-NEXT: .LBB6_1: ; =>This Inner Loop Header: Depth=1 -; GCN-NEXT: v_readfirstlane_b32 s8, v0 -; GCN-NEXT: v_readfirstlane_b32 s9, v1 -; GCN-NEXT: v_cmp_eq_u64_e32 vcc, s[8:9], v[0:1] -; GCN-NEXT: s_and_saveexec_b64 s[10:11], vcc -; GCN-NEXT: s_swappc_b64 s[30:31], s[8:9] +; GCN-NEXT: v_readfirstlane_b32 s6, v0 +; GCN-NEXT: v_readfirstlane_b32 s7, v1 +; GCN-NEXT: v_cmp_eq_u64_e32 vcc, s[6:7], v[0:1] +; GCN-NEXT: s_and_saveexec_b64 s[8:9], vcc +; GCN-NEXT: s_movk_i32 s0, 0x7b +; GCN-NEXT: s_swappc_b64 s[30:31], s[6:7] ; GCN-NEXT: ; implicit-def: $vgpr0_vgpr1 -; GCN-NEXT: s_xor_b64 exec, exec, s[10:11] +; GCN-NEXT: s_xor_b64 exec, exec, s[8:9] ; GCN-NEXT: s_cbranch_execnz .LBB6_1 ; GCN-NEXT: ; %bb.2: -; GCN-NEXT: s_mov_b64 exec, s[6:7] +; GCN-NEXT: s_mov_b64 exec, s[4:5] ; GCN-NEXT: v_readlane_b32 s63, v40, 31 ; GCN-NEXT: v_readlane_b32 s62, v40, 30 ; GCN-NEXT: v_readlane_b32 s61, v40, 29 @@ -930,22 +930,22 @@ define void @test_indirect_call_vgpr_ptr_inreg_arg(ptr %fptr) { ; GCN-NEXT: v_readlane_b32 s34, v40, 2 ; GCN-NEXT: v_readlane_b32 s31, v40, 1 ; GCN-NEXT: v_readlane_b32 s30, v40, 0 -; GCN-NEXT: s_or_saveexec_b64 s[6:7], -1 +; GCN-NEXT: s_or_saveexec_b64 s[4:5], -1 ; GCN-NEXT: buffer_load_dword v40, off, s[0:3], s33 ; 4-byte Folded Reload -; GCN-NEXT: s_mov_b64 exec, s[6:7] +; GCN-NEXT: s_mov_b64 exec, s[4:5] ; GCN-NEXT: s_addk_i32 s32, 0xfc00 -; GCN-NEXT: s_mov_b32 s33, s5 +; GCN-NEXT: s_mov_b32 s33, s10 ; GCN-NEXT: s_waitcnt vmcnt(0) ; GCN-NEXT: s_setpc_b64 s[30:31] ; ; GISEL-LABEL: test_indirect_call_vgpr_ptr_inreg_arg: ; GISEL: ; %bb.0: ; GISEL-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GISEL-NEXT: s_mov_b32 s5, s33 +; GISEL-NEXT: s_mov_b32 s10, s33 ; GISEL-NEXT: s_mov_b32 s33, s32 -; GISEL-NEXT: s_or_saveexec_b64 s[6:7], -1 +; GISEL-NEXT: s_or_saveexec_b64 s[4:5], -1 ; GISEL-NEXT: buffer_store_dword v40, off, s[0:3], s33 ; 4-byte Folded Spill -; GISEL-NEXT: s_mov_b64 exec, s[6:7] +; GISEL-NEXT: s_mov_b64 exec, s[4:5] ; GISEL-NEXT: s_addk_i32 s32, 0x400 ; GISEL-NEXT: v_writelane_b32 v40, s30, 0 ; GISEL-NEXT: v_writelane_b32 v40, s31, 1 @@ -979,19 +979,19 @@ define void @test_indirect_call_vgpr_ptr_inreg_arg(ptr %fptr) { ; GISEL-NEXT: v_writelane_b32 v40, s61, 29 ; GISEL-NEXT: v_writelane_b32 v40, s62, 30 ; GISEL-NEXT: v_writelane_b32 v40, s63, 31 -; GISEL-NEXT: s_mov_b64 s[6:7], exec -; GISEL-NEXT: s_movk_i32 s4, 0x7b +; GISEL-NEXT: s_mov_b64 s[4:5], exec ; GISEL-NEXT: .LBB6_1: ; =>This Inner Loop Header: Depth=1 -; GISEL-NEXT: v_readfirstlane_b32 s8, v0 -; GISEL-NEXT: v_readfirstlane_b32 s9, v1 -; GISEL-NEXT: v_cmp_eq_u64_e32 vcc, s[8:9], v[0:1] -; GISEL-NEXT: s_and_saveexec_b64 s[10:11], vcc -; GISEL-NEXT: s_swappc_b64 s[30:31], s[8:9] +; GISEL-NEXT: v_readfirstlane_b32 s6, v0 +; GISEL-NEXT: v_readfirstlane_b32 s7, v1 +; GISEL-NEXT: v_cmp_eq_u64_e32 vcc, s[6:7], v[0:1] +; GISEL-NEXT: s_and_saveexec_b64 s[8:9], vcc +; GISEL-NEXT: s_movk_i32 s0, 0x7b +; GISEL-NEXT: s_swappc_b64 s[30:31], s[6:7] ; GISEL-NEXT: ; implicit-def: $vgpr0 -; GISEL-NEXT: s_xor_b64 exec, exec, s[10:11] +; GISEL-NEXT: s_xor_b64 exec, exec, s[8:9] ; GISEL-NEXT: s_cbranch_execnz .LBB6_1 ; GISEL-NEXT: ; %bb.2: -; GISEL-NEXT: s_mov_b64 exec, s[6:7] +; GISEL-NEXT: s_mov_b64 exec, s[4:5] ; GISEL-NEXT: v_readlane_b32 s63, v40, 31 ; GISEL-NEXT: v_readlane_b32 s62, v40, 30 ; GISEL-NEXT: v_readlane_b32 s61, v40, 29 @@ -1024,11 +1024,11 @@ define void @test_indirect_call_vgpr_ptr_inreg_arg(ptr %fptr) { ; GISEL-NEXT: v_readlane_b32 s34, v40, 2 ; GISEL-NEXT: v_readlane_b32 s31, v40, 1 ; GISEL-NEXT: v_readlane_b32 s30, v40, 0 -; GISEL-NEXT: s_or_saveexec_b64 s[6:7], -1 +; GISEL-NEXT: s_or_saveexec_b64 s[4:5], -1 ; GISEL-NEXT: buffer_load_dword v40, off, s[0:3], s33 ; 4-byte Folded Reload -; GISEL-NEXT: s_mov_b64 exec, s[6:7] +; GISEL-NEXT: s_mov_b64 exec, s[4:5] ; GISEL-NEXT: s_addk_i32 s32, 0xfc00 -; GISEL-NEXT: s_mov_b32 s33, s5 +; GISEL-NEXT: s_mov_b32 s33, s10 ; GISEL-NEXT: s_waitcnt vmcnt(0) ; GISEL-NEXT: s_setpc_b64 s[30:31] call amdgpu_gfx void %fptr(i32 inreg 123) 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/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/lds-run-twice-absolute-md.ll b/llvm/test/CodeGen/AMDGPU/lds-run-twice-absolute-md.ll index 52b44eea35c827ec7e0b78c646fb293006843ea2..51e10d90379704f82bfb865c47b6b5fb1e3c6420 100644 --- a/llvm/test/CodeGen/AMDGPU/lds-run-twice-absolute-md.ll +++ b/llvm/test/CodeGen/AMDGPU/lds-run-twice-absolute-md.ll @@ -1,3 +1,5 @@ +; XFAIL: target={{.*}}-aix{{.*}} + ; RUN: opt -S -mtriple=amdgcn-- -amdgpu-lower-module-lds %s -o %t.ll ; RUN: opt -S -mtriple=amdgcn-- -amdgpu-lower-module-lds %t.ll -o %t.second.ll ; RUN: diff -ub %t.ll %t.second.ll -I ".*ModuleID.*" diff --git a/llvm/test/CodeGen/AMDGPU/lds-run-twice.ll b/llvm/test/CodeGen/AMDGPU/lds-run-twice.ll index b830ccb944a2820a72ac7ec776a69189a64c6984..e121f0da327d0ae54b0465500e5ea91187adb93b 100644 --- a/llvm/test/CodeGen/AMDGPU/lds-run-twice.ll +++ b/llvm/test/CodeGen/AMDGPU/lds-run-twice.ll @@ -1,3 +1,5 @@ +; XFAIL: target={{.*}}-aix{{.*}} + ; RUN: opt -S -mtriple=amdgcn-- -amdgpu-lower-module-lds %s -o %t.ll ; RUN: opt -S -mtriple=amdgcn-- -amdgpu-lower-module-lds %t.ll -o %t.second.ll ; RUN: diff -ub %t.ll %t.second.ll -I ".*ModuleID.*" 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.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.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/mai-hazards-gfx940.mir b/llvm/test/CodeGen/AMDGPU/mai-hazards-gfx940.mir index 4d307a444b19c682e69d93dc2734c8f8be1426c0..a98b02d792d9849477edb0969d34ccad94801551 100644 --- a/llvm/test/CodeGen/AMDGPU/mai-hazards-gfx940.mir +++ b/llvm/test/CodeGen/AMDGPU/mai-hazards-gfx940.mir @@ -2028,3 +2028,457 @@ body: | $agpr0_agpr1 = V_MFMA_F64_4X4X4F64_e64 $agpr0_agpr1, $agpr0_agpr1, $agpr0_agpr1, 0, 0, 0, implicit $mode, implicit $exec BUFFER_STORE_DWORDX2_OFFEN_exact $vgpr2_vgpr3, $vgpr0, $sgpr0_sgpr1_sgpr2_sgpr3, 0, 0, 0, 0, implicit $exec ... + +... +# 2 pass source +# GCN-LABEL: name: xdl_mfma_2pass_write_vgpr_xdl_mfma_read_overlap_srcc +# GCN: V_MFMA +# GCN-NEXT: S_NOP 2 +# GCN-NEXT: V_MFMA +name: xdl_mfma_2pass_write_vgpr_xdl_mfma_read_overlap_srcc +body: | + bb.0: + + $vgpr0_vgpr1_vgpr2_vgpr3 = V_MFMA_F32_4X4X4F16_vgprcd_e64 $vgpr4_vgpr5, $vgpr6_vgpr7, $vgpr0_vgpr1_vgpr2_vgpr3, 1, 2, 3, implicit $mode, implicit $exec + $vgpr0_vgpr1_vgpr2_vgpr3 = V_MFMA_F32_4X4X4F16_vgprcd_e64 $vgpr4_vgpr5, $vgpr6_vgpr7, $vgpr2_vgpr3_vgpr4_vgpr5, 1, 2, 3, implicit $mode, implicit $exec + +... + +... +# 2 pass source +# GCN-LABEL: name: xdl_mfma_2pass_write_vgpr_xdl_mfma_read_overlap_srca +# GCN: V_MFMA +# GCN-NEXT: S_NOP 4 +# GCN-NEXT: V_MFMA +name: xdl_mfma_2pass_write_vgpr_xdl_mfma_read_overlap_srca +body: | + bb.0: + + $vgpr0_vgpr1_vgpr2_vgpr3 = V_MFMA_F32_4X4X4F16_vgprcd_e64 $vgpr4_vgpr5, $vgpr6_vgpr7, $vgpr0_vgpr1_vgpr2_vgpr3, 1, 2, 3, implicit $mode, implicit $exec + $vgpr0_vgpr1_vgpr2_vgpr3 = V_MFMA_F32_4X4X4F16_vgprcd_e64 $vgpr0_vgpr1, $vgpr6_vgpr7, $vgpr8_vgpr9_vgpr10_vgpr11, 1, 2, 3, implicit $mode, implicit $exec + +... + +... +# 2 pass source +# GCN-LABEL: name: xdl_mfma_2pass_write_vgpr_xdl_mfma_read_overlap_srcb +# GCN: V_MFMA +# GCN-NEXT: S_NOP 4 +# GCN-NEXT: V_MFMA +name: xdl_mfma_2pass_write_vgpr_xdl_mfma_read_overlap_srcb +body: | + bb.0: + + $vgpr0_vgpr1_vgpr2_vgpr3 = V_MFMA_F32_4X4X4F16_vgprcd_e64 $vgpr4_vgpr5, $vgpr6_vgpr7, $vgpr0_vgpr1_vgpr2_vgpr3, 1, 2, 3, implicit $mode, implicit $exec + $vgpr0_vgpr1_vgpr2_vgpr3 = V_MFMA_F32_4X4X4F16_vgprcd_e64 $vgpr6_vgpr7, $vgpr2_vgpr3, $vgpr8_vgpr9_vgpr10_vgpr11, 1, 2, 3, implicit $mode, implicit $exec + +... + +... +# 4 pass source +# GCN-LABEL: name: xdl_mfma_4pass_write_vgpr_xdl_mfma_read_overlap_srcc +# GCN: V_MFMA +# GCN-NEXT: S_NOP 4 +# GCN-NEXT: V_MFMA +name: xdl_mfma_4pass_write_vgpr_xdl_mfma_read_overlap_srcc +body: | + bb.0: + $vgpr0_vgpr1_vgpr2_vgpr3 = V_MFMA_F32_16X16X16F16_vgprcd_e64 $vgpr4_vgpr5, $vgpr6_vgpr7, $vgpr0_vgpr1_vgpr2_vgpr3, 1, 2, 3, implicit $mode, implicit $exec + $vgpr0_vgpr1_vgpr2_vgpr3 = V_MFMA_F32_16X16X16F16_vgprcd_e64 $vgpr8_vgpr9, $vgpr10_vgpr11, $vgpr2_vgpr3_vgpr4_vgpr5, 1, 2, 3, implicit $mode, implicit $exec + +... + +... +# 4 pass source +# GCN-LABEL: name: xdl_mfma_4pass_write_vgpr_xdl_mfma_read_overlap_srca +# GCN: V_MFMA +# GCN-NEXT: S_NOP 6 +# GCN-NEXT: V_MFMA +name: xdl_mfma_4pass_write_vgpr_xdl_mfma_read_overlap_srca +body: | + bb.0: + $vgpr0_vgpr1_vgpr2_vgpr3 = V_MFMA_F32_16X16X16F16_vgprcd_e64 $vgpr4_vgpr5, $vgpr6_vgpr7, $vgpr0_vgpr1_vgpr2_vgpr3, 1, 2, 3, implicit $mode, implicit $exec + $vgpr0_vgpr1_vgpr2_vgpr3 = V_MFMA_F32_16X16X16F16_vgprcd_e64 $vgpr2_vgpr3, $vgpr10_vgpr11, $vgpr6_vgpr7_vgpr8_vgpr9, 1, 2, 3, implicit $mode, implicit $exec + +... + +... +# 4 pass source +# GCN-LABEL: name: xdl_mfma_4pass_write_vgpr_xdl_mfma_read_overlap_srcb +# GCN: V_MFMA +# GCN-NEXT: S_NOP 6 +# GCN-NEXT: V_MFMA +name: xdl_mfma_4pass_write_vgpr_xdl_mfma_read_overlap_srcb +body: | + bb.0: + $vgpr0_vgpr1_vgpr2_vgpr3 = V_MFMA_F32_16X16X16F16_vgprcd_e64 $vgpr4_vgpr5, $vgpr6_vgpr7, $vgpr0_vgpr1_vgpr2_vgpr3, 1, 2, 3, implicit $mode, implicit $exec + $vgpr0_vgpr1_vgpr2_vgpr3 = V_MFMA_F32_16X16X16F16_vgprcd_e64 $vgpr10_vgpr11, $vgpr2_vgpr3, $vgpr6_vgpr7_vgpr8_vgpr9, 1, 2, 3, implicit $mode, implicit $exec + +... + +... +# 2 pass source +# GCN-LABEL: name: xdl_mfma_2pass_write_vgpr_sgemm_mfma_read_overlap_srcc +# GCN: V_MFMA +# GCN-NEXT: S_NOP 2 +# GCN-NEXT: V_MFMA +name: xdl_mfma_2pass_write_vgpr_sgemm_mfma_read_overlap_srcc +body: | + bb.0: + + $vgpr0_vgpr1_vgpr2_vgpr3 = V_MFMA_F32_4X4X4F16_vgprcd_e64 $vgpr4_vgpr5, $vgpr6_vgpr7, $vgpr0_vgpr1_vgpr2_vgpr3, 1, 2, 3, implicit $mode, implicit $exec + $vgpr0_vgpr1_vgpr2_vgpr3 = V_MFMA_F32_4X4X1F32_vgprcd_e64 $vgpr6, $vgpr8, $vgpr2_vgpr3_vgpr4_vgpr5, 0, 0, 0, implicit $mode, implicit $exec + +... + +... +# 2 pass source +# GCN-LABEL: name: xdl_mfma_2pass_write_vgpr_sgemm_mfma_read_overlap_srca +# GCN: V_MFMA +# GCN-NEXT: S_NOP 4 +# GCN-NEXT: V_MFMA +name: xdl_mfma_2pass_write_vgpr_sgemm_mfma_read_overlap_srca +body: | + bb.0: + + $vgpr0_vgpr1_vgpr2_vgpr3 = V_MFMA_F32_4X4X4F16_vgprcd_e64 $vgpr4_vgpr5, $vgpr6_vgpr7, $vgpr0_vgpr1_vgpr2_vgpr3, 1, 2, 3, implicit $mode, implicit $exec + $vgpr0_vgpr1_vgpr2_vgpr3 = V_MFMA_F32_4X4X1F32_vgprcd_e64 $vgpr1, $vgpr8, $vgpr6_vgpr7_vgpr8_vgpr9, 0, 0, 0, implicit $mode, implicit $exec + +... + +... +# 2 pass source +# GCN-LABEL: name: xdl_mfma_2pass_write_vgpr_sgemm_mfma_read_overlap_srcb +# GCN: V_MFMA +# GCN-NEXT: S_NOP 4 +# GCN-NEXT: V_MFMA +name: xdl_mfma_2pass_write_vgpr_sgemm_mfma_read_overlap_srcb +body: | + bb.0: + + $vgpr0_vgpr1_vgpr2_vgpr3 = V_MFMA_F32_4X4X4F16_vgprcd_e64 $vgpr4_vgpr5, $vgpr6_vgpr7, $vgpr0_vgpr1_vgpr2_vgpr3, 1, 2, 3, implicit $mode, implicit $exec + $vgpr0_vgpr1_vgpr2_vgpr3 = V_MFMA_F32_4X4X1F32_vgprcd_e64 $vgpr8, $vgpr1, $vgpr6_vgpr7_vgpr8_vgpr9, 0, 0, 0, implicit $mode, implicit $exec + +... + +... +# 4 pass source +# GCN-LABEL: name: xdl_mfma_4pass_write_vgpr_sgemm_mfma_read_overlap_srcc +# GCN: V_MFMA +# GCN-NEXT: S_NOP 4 +# GCN-NEXT: V_MFMA +name: xdl_mfma_4pass_write_vgpr_sgemm_mfma_read_overlap_srcc +body: | + bb.0: + $vgpr0_vgpr1_vgpr2_vgpr3 = V_MFMA_F32_16X16X16F16_vgprcd_e64 $vgpr4_vgpr5, $vgpr6_vgpr7, $vgpr0_vgpr1_vgpr2_vgpr3, 1, 2, 3, implicit $mode, implicit $exec + $vgpr0_vgpr1_vgpr2_vgpr3 = V_MFMA_F32_4X4X1F32_vgprcd_e64 $vgpr8, $vgpr9, $vgpr2_vgpr3_vgpr4_vgpr5, 0, 0, 0, implicit $mode, implicit $exec + +... + +... +# 4 pass source +# GCN-LABEL: name: xdl_mfma_4pass_write_vgpr_sgemm_mfma_read_overlap_srca +# GCN: V_MFMA +# GCN-NEXT: S_NOP 6 +# GCN-NEXT: V_MFMA +name: xdl_mfma_4pass_write_vgpr_sgemm_mfma_read_overlap_srca +body: | + bb.0: + $vgpr0_vgpr1_vgpr2_vgpr3 = V_MFMA_F32_16X16X16F16_vgprcd_e64 $vgpr4_vgpr5, $vgpr6_vgpr7, $vgpr0_vgpr1_vgpr2_vgpr3, 1, 2, 3, implicit $mode, implicit $exec + $vgpr0_vgpr1_vgpr2_vgpr3 = V_MFMA_F32_4X4X1F32_vgprcd_e64 $vgpr1, $vgpr8, $vgpr6_vgpr7_vgpr8_vgpr9, 0, 0, 0, implicit $mode, implicit $exec + +... + +... +# 4 pass source +# GCN-LABEL: name: xdl_mfma_4pass_write_vgpr_sgemm_mfma_read_overlap_srcb +# GCN: V_MFMA +# GCN-NEXT: S_NOP 6 +# GCN-NEXT: V_MFMA +name: xdl_mfma_4pass_write_vgpr_sgemm_mfma_read_overlap_srcb +body: | + bb.0: + $vgpr0_vgpr1_vgpr2_vgpr3 = V_MFMA_F32_16X16X16F16_vgprcd_e64 $vgpr4_vgpr5, $vgpr6_vgpr7, $vgpr0_vgpr1_vgpr2_vgpr3, 1, 2, 3, implicit $mode, implicit $exec + $vgpr0_vgpr1_vgpr2_vgpr3 = V_MFMA_F32_4X4X1F32_vgprcd_e64 $vgpr8, $vgpr1, $vgpr6_vgpr7_vgpr8_vgpr9, 0, 0, 0, implicit $mode, implicit $exec + +... + +... +# 8 pass source +# GCN-LABEL: name: xdl_mfma_8pass_write_vgpr_nonxdl_sgemm_mfma_read_overlap_srcc +# GCN: V_MFMA +# GCN-NEXT: S_NOP 7 +# GCN-NEXT: S_NOP 0 +# GCN-NEXT: V_MFMA +name: xdl_mfma_8pass_write_vgpr_nonxdl_sgemm_mfma_read_overlap_srcc +body: | + bb.0: + renamable $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15 = V_MFMA_F32_32X32X8F16_vgprcd_e64 killed $vgpr0_vgpr1, killed $vgpr2_vgpr3, 1065353216, 0, 0, 0, implicit $mode, implicit $exec + + $vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17 = V_MFMA_F32_16X16X1F32_vgprcd_e64 $vgpr18, $vgpr19, $vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17, 0, 0, 0, implicit $mode, implicit $exec +... + +... +# 8 pass source +# GCN-LABEL: name: xdl_mfma_8pass_write_vgpr_nonxdl_sgemm_mfma_read_overlap_srca +# GCN: V_MFMA +# GCN-NEXT: S_NOP 7 +# GCN-NEXT: S_NOP 2 +# GCN-NEXT: V_MFMA +name: xdl_mfma_8pass_write_vgpr_nonxdl_sgemm_mfma_read_overlap_srca +body: | + bb.0: + renamable $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15 = V_MFMA_F32_32X32X8F16_vgprcd_e64 killed $vgpr0_vgpr1, killed $vgpr2_vgpr3, 1065353216, 0, 0, 0, implicit $mode, implicit $exec + + $vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17 = V_MFMA_F32_16X16X1F32_vgprcd_e64 $vgpr0, $vgpr33, $vgpr18_vgpr19_vgpr20_vgpr21_vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31_vgpr32_vgpr33, 0, 0, 0, implicit $mode, implicit $exec +... + +... +# 8 pass source +# GCN-LABEL: name: xdl_mfma_8pass_write_vgpr_nonxdl_sgemm_mfma_read_overlap_srcb +# GCN: V_MFMA +# GCN-NEXT: S_NOP 7 +# GCN-NEXT: S_NOP 2 +# GCN-NEXT: V_MFMA +name: xdl_mfma_8pass_write_vgpr_nonxdl_sgemm_mfma_read_overlap_srcb +body: | + bb.0: + renamable $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15 = V_MFMA_F32_32X32X8F16_vgprcd_e64 killed $vgpr0_vgpr1, killed $vgpr2_vgpr3, 1065353216, 0, 0, 0, implicit $mode, implicit $exec + + $vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17 = V_MFMA_F32_16X16X1F32_vgprcd_e64 $vgpr33, $vgpr1, $vgpr18_vgpr19_vgpr20_vgpr21_vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31_vgpr32_vgpr33, 0, 0, 0, implicit $mode, implicit $exec +... + +... +# 16 pass source +# GCN-LABEL: name: xdl_16pass_write_vgpr_nonxdl_sgemm_mfma_read_overlap_srcc +# GCN: V_MFMA +# GCN-NEXT: S_NOP 7 +# GCN-NEXT: S_NOP 7 +# GCN-NEXT: S_NOP 0 +# GCN-NEXT: V_MFMA +name: xdl_16pass_write_vgpr_nonxdl_sgemm_mfma_read_overlap_srcc +body: | + bb.0: + $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21_vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31 = V_MFMA_F32_32X32X4F16_vgprcd_e64 $vgpr126_vgpr127, $vgpr128_vgpr129, $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21_vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31, 0, 0, 0, implicit $mode, implicit $exec + + $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15 = V_MFMA_F32_32X32X2F32_vgprcd_e64 killed $vgpr32, killed $vgpr33, $vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21_vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31, 1, 2, 3, implicit $mode, implicit $exec + +... + +... +# 16 pass source +# GCN-LABEL: name: xdl_16pass_write_vgpr_nonxdl_sgemm_mfma_read_overlap_srca +# GCN: V_MFMA +# GCN-NEXT: S_NOP 7 +# GCN-NEXT: S_NOP 7 +# GCN-NEXT: S_NOP 2 +# GCN-NEXT: V_MFMA +name: xdl_16pass_write_vgpr_nonxdl_sgemm_mfma_read_overlap_srca +body: | + bb.0: + $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21_vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31 = V_MFMA_F32_32X32X4F16_vgprcd_e64 $vgpr126_vgpr127, $vgpr128_vgpr129, $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21_vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31, 0, 0, 0, implicit $mode, implicit $exec + $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15 = V_MFMA_F32_32X32X2F32_vgprcd_e64 killed $vgpr0, killed $vgpr33, $vgpr32_vgpr33_vgpr34_vgpr35_vgpr36_vgpr37_vgpr38_vgpr39_vgpr40_vgpr41_vgpr42_vgpr43_vgpr44_vgpr45_vgpr46_vgpr47, 1, 2, 3, implicit $mode, implicit $exec + +... + +... +# 16 pass source +# GCN-LABEL: name: xdl_16pass_write_vgpr_nonxdl_sgemm_mfma_read_overlap_srcb +# GCN: V_MFMA +# GCN-NEXT: S_NOP 7 +# GCN-NEXT: S_NOP 7 +# GCN-NEXT: S_NOP 2 +# GCN-NEXT: V_MFMA +name: xdl_16pass_write_vgpr_nonxdl_sgemm_mfma_read_overlap_srcb +body: | + bb.0: + $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21_vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31 = V_MFMA_F32_32X32X4F16_vgprcd_e64 $vgpr126_vgpr127, $vgpr128_vgpr129, $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21_vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31, 0, 0, 0, implicit $mode, implicit $exec + $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15 = V_MFMA_F32_32X32X2F32_vgprcd_e64 killed $vgpr33, killed $vgpr0, $vgpr32_vgpr33_vgpr34_vgpr35_vgpr36_vgpr37_vgpr38_vgpr39_vgpr40_vgpr41_vgpr42_vgpr43_vgpr44_vgpr45_vgpr46_vgpr47, 1, 2, 3, implicit $mode, implicit $exec + +... + +... +# 8 pass source +# GCN-LABEL: name: nonxdl_8pass_write_vgpr_nonxdl_sgemm_mfma_read_overlap_srcc +# GCN: V_MFMA +# GCN-NEXT: S_NOP 7 +# GCN-NEXT: V_MFMA +name: nonxdl_8pass_write_vgpr_nonxdl_sgemm_mfma_read_overlap_srcc +body: | + bb.0: + $vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17 = V_MFMA_F32_16X16X1F32_vgprcd_e64 $vgpr18, $vgpr19, $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15, 0, 0, 0, implicit $mode, implicit $exec + $vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17 = V_MFMA_F32_16X16X1F32_vgprcd_e64 $vgpr18, $vgpr19, $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15, 0, 0, 0, implicit $mode, implicit $exec +... + +... +# 8 pass source +# GCN-LABEL: name: nonxdl_8pass_write_vgpr_nonxdl_sgemm_mfma_read_overlap_srca +# GCN: V_MFMA +# GCN-NEXT: S_NOP 7 +# GCN-NEXT: S_NOP 1 +# GCN-NEXT: V_MFMA +name: nonxdl_8pass_write_vgpr_nonxdl_sgemm_mfma_read_overlap_srca +body: | + bb.0: + $vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17 = V_MFMA_F32_16X16X1F32_vgprcd_e64 $vgpr18, $vgpr19, $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15, 0, 0, 0, implicit $mode, implicit $exec + $vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17 = V_MFMA_F32_16X16X1F32_vgprcd_e64 $vgpr3, $vgpr19, $vgpr18_vgpr19_vgpr20_vgpr21_vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31_vgpr32_vgpr33, 0, 0, 0, implicit $mode, implicit $exec +... + +... +# 8 pass source +# GCN-LABEL: name: nonxdl_8pass_write_vgpr_nonxdl_sgemm_mfma_read_overlap_srcb +# GCN: V_MFMA +# GCN-NEXT: S_NOP 7 +# GCN-NEXT: S_NOP 1 +# GCN-NEXT: V_MFMA +name: nonxdl_8pass_write_vgpr_nonxdl_sgemm_mfma_read_overlap_srcb +body: | + bb.0: + $vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17 = V_MFMA_F32_16X16X1F32_vgprcd_e64 $vgpr18, $vgpr19, $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15, 0, 0, 0, implicit $mode, implicit $exec + $vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17 = V_MFMA_F32_16X16X1F32_vgprcd_e64 $vgpr19, $vgpr3, $vgpr18_vgpr19_vgpr20_vgpr21_vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31_vgpr32_vgpr33, 0, 0, 0, implicit $mode, implicit $exec +... +... +# 8 pass source +# GCN-LABEL: name: xdl_mfma_8pass_write_vgpr_xdl_mfma_read_overlap_srcc +# GCN: V_MFMA +# GCN-NEXT: S_NOP 7 +# GCN-NEXT: S_NOP 0 +# GCN-NEXT: V_MFMA +name: xdl_mfma_8pass_write_vgpr_xdl_mfma_read_overlap_srcc +body: | + bb.0: + $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15 = V_MFMA_F32_32X32X8F16_vgprcd_e64 killed $vgpr0_vgpr1, killed $vgpr2_vgpr3, 1065353216, 0, 0, 0, implicit $mode, implicit $exec + $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15 = V_MFMA_F32_32X32X8F16_vgprcd_e64 killed $vgpr18_vgpr19, killed $vgpr20_vgpr21, $vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17, 0, 0, 0, implicit $mode, implicit $exec +... + +... +# 8 pass source +# GCN-LABEL: name: xdl_mfma_8pass_write_vgpr_xdl_mfma_read_overlap_srca +# GCN: V_MFMA +# GCN-NEXT: S_NOP 7 +# GCN-NEXT: S_NOP 2 +# GCN-NEXT: V_MFMA +name: xdl_mfma_8pass_write_vgpr_xdl_mfma_read_overlap_srca +body: | + bb.0: + renamable $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15 = V_MFMA_F32_32X32X8F16_vgprcd_e64 killed $vgpr0_vgpr1, killed $vgpr2_vgpr3, 1065353216, 0, 0, 0, implicit $mode, implicit $exec + $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15 = V_MFMA_F32_32X32X8F16_vgprcd_e64 killed $vgpr2_vgpr3, killed $vgpr36_vgpr37, $vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21_vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31, 0, 0, 0, implicit $mode, implicit $exec +... + +... +# 8 pass source +# GCN-LABEL: name: xdl_mfma_8pass_write_vgpr_xdl_mfma_read_overlap_srcb +# GCN: V_MFMA +# GCN-NEXT: S_NOP 7 +# GCN-NEXT: S_NOP 2 +# GCN-NEXT: V_MFMA +name: xdl_mfma_8pass_write_vgpr_xdl_mfma_read_overlap_srcb +body: | + bb.0: + renamable $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15 = V_MFMA_F32_32X32X8F16_vgprcd_e64 killed $vgpr0_vgpr1, killed $vgpr2_vgpr3, 1065353216, 0, 0, 0, implicit $mode, implicit $exec + $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15 = V_MFMA_F32_32X32X8F16_vgprcd_e64 killed $vgpr36_vgpr37, killed $vgpr2_vgpr3, $vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21_vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31, 0, 0, 0, implicit $mode, implicit $exec +... + +... +# 16 pass source +# GCN-LABEL: name: xdl_16pass_write_vgpr_xdl_mfma_read_overlap_srcc +# GCN: V_MFMA +# GCN-NEXT: S_NOP 7 +# GCN-NEXT: S_NOP 7 +# GCN-NEXT: S_NOP 0 +# GCN-NEXT: V_MFMA +name: xdl_16pass_write_vgpr_xdl_mfma_read_overlap_srcc +body: | + bb.0: + $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21_vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31 = V_MFMA_F32_32X32X4F16_vgprcd_e64 $vgpr126_vgpr127, $vgpr128_vgpr129, $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21_vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31, 0, 0, 0, implicit $mode, implicit $exec + $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21_vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31 = V_MFMA_F32_32X32X4F16_vgprcd_e64 $vgpr126_vgpr127, $vgpr128_vgpr129, $vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21_vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31_vgpr32_vgpr33, 0, 0, 0, implicit $mode, implicit $exec + +... + +... +# 16 pass source +# GCN-LABEL: name: xdl_16pass_write_vgpr_xdl_mfma_read_overlap_srca +# GCN: V_MFMA +# GCN-NEXT: S_NOP 7 +# GCN-NEXT: S_NOP 7 +# GCN-NEXT: S_NOP 2 +# GCN-NEXT: V_MFMA +name: xdl_16pass_write_vgpr_xdl_mfma_read_overlap_srca +body: | + bb.0: + $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21_vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31 = V_MFMA_F32_32X32X4F16_vgprcd_e64 $vgpr126_vgpr127, $vgpr128_vgpr129, $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21_vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31, 0, 0, 0, implicit $mode, implicit $exec + $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21_vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31 = V_MFMA_F32_32X32X4F16_vgprcd_e64 $vgpr2_vgpr3, $vgpr128_vgpr129, $vgpr32_vgpr33_vgpr34_vgpr35_vgpr36_vgpr37_vgpr38_vgpr39_vgpr40_vgpr41_vgpr42_vgpr43_vgpr44_vgpr45_vgpr46_vgpr47_vgpr48_vgpr49_vgpr50_vgpr51_vgpr52_vgpr53_vgpr54_vgpr55_vgpr56_vgpr57_vgpr58_vgpr59_vgpr60_vgpr61_vgpr62_vgpr63, 0, 0, 0, implicit $mode, implicit $exec + + +... + +... +# 16 pass source +# GCN-LABEL: name: xdl_16pass_write_vgpr_xdl_mfma_read_overlap_srcb +# GCN: V_MFMA +# GCN-NEXT: S_NOP 7 +# GCN-NEXT: S_NOP 7 +# GCN-NEXT: S_NOP 2 +# GCN-NEXT: V_MFMA +name: xdl_16pass_write_vgpr_xdl_mfma_read_overlap_srcb +body: | + bb.0: + $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21_vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31 = V_MFMA_F32_32X32X4F16_vgprcd_e64 $vgpr126_vgpr127, $vgpr128_vgpr129, $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21_vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31, 0, 0, 0, implicit $mode, implicit $exec + $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21_vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31 = V_MFMA_F32_32X32X4F16_vgprcd_e64 $vgpr128_vgpr129, $vgpr2_vgpr3, $vgpr32_vgpr33_vgpr34_vgpr35_vgpr36_vgpr37_vgpr38_vgpr39_vgpr40_vgpr41_vgpr42_vgpr43_vgpr44_vgpr45_vgpr46_vgpr47_vgpr48_vgpr49_vgpr50_vgpr51_vgpr52_vgpr53_vgpr54_vgpr55_vgpr56_vgpr57_vgpr58_vgpr59_vgpr60_vgpr61_vgpr62_vgpr63, 0, 0, 0, implicit $mode, implicit $exec + +... + +... +# 2 pass source +# GCN-LABEL: name: xdl_mfma_2pass_write_agpr_smfmac_read_overlap_srcc +# GCN: V_MFMA +# GCN-NEXT: S_NOP 2 +# GCN-NEXT: V_SMFMAC_ +name: xdl_mfma_2pass_write_agpr_smfmac_read_overlap_srcc +body: | + bb.0: + + $agpr0_agpr1_agpr2_agpr3 = V_MFMA_F32_4X4X4F16_e64 $vgpr4_vgpr5, $vgpr6_vgpr7, $agpr0_agpr1_agpr2_agpr3, 1, 2, 3, implicit $mode, implicit $exec + $agpr2_agpr3_agpr4_agpr5 = V_SMFMAC_F32_16X16X32_F16_e64 $vgpr0_vgpr1, $vgpr2_vgpr3_vgpr4_vgpr5, $vgpr32, 0, 0, $agpr2_agpr3_agpr4_agpr5, implicit $mode, implicit $exec + +... + +... +# GCN-LABEL: name: xdl_4pass_mfma_write_agpr_smfmac_read_overlap_srcc +# GCN: V_MFMA +# GCN-NEXT: S_NOP 4 +# GCN-NEXT: V_SMFMAC_ +name: xdl_4pass_mfma_write_agpr_smfmac_read_overlap_srcc +body: | + bb.0: + $agpr0_agpr1_agpr2_agpr3 = V_MFMA_I32_16X16X32I8_e64 $vgpr0_vgpr1, $vgpr2_vgpr3, $agpr0_agpr1_agpr2_agpr3, 0, 0, 0, implicit $mode, implicit $exec + $agpr2_agpr3_agpr4_agpr5 = V_SMFMAC_F32_16X16X32_F16_e64 $vgpr0_vgpr1, $vgpr2_vgpr3_vgpr4_vgpr5, $vgpr32, 0, 0, $agpr2_agpr3_agpr4_agpr5, implicit $mode, implicit $exec + +... + +... +# GCN-LABEL: name: xdl_8pass_mfma_write_agpr_smfmac_read_overlap_srcc +# GCN: V_MFMA +# GCN-NEXT: S_NOP 7 +# GCN-NEXT: S_NOP 0 +# GCN-NEXT: V_SMFMAC_ +name: xdl_8pass_mfma_write_agpr_smfmac_read_overlap_srcc +body: | + bb.0: + renamable $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15 = V_MFMA_F32_32X32X8F16_e64 killed $vgpr0_vgpr1, killed $vgpr2_vgpr3, 1065353216, 0, 0, 0, implicit $mode, implicit $exec + $agpr2_agpr3_agpr4_agpr5 = V_SMFMAC_F32_16X16X32_F16_e64 $vgpr0_vgpr1, $vgpr2_vgpr3_vgpr4_vgpr5, $vgpr32, 0, 0, $agpr2_agpr3_agpr4_agpr5, implicit $mode, implicit $exec +... + +... +# GCN-LABEL: name: xdl_16pass_mfma_write_agpr_smfmac_read_overlap_srcc +# GCN: V_MFMA +# GCN-NEXT: S_NOP 7 +# GCN-NEXT: S_NOP 7 +# GCN-NEXT: S_NOP 0 +# GCN-NEXT: V_SMFMAC_ +name: xdl_16pass_mfma_write_agpr_smfmac_read_overlap_srcc +body: | + bb.0: + $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15_agpr16_agpr17_agpr18_agpr19_agpr20_agpr21_agpr22_agpr23_agpr24_agpr25_agpr26_agpr27_agpr28_agpr29_agpr30_agpr31 = V_MFMA_F32_32X32X4F16_e64 $vgpr126_vgpr127, $vgpr128_vgpr129, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15_agpr16_agpr17_agpr18_agpr19_agpr20_agpr21_agpr22_agpr23_agpr24_agpr25_agpr26_agpr27_agpr28_agpr29_agpr30_agpr31, 0, 0, 0, implicit $mode, implicit $exec + $agpr2_agpr3_agpr4_agpr5 = V_SMFMAC_F32_16X16X32_F16_e64 $vgpr0_vgpr1, $vgpr2_vgpr3_vgpr4_vgpr5, $vgpr32, 0, 0, $agpr2_agpr3_agpr4_agpr5, implicit $mode, implicit $exec +... 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/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-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/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/schedule-addrspaces.ll b/llvm/test/CodeGen/AMDGPU/schedule-addrspaces.ll index 0139c52db1d5827ee4f66850f627e184da09219d..27e9d0fce9426d9877aa13288713d021b6ff256c 100644 --- a/llvm/test/CodeGen/AMDGPU/schedule-addrspaces.ll +++ b/llvm/test/CodeGen/AMDGPU/schedule-addrspaces.ll @@ -10,7 +10,7 @@ define amdgpu_gfx void @example(<4 x i32> inreg %rsrc, ptr addrspace(5) %src, i3 ; CHECK-NEXT: scratch_load_b32 v2, v0, off ; CHECK-NEXT: scratch_load_b32 v3, v3, off ; CHECK-NEXT: s_waitcnt vmcnt(0) -; CHECK-NEXT: buffer_store_b64 v[2:3], v1, s[4:7], 0 offen +; CHECK-NEXT: buffer_store_b64 v[2:3], v1, s[0:3], 0 offen ; CHECK-NEXT: s_setpc_b64 s[30:31] %x0 = load i32, ptr addrspace(5) %src diff --git a/llvm/test/CodeGen/AMDGPU/scratch-pointer-sink.ll b/llvm/test/CodeGen/AMDGPU/scratch-pointer-sink.ll index cdaac14833e0ef0e163f9c9d38815b8c60cac8fb..ec1de0222d5d9b941f7e04b9dbbe14d4814b9178 100644 --- a/llvm/test/CodeGen/AMDGPU/scratch-pointer-sink.ll +++ b/llvm/test/CodeGen/AMDGPU/scratch-pointer-sink.ll @@ -6,7 +6,7 @@ define amdgpu_gfx i32 @sink_scratch_pointer(ptr addrspace(5) %stack, i32 inreg % ; GCN-LABEL: sink_scratch_pointer: ; GCN: ; %bb.0: ; GCN-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN-NEXT: s_cmp_lg_u32 s4, 0 +; GCN-NEXT: s_cmp_lg_u32 s0, 0 ; GCN-NEXT: s_cbranch_scc0 .LBB0_2 ; GCN-NEXT: ; %bb.1: ; %bb2 ; GCN-NEXT: scratch_load_b32 v0, v0, off offset:-4 @@ -21,7 +21,7 @@ define amdgpu_gfx i32 @sink_scratch_pointer(ptr addrspace(5) %stack, i32 inreg % ; GISEL-LABEL: sink_scratch_pointer: ; GISEL: ; %bb.0: ; GISEL-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GISEL-NEXT: s_cmp_lg_u32 s4, 0 +; GISEL-NEXT: s_cmp_lg_u32 s0, 0 ; GISEL-NEXT: s_cbranch_scc0 .LBB0_2 ; GISEL-NEXT: ; %bb.1: ; %bb2 ; GISEL-NEXT: scratch_load_b32 v0, v0, off offset:-4 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/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/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/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/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-auto-casts.ll b/llvm/test/CodeGen/BPF/addr-space-auto-casts.ll new file mode 100644 index 0000000000000000000000000000000000000000..08e11e861c71cbd7fbc72765f1989e1c7d0190d5 --- /dev/null +++ b/llvm/test/CodeGen/BPF/addr-space-auto-casts.ll @@ -0,0 +1,78 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 +; RUN: opt --bpf-check-and-opt-ir -S -mtriple=bpf-pc-linux < %s | FileCheck %s + +define void @simple_store(ptr addrspace(272) %foo) { +; CHECK-LABEL: define void @simple_store( +; CHECK-SAME: ptr addrspace(272) [[FOO:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[FOO1:%.*]] = addrspacecast ptr addrspace(272) [[FOO]] to ptr +; CHECK-NEXT: [[ADD_PTR2:%.*]] = getelementptr inbounds i8, ptr [[FOO1]], i64 16 +; CHECK-NEXT: store volatile i32 57005, ptr [[ADD_PTR2]], align 4 +; CHECK-NEXT: [[ADD_PTR13:%.*]] = getelementptr inbounds i8, ptr [[FOO1]], i64 12 +; CHECK-NEXT: store volatile i32 48879, ptr [[ADD_PTR13]], align 4 +; CHECK-NEXT: ret void +; +entry: + %add.ptr = getelementptr inbounds i8, ptr addrspace(272) %foo, i64 16 + store volatile i32 57005, ptr addrspace(272) %add.ptr, align 4 + %add.ptr1 = getelementptr inbounds i8, ptr addrspace(272) %foo, i64 12 + store volatile i32 48879, ptr addrspace(272) %add.ptr1, align 4 + ret void +} + +define void @separate_addr_store(ptr addrspace(272) %foo, ptr addrspace(272) %bar) { +; CHECK-LABEL: define void @separate_addr_store( +; CHECK-SAME: ptr addrspace(272) [[FOO:%.*]], ptr addrspace(272) [[BAR:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[BAR3:%.*]] = addrspacecast ptr addrspace(272) [[BAR]] to ptr +; CHECK-NEXT: [[FOO1:%.*]] = addrspacecast ptr addrspace(272) [[FOO]] to ptr +; CHECK-NEXT: [[ADD_PTR2:%.*]] = getelementptr inbounds i8, ptr [[FOO1]], i64 16 +; CHECK-NEXT: store volatile i32 57005, ptr [[ADD_PTR2]], align 4 +; CHECK-NEXT: [[ADD_PTR14:%.*]] = getelementptr inbounds i8, ptr [[BAR3]], i64 12 +; CHECK-NEXT: store volatile i32 48879, ptr [[ADD_PTR14]], align 4 +; CHECK-NEXT: ret void +; +entry: + %add.ptr = getelementptr inbounds i8, ptr addrspace(272) %foo, i64 16 + store volatile i32 57005, ptr addrspace(272) %add.ptr, align 4 + %add.ptr1 = getelementptr inbounds i8, ptr addrspace(272) %bar, i64 12 + store volatile i32 48879, ptr addrspace(272) %add.ptr1, align 4 + ret void +} + +define i32 @simple_load(ptr addrspace(272) %foo) { +; CHECK-LABEL: define i32 @simple_load( +; CHECK-SAME: ptr addrspace(272) [[FOO:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[FOO1:%.*]] = addrspacecast ptr addrspace(272) [[FOO]] to ptr +; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[FOO1]], align 4 +; CHECK-NEXT: ret i32 [[TMP0]] +; +entry: + %0 = load i32, ptr addrspace(272) %foo, align 4 + ret i32 %0 +} + +define { i32, i1 } @simple_cmpxchg(ptr addrspace(1) %i) { +; CHECK-LABEL: define { i32, i1 } @simple_cmpxchg( +; CHECK-SAME: ptr addrspace(1) [[I:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[I1:%.*]] = addrspacecast ptr addrspace(1) [[I]] to ptr +; CHECK-NEXT: [[A:%.*]] = cmpxchg ptr [[I1]], i32 7, i32 42 monotonic monotonic, align 4 +; CHECK-NEXT: ret { i32, i1 } [[A]] +; +entry: + %a = cmpxchg ptr addrspace(1) %i, i32 7, i32 42 monotonic monotonic, align 4 + ret { i32, i1 } %a +} + +define void @simple_atomicrmw(ptr addrspace(1) %p) { +; CHECK-LABEL: define void @simple_atomicrmw( +; CHECK-SAME: ptr addrspace(1) [[P:%.*]]) { +; CHECK-NEXT: [[P1:%.*]] = addrspacecast ptr addrspace(1) [[P]] to ptr +; CHECK-NEXT: [[A:%.*]] = atomicrmw add ptr [[P1]], i64 42 monotonic, align 8 +; CHECK-NEXT: ret void +; + %a = atomicrmw add ptr addrspace(1) %p, i64 42 monotonic, align 8 + ret void +} diff --git a/llvm/test/CodeGen/BPF/addr-space-cast.ll b/llvm/test/CodeGen/BPF/addr-space-cast.ll new file mode 100644 index 0000000000000000000000000000000000000000..ad2860d8038ea72d063aed84192deab501469d1a --- /dev/null +++ b/llvm/test/CodeGen/BPF/addr-space-cast.ll @@ -0,0 +1,22 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4 +; RUN: llc -march=bpfel -mcpu=v4 -filetype=asm -show-mc-encoding < %s | FileCheck %s + +define ptr addrspace(1) @foo(ptr %p) { +; CHECK-LABEL: foo: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: r0 = addr_space_cast(r1, 1, 0) # encoding: [0xbf,0x10,0x01,0x00,0x00,0x00,0x01,0x00] +; CHECK-NEXT: exit # encoding: [0x95,0x00,0x00,0x00,0x00,0x00,0x00,0x00] +entry: + %0 = addrspacecast ptr %p to ptr addrspace(1) + ret ptr addrspace(1) %0 +} + +define ptr @bar(ptr addrspace(1) %p) { +; CHECK-LABEL: bar: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: r0 = addr_space_cast(r1, 0, 1) # encoding: [0xbf,0x10,0x01,0x00,0x01,0x00,0x00,0x00] +; CHECK-NEXT: exit # encoding: [0x95,0x00,0x00,0x00,0x00,0x00,0x00,0x00] +entry: + %0 = addrspacecast ptr addrspace(1) %p to ptr + ret ptr %0 +} diff --git a/llvm/test/CodeGen/BPF/addr-space-gep-chain.ll b/llvm/test/CodeGen/BPF/addr-space-gep-chain.ll new file mode 100644 index 0000000000000000000000000000000000000000..3ac85fb9b12662e26b8f83a24ce73d42c9ecd47b --- /dev/null +++ b/llvm/test/CodeGen/BPF/addr-space-gep-chain.ll @@ -0,0 +1,25 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 +; RUN: opt --bpf-check-and-opt-ir -S -mtriple=bpf-pc-linux < %s | FileCheck %s + +define void @test(ptr addrspace(1) %p) { +; CHECK-LABEL: define void @test( +; CHECK-SAME: ptr addrspace(1) [[P:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[P1:%.*]] = addrspacecast ptr addrspace(1) [[P]] to ptr +; CHECK-NEXT: [[A2:%.*]] = getelementptr inbounds i8, ptr [[P1]], i64 8 +; CHECK-NEXT: [[B3:%.*]] = getelementptr inbounds i8, ptr [[A2]], i64 16 +; CHECK-NEXT: [[C4:%.*]] = getelementptr inbounds i8, ptr [[B3]], i64 24 +; CHECK-NEXT: [[D5:%.*]] = getelementptr inbounds i8, ptr [[C4]], i64 32 +; CHECK-NEXT: store i64 11, ptr [[C4]], align 8 +; CHECK-NEXT: store i64 22, ptr [[D5]], align 8 +; CHECK-NEXT: ret void +; +entry: + %a = getelementptr inbounds i8, ptr addrspace(1) %p, i64 8 + %b = getelementptr inbounds i8, ptr addrspace(1) %a, i64 16 + %c = getelementptr inbounds i8, ptr addrspace(1) %b, i64 24 + %d = getelementptr inbounds i8, ptr addrspace(1) %c, i64 32 + store i64 11, ptr addrspace(1) %c, align 8 + store i64 22, ptr addrspace(1) %d, align 8 + ret void +} diff --git a/llvm/test/CodeGen/BPF/addr-space-globals.ll b/llvm/test/CodeGen/BPF/addr-space-globals.ll new file mode 100644 index 0000000000000000000000000000000000000000..73e80b7a0400b352cf597d323b4754ebe6a72d7c --- /dev/null +++ b/llvm/test/CodeGen/BPF/addr-space-globals.ll @@ -0,0 +1,30 @@ +; RUN: llc -march=bpfel -mcpu=v4 < %s | FileCheck %s + +; Generated from the following C code: +; +; #define __as __attribute__((address_space(272))) +; __as const char a[2] = {1,2}; +; __as char b[2] = {3,4}; +; __as char c[2]; +; +; Using the following command: +; +; clang --target=bpf -O2 -S -emit-llvm -o t.ll t.c + + +@a = dso_local local_unnamed_addr addrspace(272) constant [2 x i8] [i8 1, i8 2], align 1 +@b = dso_local local_unnamed_addr addrspace(272) global [2 x i8] [i8 3, i8 4], align 1 +@c = dso_local local_unnamed_addr addrspace(272) global [2 x i8] zeroinitializer, align 1 + +; Verify that a,b,c reside in the same section + +; CHECK: .section .addr_space.272,"aw",@progbits +; CHECK-NOT: .section +; CHECK: .globl a +; CHECK: .ascii "\001\002" +; CHECK-NOT: .section +; CHECK: .globl b +; CHECK: .ascii "\003\004" +; CHECK-NOT: .section +; CHECK: .globl c +; CHECK: .zero 2 diff --git a/llvm/test/CodeGen/BPF/addr-space-globals2.ll b/llvm/test/CodeGen/BPF/addr-space-globals2.ll new file mode 100644 index 0000000000000000000000000000000000000000..5944cb27ee18a87263b1c5d3c295626fe4d71ede --- /dev/null +++ b/llvm/test/CodeGen/BPF/addr-space-globals2.ll @@ -0,0 +1,25 @@ +; RUN: llc -march=bpfel -mcpu=v4 < %s | FileCheck %s + +; Generated from the following C code: +; +; __attribute__((address_space(1))) char a[2] = {1,2}; +; __attribute__((address_space(2))) char b[2] = {3,4}; +; +; Using the following command: +; +; clang --target=bpf -O2 -S -emit-llvm -o t.ll t.c + +@a = dso_local local_unnamed_addr addrspace(1) global [2 x i8] [i8 1, i8 2], align 1 +@b = dso_local local_unnamed_addr addrspace(2) global [2 x i8] [i8 3, i8 4], align 1 + +; Verify that a,b reside in separate sections + +; CHECK: .section .addr_space.1,"aw",@progbits +; CHECK-NOT: .section +; CHECK: .globl a +; CHECK: .ascii "\001\002" + +; CHECK: .section .addr_space.2,"aw",@progbits +; CHECK-NOT: .section +; CHECK: .globl b +; CHECK: .ascii "\003\004" diff --git a/llvm/test/CodeGen/BPF/addr-space-phi.ll b/llvm/test/CodeGen/BPF/addr-space-phi.ll new file mode 100644 index 0000000000000000000000000000000000000000..6d28b071f28086e9de94e19aa696b79e2108214c --- /dev/null +++ b/llvm/test/CodeGen/BPF/addr-space-phi.ll @@ -0,0 +1,53 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 +; RUN: opt --bpf-check-and-opt-ir -S -mtriple=bpf-pc-linux < %s | FileCheck %s + +; Generated from the following C code: +; +; #define __uptr __attribute__((address_space(1))) +; +; extern int __uptr *magic1(); +; extern int __uptr *magic2(); +; +; void test(long i) { +; int __uptr *a; +; +; if (i > 42) +; a = magic1(); +; else +; a = magic2(); +; a[5] = 7; +; } +; +; Using the following command: +; +; clang --target=bpf -O2 -S -emit-llvm -o t.ll t.c + +define void @test(i64 noundef %i) { +; CHECK: if.end: +; CHECK-NEXT: [[A_0:%.*]] = phi ptr addrspace(1) +; CHECK-NEXT: [[A_01:%.*]] = addrspacecast ptr addrspace(1) [[A_0]] to ptr +; CHECK-NEXT: [[ARRAYIDX2:%.*]] = getelementptr inbounds i32, ptr [[A_01]], i64 5 +; CHECK-NEXT: store i32 7, ptr [[ARRAYIDX2]], align 4 +; CHECK-NEXT: ret void +; +entry: + %cmp = icmp sgt i64 %i, 42 + br i1 %cmp, label %if.then, label %if.else + +if.then: ; preds = %entry + %call = tail call ptr addrspace(1) @magic1() + br label %if.end + +if.else: ; preds = %entry + %call1 = tail call ptr addrspace(1) @magic2() + br label %if.end + +if.end: ; preds = %if.else, %if.then + %a.0 = phi ptr addrspace(1) [ %call, %if.then ], [ %call1, %if.else ] + %arrayidx = getelementptr inbounds i32, ptr addrspace(1) %a.0, i64 5 + store i32 7, ptr addrspace(1) %arrayidx, align 4 + ret void +} + +declare ptr addrspace(1) @magic1(...) +declare ptr addrspace(1) @magic2(...) diff --git a/llvm/test/CodeGen/BPF/addr-space-simplify-1.ll b/llvm/test/CodeGen/BPF/addr-space-simplify-1.ll new file mode 100644 index 0000000000000000000000000000000000000000..32d67284d1c1b70dc359064cdcc6079d1b1f3c30 --- /dev/null +++ b/llvm/test/CodeGen/BPF/addr-space-simplify-1.ll @@ -0,0 +1,19 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 +; RUN: opt -passes=bpf-aspace-simplify -mtriple=bpf-pc-linux -S < %s | FileCheck %s + +; Check that bpf-aspace-simplify pass removes unnecessary (for BPF) +; address space casts for cast M->N -> GEP -> cast N->M chain. + +define dso_local ptr addrspace(1) @test (ptr addrspace(1) %p) { +; CHECK-LABEL: define dso_local ptr addrspace(1) @test( +; CHECK-SAME: ptr addrspace(1) [[P:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[B1:%.*]] = getelementptr inbounds i8, ptr addrspace(1) [[P]], i64 8 +; CHECK-NEXT: ret ptr addrspace(1) [[B1]] +; + entry: + %a = addrspacecast ptr addrspace(1) %p to ptr + %b = getelementptr inbounds i8, ptr %a, i64 8 + %c = addrspacecast ptr %b to ptr addrspace(1) + ret ptr addrspace(1) %c +} diff --git a/llvm/test/CodeGen/BPF/addr-space-simplify-2.ll b/llvm/test/CodeGen/BPF/addr-space-simplify-2.ll new file mode 100644 index 0000000000000000000000000000000000000000..a2965554a973302c50e745f3735ca904c3b316d0 --- /dev/null +++ b/llvm/test/CodeGen/BPF/addr-space-simplify-2.ll @@ -0,0 +1,21 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 +; RUN: opt -passes=bpf-aspace-simplify -mtriple=bpf-pc-linux -S < %s | FileCheck %s + +; Check that bpf-aspace-simplify pass does not change +; chain 'cast M->N -> GEP -> cast N->K'. + +define dso_local ptr addrspace(2) @test (ptr addrspace(1) %p) { +; CHECK-LABEL: define dso_local ptr addrspace(2) @test( +; CHECK-SAME: ptr addrspace(1) [[P:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[A:%.*]] = addrspacecast ptr addrspace(1) [[P]] to ptr +; CHECK-NEXT: [[B:%.*]] = getelementptr inbounds i8, ptr [[A]], i64 8 +; CHECK-NEXT: [[C:%.*]] = addrspacecast ptr [[B]] to ptr addrspace(2) +; CHECK-NEXT: ret ptr addrspace(2) [[C]] +; + entry: + %a = addrspacecast ptr addrspace(1) %p to ptr + %b = getelementptr inbounds i8, ptr %a, i64 8 + %c = addrspacecast ptr %b to ptr addrspace(2) + ret ptr addrspace(2) %c +} diff --git a/llvm/test/CodeGen/BPF/addr-space-simplify-3.ll b/llvm/test/CodeGen/BPF/addr-space-simplify-3.ll new file mode 100644 index 0000000000000000000000000000000000000000..a7736c462b44b32a47cf733275227ff5ef532b91 --- /dev/null +++ b/llvm/test/CodeGen/BPF/addr-space-simplify-3.ll @@ -0,0 +1,26 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 +; RUN: opt -passes=bpf-aspace-simplify -mtriple=bpf-pc-linux -S < %s | FileCheck %s + +; Check that when bpf-aspace-simplify pass modifies chain +; 'cast M->N -> GEP -> cast N->M' it does not remove GEP, +; when that GEP is used by some other instruction. + +define dso_local ptr addrspace(1) @test (ptr addrspace(1) %p) { +; CHECK-LABEL: define dso_local ptr addrspace(1) @test( +; CHECK-SAME: ptr addrspace(1) [[P:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[A:%.*]] = addrspacecast ptr addrspace(1) [[P]] to ptr +; CHECK-NEXT: [[B:%.*]] = getelementptr inbounds i8, ptr [[A]], i64 8 +; CHECK-NEXT: [[B1:%.*]] = getelementptr inbounds i8, ptr addrspace(1) [[P]], i64 8 +; CHECK-NEXT: call void @sink(ptr [[B]]) +; CHECK-NEXT: ret ptr addrspace(1) [[B1]] +; + entry: + %a = addrspacecast ptr addrspace(1) %p to ptr + %b = getelementptr inbounds i8, ptr %a, i64 8 + %c = addrspacecast ptr %b to ptr addrspace(1) + call void @sink(ptr %b) + ret ptr addrspace(1) %c +} + +declare dso_local void @sink(ptr) diff --git a/llvm/test/CodeGen/BPF/addr-space-simplify-4.ll b/llvm/test/CodeGen/BPF/addr-space-simplify-4.ll new file mode 100644 index 0000000000000000000000000000000000000000..b2c384bbb6abd3ef7468f8d1fc98a3b41be1f911 --- /dev/null +++ b/llvm/test/CodeGen/BPF/addr-space-simplify-4.ll @@ -0,0 +1,21 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 +; RUN: opt -passes=bpf-aspace-simplify -mtriple=bpf-pc-linux -S < %s | FileCheck %s + +; Check that bpf-aspace-simplify pass simplifies chain +; 'cast K->M -> cast M->N -> GEP -> cast N->M -> cast M->K'. + +define dso_local ptr addrspace(2) @test (ptr addrspace(2) %p) { +; CHECK-LABEL: define dso_local ptr addrspace(2) @test( +; CHECK-SAME: ptr addrspace(2) [[P:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[C12:%.*]] = getelementptr inbounds i8, ptr addrspace(2) [[P]], i64 8 +; CHECK-NEXT: ret ptr addrspace(2) [[C12]] +; + entry: + %a = addrspacecast ptr addrspace(2) %p to ptr addrspace(1) + %b = addrspacecast ptr addrspace(1) %a to ptr + %c = getelementptr inbounds i8, ptr %b, i64 8 + %d = addrspacecast ptr %c to ptr addrspace(1) + %e = addrspacecast ptr addrspace (1) %d to ptr addrspace(2) + ret ptr addrspace(2) %e +} diff --git a/llvm/test/CodeGen/BPF/addr-space-simplify-5.ll b/llvm/test/CodeGen/BPF/addr-space-simplify-5.ll new file mode 100644 index 0000000000000000000000000000000000000000..b62d25384d9583fac21cef6dc8b7338582c4d816 --- /dev/null +++ b/llvm/test/CodeGen/BPF/addr-space-simplify-5.ll @@ -0,0 +1,25 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 +; RUN: opt -passes=bpf-aspace-simplify -mtriple=bpf-pc-linux -S < %s | FileCheck %s + +; Check that bpf-aspace-simplify pass removes unnecessary (for BPF) +; address space casts for cast M->N -> GEP -> cast N->M chain, +; where chain is split between several BBs. + +define dso_local ptr addrspace(1) @test (ptr addrspace(1) %p) { +; CHECK-LABEL: define dso_local ptr addrspace(1) @test( +; CHECK-SAME: ptr addrspace(1) [[P:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[EXIT:%.*]] +; CHECK: exit: +; CHECK-NEXT: [[B1:%.*]] = getelementptr inbounds i8, ptr addrspace(1) [[P]], i64 8 +; CHECK-NEXT: ret ptr addrspace(1) [[B1]] +; +entry: + %a = addrspacecast ptr addrspace(1) %p to ptr + %b = getelementptr inbounds i8, ptr %a, i64 8 + br label %exit + +exit: + %c = addrspacecast ptr %b to ptr addrspace(1) + ret ptr addrspace(1) %c +} diff --git a/llvm/test/CodeGen/BPF/assembler-disassembler.s b/llvm/test/CodeGen/BPF/assembler-disassembler.s index 2bc7421c2471c26f59ec8c21a2aaae80a2f1d321..991d6edc683a302a9a89ca7e2e64695697f4e35d 100644 --- a/llvm/test/CodeGen/BPF/assembler-disassembler.s +++ b/llvm/test/CodeGen/BPF/assembler-disassembler.s @@ -289,3 +289,10 @@ r0 = *(u32*)skb[42] r0 = *(u8*)skb[r1] r0 = *(u16*)skb[r1] r0 = *(u32*)skb[r1] + +// CHECK: bf 10 01 00 01 00 00 00 r0 = addr_space_cast(r1, 0x0, 0x1) +// CHECK: bf 21 01 00 00 00 01 00 r1 = addr_space_cast(r2, 0x1, 0x0) +// CHECK: bf 43 01 00 2a 00 07 00 r3 = addr_space_cast(r4, 0x7, 0x2a) +r0 = addr_space_cast(r1, 0, 1) +r1 = addr_space_cast(r2, 1, 0) +r3 = addr_space_cast(r4, 7, 42) 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/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/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/exp2_error.ll b/llvm/test/CodeGen/DirectX/exp2_error.ll new file mode 100644 index 0000000000000000000000000000000000000000..6b9126785fd4b87475d3dd2c07d945ee3e75e56e --- /dev/null +++ b/llvm/test/CodeGen/DirectX/exp2_error.ll @@ -0,0 +1,13 @@ +; RUN: not opt -S -dxil-op-lower %s 2>&1 | FileCheck %s + +; DXIL operation exp2 does not support double overload type +; CHECK: LLVM ERROR: Invalid Overload + +define noundef double @exp2_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 + %elt.exp2 = call double @llvm.exp2.f64(double %0) + ret double %elt.exp2 +} 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/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/frac.ll b/llvm/test/CodeGen/DirectX/frac.ll index ab605ed6084aa4f87e9b852ffcbd6701f8125a6f..ae86fe06654da15b4b8cb930013e1be06caf90bf 100644 --- a/llvm/test/CodeGen/DirectX/frac.ll +++ b/llvm/test/CodeGen/DirectX/frac.ll @@ -29,6 +29,3 @@ entry: %dx.frac = call half @llvm.dx.frac.f16(half %0) ret half %dx.frac } - -; Function Attrs: nocallback nofree nosync nounwind readnone speculatable willreturn -declare half @llvm.dx.frac.f16(half) #1 diff --git a/llvm/test/CodeGen/DirectX/frac_error.ll b/llvm/test/CodeGen/DirectX/frac_error.ll new file mode 100644 index 0000000000000000000000000000000000000000..ebce76105ad4d7bdc25212a3313234bdd3fc9533 --- /dev/null +++ b/llvm/test/CodeGen/DirectX/frac_error.ll @@ -0,0 +1,14 @@ +; RUN: not opt -S -dxil-op-lower %s 2>&1 | FileCheck %s + +; DXIL operation frac does not support double overload type +; CHECK: LLVM ERROR: Invalid Overload Type + +; Function Attrs: noinline nounwind optnone +define noundef double @frac_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.frac = call double @llvm.dx.frac.f64(double %0) + ret double %dx.frac +} 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/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/round_error.ll b/llvm/test/CodeGen/DirectX/round_error.ll new file mode 100644 index 0000000000000000000000000000000000000000..3bd87b2bbf02007916b67fe0a2e89c8a4ffd3970 --- /dev/null +++ b/llvm/test/CodeGen/DirectX/round_error.ll @@ -0,0 +1,13 @@ +; RUN: not opt -S -dxil-op-lower %s 2>&1 | FileCheck %s + +; This test is expected to fail with the following error +; CHECK: LLVM ERROR: Invalid Overload Type + +define noundef double @round_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 + %elt.round = call double @llvm.round.f64(double %0) + ret double %elt.round +} 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/sin.ll b/llvm/test/CodeGen/DirectX/sin.ll index bb31d28bfcfee62365ae2d3153057a49754a639c..1f285c433581cfc398dafd268e0b2a8cd1923036 100644 --- a/llvm/test/CodeGen/DirectX/sin.ll +++ b/llvm/test/CodeGen/DirectX/sin.ll @@ -4,11 +4,8 @@ ; CHECK:call float @dx.op.unary.f32(i32 13, float %{{.*}}) ; CHECK:call half @dx.op.unary.f16(i32 13, 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 @_Z3foof(float noundef %a) #0 { +define noundef float @sin_float(float noundef %a) #0 { entry: %a.addr = alloca float, align 4 store float %a, ptr %a.addr, align 4 @@ -17,11 +14,8 @@ entry: ret float %1 } -; Function Attrs: nocallback nofree nosync nounwind readnone speculatable willreturn -declare float @llvm.sin.f32(float) #1 - ; Function Attrs: noinline nounwind optnone -define noundef half @_Z3barDh(half noundef %a) #0 { +define noundef half @sin_half(half noundef %a) #0 { entry: %a.addr = alloca half, align 2 store half %a, ptr %a.addr, align 2 @@ -29,15 +23,3 @@ entry: %1 = call half @llvm.sin.f16(half %0) ret half %1 } - -; Function Attrs: nocallback nofree nosync nounwind readnone speculatable willreturn -declare half @llvm.sin.f16(half) #1 - -attributes #0 = { noinline nounwind optnone "frame-pointer"="none" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" } -attributes #1 = { nocallback nofree nosync nounwind readnone speculatable willreturn } - -!llvm.module.flags = !{!0} -!llvm.ident = !{!1} - -!0 = !{i32 1, !"wchar_size", i32 4} -!1 = !{!"clang version 15.0.0 (https://github.com/llvm/llvm-project.git 73417c517644db5c419c85c0b3cb6750172fcab5)"} diff --git a/llvm/test/CodeGen/DirectX/sin_error.ll b/llvm/test/CodeGen/DirectX/sin_error.ll new file mode 100644 index 0000000000000000000000000000000000000000..ece0e530315b2fecf1746e8a1c56748646be1a3e --- /dev/null +++ b/llvm/test/CodeGen/DirectX/sin_error.ll @@ -0,0 +1,14 @@ +; RUN: not opt -S -dxil-op-lower %s 2>&1 | FileCheck %s + +; DXIL operation sin does not support double overload type +; CHECK: LLVM ERROR: Invalid Overload + +define noundef double @sin_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 + %1 = call double @llvm.sin.f64(double %0) + ret double %1 +} + 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/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/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/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/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/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/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-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-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/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/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/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/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/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/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/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/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/calling-conv.ll b/llvm/test/CodeGen/RISCV/rvv/calling-conv.ll index 78385a80b47ebd399fc3bc1a89a7f46c408fc6ce..78e8700a9feff80cb9e3892f8b8ff3da7090a2a0 100644 --- a/llvm/test/CodeGen/RISCV/rvv/calling-conv.ll +++ b/llvm/test/CodeGen/RISCV/rvv/calling-conv.ll @@ -86,3 +86,79 @@ 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>}) 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-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-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/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-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/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..0a7051633a19ae877a6eb8ad9639b08e201e9e94 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,34 @@ 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 +} diff --git a/llvm/test/CodeGen/RISCV/rvv/vwmul-sdnode.ll b/llvm/test/CodeGen/RISCV/rvv/vwmul-sdnode.ll index 3634162eefd642f8047497beaab14729c15784cc..539a4bdb27ad59c58990901f3091d4d236d36cb1 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, e32, mf2, ta, ma +; CHECK-NEXT: vzext.vf2 v10, v8 +; CHECK-NEXT: vzext.vf2 v11, v9 +; CHECK-NEXT: vwmulu.vv v8, v10, v11 ; 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 @@ -403,10 +403,10 @@ define <vscale x 1 x i64> @vwmulu_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: vzext.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: vzext.vf2 v10, v8 +; CHECK-NEXT: vzext.vf2 v11, v9 +; CHECK-NEXT: vwmulu.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 @@ -421,10 +421,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 +437,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 +451,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, e32, m1, ta, ma +; CHECK-NEXT: vzext.vf2 v10, v8 +; CHECK-NEXT: vzext.vf2 v11, v9 +; CHECK-NEXT: vwmulu.vv v8, v10, v11 ; 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 +465,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 +481,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 @@ -499,10 +499,10 @@ define <vscale x 2 x i64> @vwmulu_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: vzext.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: vzext.vf2 v10, v8 +; CHECK-NEXT: vzext.vf2 v11, v9 +; CHECK-NEXT: vwmulu.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 @@ -517,10 +517,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 +533,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 +547,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, e32, m2, ta, ma +; CHECK-NEXT: vzext.vf2 v12, v8 +; CHECK-NEXT: vzext.vf2 v14, v9 +; CHECK-NEXT: vwmulu.vv v8, v12, v14 ; 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 +561,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 +577,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 @@ -595,10 +595,10 @@ define <vscale x 4 x i64> @vwmulu_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: vzext.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: vzext.vf2 v12, v8 +; CHECK-NEXT: vzext.vf2 v14, v9 +; CHECK-NEXT: vwmulu.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 @@ -613,10 +613,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 +629,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 +643,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, e32, m4, ta, ma +; CHECK-NEXT: vzext.vf2 v16, v8 +; CHECK-NEXT: vzext.vf2 v20, v10 +; CHECK-NEXT: vwmulu.vv v8, v16, v20 ; 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 +657,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 +673,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 @@ -691,10 +691,10 @@ define <vscale x 8 x i64> @vwmulu_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: vzext.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: vzext.vf2 v16, v8 +; CHECK-NEXT: vzext.vf2 v20, v10 +; CHECK-NEXT: vwmulu.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 @@ -709,10 +709,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 +725,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 +739,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, e32, mf2, ta, ma +; CHECK-NEXT: vzext.vf4 v10, v8 +; CHECK-NEXT: vzext.vf4 v11, v9 +; CHECK-NEXT: vwmulu.vv v8, v10, v11 ; 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 +753,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 +769,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 @@ -787,10 +787,10 @@ define <vscale x 1 x i64> @vwmulu_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: vzext.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: vzext.vf4 v10, v8 +; CHECK-NEXT: vzext.vf4 v11, v9 +; CHECK-NEXT: vwmulu.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 @@ -805,10 +805,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 +821,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 +835,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, e32, m1, ta, ma +; CHECK-NEXT: vzext.vf4 v10, v8 +; CHECK-NEXT: vzext.vf4 v11, v9 +; CHECK-NEXT: vwmulu.vv v8, v10, v11 ; 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 +849,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 +865,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 @@ -883,10 +883,10 @@ define <vscale x 2 x i64> @vwmulu_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: vzext.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: vzext.vf4 v10, v8 +; CHECK-NEXT: vzext.vf4 v11, v9 +; CHECK-NEXT: vwmulu.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 @@ -901,10 +901,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 +917,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 +931,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, e32, m2, ta, ma +; CHECK-NEXT: vzext.vf4 v12, v8 +; CHECK-NEXT: vzext.vf4 v14, v9 +; CHECK-NEXT: vwmulu.vv v8, v12, v14 ; 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 +945,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 +961,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 @@ -979,10 +979,10 @@ define <vscale x 4 x i64> @vwmulu_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: vzext.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: vzext.vf4 v12, v8 +; CHECK-NEXT: vzext.vf4 v14, v9 +; CHECK-NEXT: vwmulu.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 @@ -997,10 +997,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 +1013,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 +1027,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, e32, m4, ta, ma +; CHECK-NEXT: vzext.vf4 v16, v8 +; CHECK-NEXT: vzext.vf4 v20, v9 +; CHECK-NEXT: vwmulu.vv v8, v16, v20 ; 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 +1041,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 +1057,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 @@ -1075,10 +1075,10 @@ define <vscale x 8 x i64> @vwmulu_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: vzext.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: vzext.vf4 v16, v8 +; CHECK-NEXT: vzext.vf4 v20, v9 +; CHECK-NEXT: vwmulu.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 @@ -1093,10 +1093,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 new file mode 100644 index 0000000000000000000000000000000000000000..e5c2e0180ee0a6f719e6ab77643066fc39739c21 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/zcmp-additional-stack.ll @@ -0,0 +1,49 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4 +; RUN: llc -mtriple=riscv32 -mattr=+zcmp,+e -target-abi ilp32e -verify-machineinstrs < %s | FileCheck %s --check-prefix=RV32 +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: .cfi_def_cfa_offset 24 +; RV32-NEXT: .cfi_offset ra, -12 +; RV32-NEXT: .cfi_offset s0, -8 +; RV32-NEXT: .cfi_offset s1, -4 +; RV32-NEXT: sw a4, 4(sp) # 4-byte Folded Spill +; RV32-NEXT: sw a2, 0(sp) # 4-byte Folded Spill +; RV32-NEXT: mv a2, a1 +; RV32-NEXT: mv s1, a0 +; RV32-NEXT: li a0, 1 +; RV32-NEXT: andi a3, a3, 1 +; RV32-NEXT: .LBB0_1: # %while.body +; RV32-NEXT: # =>This Inner Loop Header: Depth=1 +; RV32-NEXT: mv s0, a0 +; RV32-NEXT: li a0, 0 +; RV32-NEXT: bnez a3, .LBB0_1 +; RV32-NEXT: # %bb.2: # %while.end +; RV32-NEXT: lui a0, 4112 +; RV32-NEXT: addi a1, a0, 257 +; RV32-NEXT: mv a0, a2 +; RV32-NEXT: call __mulsi3 +; RV32-NEXT: sw a0, 0(zero) +; RV32-NEXT: andi s0, s0, 1 +; RV32-NEXT: lw a0, 0(sp) # 4-byte Folded Reload +; RV32-NEXT: add s0, s0, a0 +; 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 +entry: + br label %while.body + +while.body: ; preds = %while.body, %entry + %n.addr.042 = phi i32 [ 1, %entry ], [ 0, %while.body ] + br i1 %0, label %while.body, label %while.end + +while.end: ; preds = %while.body + %or5 = mul i32 %_c, 16843009 + store i32 %or5, ptr null, align 4 + %1 = and i32 %n.addr.042, 1 + %scevgep = getelementptr i8, ptr %incdec.ptr, i32 %1 + store i8 %conv14, ptr %scevgep, align 1 + ret ptr %s +} 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..a2a722a7f72824c481e01cd4b4b66cf344476d55 --- /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) + ; CHECK-NEXT: sw a1, -2036(t0) + ; CHECK-NEXT: lui a0, 1 + ; CHECK-NEXT: add a0, sp, a0 + ; CHECK-NEXT: sw a2, -2048(a0) + ; CHECK-NEXT: sw a3, -2044(a0) + ; CHECK-NEXT: sw a4, 2040(sp) + ; CHECK-NEXT: sw a5, 2044(sp) + ; CHECK-NEXT: sw a6, 2032(sp) + ; CHECK-NEXT: sw a7, 2036(sp) + ; CHECK-NEXT: lui a0, 1 + ; CHECK-NEXT: add a0, sp, a0 + ; CHECK-NEXT: lw a1, -2036(a0) + ; CHECK-NEXT: lw a0, -2040(a0) + ; CHECK-NEXT: lui a0, 1 + ; CHECK-NEXT: add a0, sp, a0 + ; CHECK-NEXT: lw a2, -2048(a0) + ; CHECK-NEXT: lw a3, -2044(a0) + ; CHECK-NEXT: lw a4, 2040(sp) + ; CHECK-NEXT: lw a5, 2044(sp) + ; CHECK-NEXT: lw a6, 2032(sp) + ; CHECK-NEXT: lw a7, 2036(sp) + ; 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/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/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/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/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/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..ce3ab8895a5948810f91ed4b306ab29f542e1105 100644 --- a/llvm/test/CodeGen/SPIRV/pointers/struct-opaque-pointers.ll +++ b/llvm/test/CodeGen/SPIRV/pointers/struct-opaque-pointers.ll @@ -1,5 +1,5 @@ ; 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]] 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..703f1e22a0321a362cc139b2414aba2626e9b704 --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/pointers/type-deduce-by-call-chain.ll @@ -0,0 +1,52 @@ +; 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) + 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-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/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..8290dbfe23104f0ca4b03ebc60239b0ab49bafd6 100644 --- a/llvm/test/CodeGen/SystemZ/call-zos-vararg.ll +++ b/llvm/test/CodeGen/SystemZ/call-zos-vararg.ll @@ -108,7 +108,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 +202,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 +294,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..23fd2739698a40507573532c632d883fb06170c5 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): diff --git a/llvm/test/CodeGen/SystemZ/cond-move-08.mir b/llvm/test/CodeGen/SystemZ/cond-move-08.mir index 93aa5626b8e894724611c35fd7d04b7696460bc8..64c6d0697992827d0c6a397eca46060fcc6e5d4f 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: 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..2701a1dc034a22706a0451a5d0a8e495ee25e090 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: | diff --git a/llvm/test/CodeGen/SystemZ/cond-move-regalloc-hints.mir b/llvm/test/CodeGen/SystemZ/cond-move-regalloc-hints.mir index e7e1eaf8f8fdcd768374e63686a2bd71bd5b74af..c98ffda83727214fc0118dc106b9d11d6aa73c52 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: diff --git a/llvm/test/CodeGen/SystemZ/frame-28.mir b/llvm/test/CodeGen/SystemZ/frame-28.mir index dd5933a9c7b4b4c73860a5888b18a12c21ff554f..13337dba6ec53feb3a81e1cfa63ab254c2b868e7 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 } 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/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/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/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/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/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..3a74fca2377370fd39e2583fcc6e1c2bacb0ff5a --- /dev/null +++ b/llvm/test/CodeGen/X86/avgceilu.ll @@ -0,0 +1,2219 @@ +; 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: 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: vextractf128 $1, %ymm0, %xmm0 +; AVX1-NEXT: vpsrlw $1, %xmm0, %xmm0 +; AVX1-NEXT: vpand %xmm3, %xmm0, %xmm0 +; AVX1-NEXT: vextractf128 $1, %ymm2, %xmm3 +; AVX1-NEXT: vpsubb %xmm0, %xmm3, %xmm0 +; AVX1-NEXT: vpsubb %xmm1, %xmm2, %xmm1 +; AVX1-NEXT: vinsertf128 $1, %xmm0, %ymm1, %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: vorps %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: 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: 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: 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: 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: vpsubb %xmm0, %xmm3, %xmm0 +; AVX1-NEXT: vpsubb %xmm6, %xmm5, %xmm3 +; AVX1-NEXT: vinsertf128 $1, %xmm0, %ymm3, %ymm0 +; AVX1-NEXT: vextractf128 $1, %ymm4, %xmm3 +; AVX1-NEXT: vpsubb %xmm1, %xmm3, %xmm1 +; AVX1-NEXT: vpsubb %xmm2, %xmm4, %xmm2 +; AVX1-NEXT: vinsertf128 $1, %xmm1, %ymm2, %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: vorps %ymm3, %ymm1, %ymm4 +; AVX1-NEXT: vorps %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: 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: 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/code-model-elf.ll b/llvm/test/CodeGen/X86/code-model-elf.ll index 71a6a310906e2efce92a48a57fa117e97925afe9..0da62e3e7a65192b2cf42f882b6ec0c862d92c42 100644 --- a/llvm/test/CodeGen/X86/code-model-elf.ll +++ b/llvm/test/CodeGen/X86/code-model-elf.ll @@ -54,6 +54,7 @@ target triple = "x86_64--linux" @extern_data = external global [10 x i32], align 16 @thread_data = external thread_local global i32, align 4 @unknown_size_data = dso_local global [0 x i32] zeroinitializer, align 16 +@bool = dso_local global i1 false @opaque = external dso_local global %t @forced_small_data = dso_local global [10 x i32] zeroinitializer, code_model "small", align 16 @forced_large_data = dso_local global [10 x i32] zeroinitializer, code_model "large", align 16 @@ -746,6 +747,64 @@ define dso_local i32 @load_unknown_size_data() #0 { ret i32 %rv } +define dso_local i1 @load_bool() #0 { +; SMALL-STATIC-LABEL: load_bool: +; SMALL-STATIC: # %bb.0: +; SMALL-STATIC-NEXT: movzbl bool(%rip), %eax +; SMALL-STATIC-NEXT: retq +; +; MEDIUM-STATIC-LABEL: load_bool: +; MEDIUM-STATIC: # %bb.0: +; MEDIUM-STATIC-NEXT: movabsq $bool, %rax +; MEDIUM-STATIC-NEXT: movzbl (%rax), %eax +; MEDIUM-STATIC-NEXT: retq +; +; LARGE-STATIC-LABEL: load_bool: +; LARGE-STATIC: # %bb.0: +; LARGE-STATIC-NEXT: movabsq $bool, %rax +; LARGE-STATIC-NEXT: movzbl (%rax), %eax +; LARGE-STATIC-NEXT: retq +; +; SMALL-PIC-LABEL: load_bool: +; SMALL-PIC: # %bb.0: +; SMALL-PIC-NEXT: movzbl bool(%rip), %eax +; SMALL-PIC-NEXT: retq +; +; MEDIUM-SMALL-DATA-PIC-LABEL: load_bool: +; MEDIUM-SMALL-DATA-PIC: # %bb.0: +; MEDIUM-SMALL-DATA-PIC-NEXT: movzbl bool(%rip), %eax +; MEDIUM-SMALL-DATA-PIC-NEXT: retq +; +; MEDIUM-PIC-LABEL: load_bool: +; MEDIUM-PIC: # %bb.0: +; MEDIUM-PIC-NEXT: leaq _GLOBAL_OFFSET_TABLE_(%rip), %rax +; MEDIUM-PIC-NEXT: movabsq $bool@GOTOFF, %rcx +; MEDIUM-PIC-NEXT: movzbl (%rax,%rcx), %eax +; MEDIUM-PIC-NEXT: retq +; +; LARGE-PIC-LABEL: load_bool: +; LARGE-PIC: # %bb.0: +; LARGE-PIC-NEXT: .L12$pb: +; LARGE-PIC-NEXT: leaq .L12$pb(%rip), %rax +; LARGE-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L12$pb, %rcx +; LARGE-PIC-NEXT: addq %rax, %rcx +; LARGE-PIC-NEXT: movabsq $bool@GOTOFF, %rax +; LARGE-PIC-NEXT: movzbl (%rcx,%rax), %eax +; LARGE-PIC-NEXT: retq +; +; LARGE-SMALL-DATA-PIC-LABEL: load_bool: +; LARGE-SMALL-DATA-PIC: # %bb.0: +; LARGE-SMALL-DATA-PIC-NEXT: .L12$pb: +; LARGE-SMALL-DATA-PIC-NEXT: leaq .L12$pb(%rip), %rax +; LARGE-SMALL-DATA-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L12$pb, %rcx +; LARGE-SMALL-DATA-PIC-NEXT: addq %rax, %rcx +; LARGE-SMALL-DATA-PIC-NEXT: movabsq $bool@GOTOFF, %rax +; LARGE-SMALL-DATA-PIC-NEXT: movzbl (%rcx,%rax), %eax +; LARGE-SMALL-DATA-PIC-NEXT: retq + %rv = load i1, ptr @bool + ret i1 %rv +} + define dso_local ptr @lea_opaque() #0 { ; SMALL-STATIC-LABEL: lea_opaque: ; SMALL-STATIC: # %bb.0: @@ -783,9 +842,9 @@ define dso_local ptr @lea_opaque() #0 { ; ; LARGE-PIC-LABEL: lea_opaque: ; LARGE-PIC: # %bb.0: -; LARGE-PIC-NEXT: .L12$pb: -; LARGE-PIC-NEXT: leaq .L12$pb(%rip), %rax -; LARGE-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L12$pb, %rcx +; LARGE-PIC-NEXT: .L13$pb: +; LARGE-PIC-NEXT: leaq .L13$pb(%rip), %rax +; LARGE-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L13$pb, %rcx ; LARGE-PIC-NEXT: addq %rax, %rcx ; LARGE-PIC-NEXT: movabsq $opaque@GOTOFF, %rax ; LARGE-PIC-NEXT: addq %rcx, %rax @@ -793,9 +852,9 @@ define dso_local ptr @lea_opaque() #0 { ; ; LARGE-SMALL-DATA-PIC-LABEL: lea_opaque: ; LARGE-SMALL-DATA-PIC: # %bb.0: -; LARGE-SMALL-DATA-PIC-NEXT: .L12$pb: -; LARGE-SMALL-DATA-PIC-NEXT: leaq .L12$pb(%rip), %rax -; LARGE-SMALL-DATA-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L12$pb, %rcx +; LARGE-SMALL-DATA-PIC-NEXT: .L13$pb: +; LARGE-SMALL-DATA-PIC-NEXT: leaq .L13$pb(%rip), %rax +; LARGE-SMALL-DATA-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L13$pb, %rcx ; LARGE-SMALL-DATA-PIC-NEXT: addq %rax, %rcx ; LARGE-SMALL-DATA-PIC-NEXT: movabsq $opaque@GOTOFF, %rax ; LARGE-SMALL-DATA-PIC-NEXT: addq %rcx, %rax @@ -840,9 +899,9 @@ define dso_local ptr @lea_ehdr_start() #0 { ; ; LARGE-PIC-LABEL: lea_ehdr_start: ; LARGE-PIC: # %bb.0: -; LARGE-PIC-NEXT: .L13$pb: -; LARGE-PIC-NEXT: leaq .L13$pb(%rip), %rax -; LARGE-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L13$pb, %rcx +; LARGE-PIC-NEXT: .L14$pb: +; LARGE-PIC-NEXT: leaq .L14$pb(%rip), %rax +; LARGE-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L14$pb, %rcx ; LARGE-PIC-NEXT: addq %rax, %rcx ; LARGE-PIC-NEXT: movabsq $__ehdr_start@GOTOFF, %rax ; LARGE-PIC-NEXT: addq %rcx, %rax @@ -850,9 +909,9 @@ define dso_local ptr @lea_ehdr_start() #0 { ; ; LARGE-SMALL-DATA-PIC-LABEL: lea_ehdr_start: ; LARGE-SMALL-DATA-PIC: # %bb.0: -; LARGE-SMALL-DATA-PIC-NEXT: .L13$pb: -; LARGE-SMALL-DATA-PIC-NEXT: leaq .L13$pb(%rip), %rax -; LARGE-SMALL-DATA-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L13$pb, %rcx +; LARGE-SMALL-DATA-PIC-NEXT: .L14$pb: +; LARGE-SMALL-DATA-PIC-NEXT: leaq .L14$pb(%rip), %rax +; LARGE-SMALL-DATA-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L14$pb, %rcx ; LARGE-SMALL-DATA-PIC-NEXT: addq %rax, %rcx ; LARGE-SMALL-DATA-PIC-NEXT: movabsq $__ehdr_start@GOTOFF, %rax ; LARGE-SMALL-DATA-PIC-NEXT: addq %rcx, %rax @@ -897,9 +956,9 @@ define dso_local ptr @lea_start_foo() #0 { ; ; LARGE-PIC-LABEL: lea_start_foo: ; LARGE-PIC: # %bb.0: -; LARGE-PIC-NEXT: .L14$pb: -; LARGE-PIC-NEXT: leaq .L14$pb(%rip), %rax -; LARGE-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L14$pb, %rcx +; LARGE-PIC-NEXT: .L15$pb: +; LARGE-PIC-NEXT: leaq .L15$pb(%rip), %rax +; LARGE-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L15$pb, %rcx ; LARGE-PIC-NEXT: addq %rax, %rcx ; LARGE-PIC-NEXT: movabsq $__start_foo@GOTOFF, %rax ; LARGE-PIC-NEXT: addq %rcx, %rax @@ -907,9 +966,9 @@ define dso_local ptr @lea_start_foo() #0 { ; ; LARGE-SMALL-DATA-PIC-LABEL: lea_start_foo: ; LARGE-SMALL-DATA-PIC: # %bb.0: -; LARGE-SMALL-DATA-PIC-NEXT: .L14$pb: -; LARGE-SMALL-DATA-PIC-NEXT: leaq .L14$pb(%rip), %rax -; LARGE-SMALL-DATA-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L14$pb, %rcx +; LARGE-SMALL-DATA-PIC-NEXT: .L15$pb: +; LARGE-SMALL-DATA-PIC-NEXT: leaq .L15$pb(%rip), %rax +; LARGE-SMALL-DATA-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L15$pb, %rcx ; LARGE-SMALL-DATA-PIC-NEXT: addq %rax, %rcx ; LARGE-SMALL-DATA-PIC-NEXT: movabsq $__start_foo@GOTOFF, %rax ; LARGE-SMALL-DATA-PIC-NEXT: addq %rcx, %rax @@ -954,9 +1013,9 @@ define dso_local ptr @lea_stop_foo() #0 { ; ; LARGE-PIC-LABEL: lea_stop_foo: ; LARGE-PIC: # %bb.0: -; LARGE-PIC-NEXT: .L15$pb: -; LARGE-PIC-NEXT: leaq .L15$pb(%rip), %rax -; LARGE-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L15$pb, %rcx +; LARGE-PIC-NEXT: .L16$pb: +; LARGE-PIC-NEXT: leaq .L16$pb(%rip), %rax +; LARGE-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L16$pb, %rcx ; LARGE-PIC-NEXT: addq %rax, %rcx ; LARGE-PIC-NEXT: movabsq $__stop_foo@GOTOFF, %rax ; LARGE-PIC-NEXT: addq %rcx, %rax @@ -964,9 +1023,9 @@ define dso_local ptr @lea_stop_foo() #0 { ; ; LARGE-SMALL-DATA-PIC-LABEL: lea_stop_foo: ; LARGE-SMALL-DATA-PIC: # %bb.0: -; LARGE-SMALL-DATA-PIC-NEXT: .L15$pb: -; LARGE-SMALL-DATA-PIC-NEXT: leaq .L15$pb(%rip), %rax -; LARGE-SMALL-DATA-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L15$pb, %rcx +; LARGE-SMALL-DATA-PIC-NEXT: .L16$pb: +; LARGE-SMALL-DATA-PIC-NEXT: leaq .L16$pb(%rip), %rax +; LARGE-SMALL-DATA-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L16$pb, %rcx ; LARGE-SMALL-DATA-PIC-NEXT: addq %rax, %rcx ; LARGE-SMALL-DATA-PIC-NEXT: movabsq $__stop_foo@GOTOFF, %rax ; LARGE-SMALL-DATA-PIC-NEXT: addq %rcx, %rax @@ -1035,9 +1094,9 @@ define dso_local ptr @lea_static_fn() #0 { ; ; LARGE-PIC-LABEL: lea_static_fn: ; LARGE-PIC: # %bb.0: -; LARGE-PIC-NEXT: .L19$pb: -; LARGE-PIC-NEXT: leaq .L19$pb(%rip), %rax -; LARGE-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L19$pb, %rcx +; LARGE-PIC-NEXT: .L20$pb: +; LARGE-PIC-NEXT: leaq .L20$pb(%rip), %rax +; LARGE-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L20$pb, %rcx ; LARGE-PIC-NEXT: addq %rax, %rcx ; LARGE-PIC-NEXT: movabsq $static_fn@GOTOFF, %rax ; LARGE-PIC-NEXT: addq %rcx, %rax @@ -1045,9 +1104,9 @@ define dso_local ptr @lea_static_fn() #0 { ; ; LARGE-SMALL-DATA-PIC-LABEL: lea_static_fn: ; LARGE-SMALL-DATA-PIC: # %bb.0: -; LARGE-SMALL-DATA-PIC-NEXT: .L19$pb: -; LARGE-SMALL-DATA-PIC-NEXT: leaq .L19$pb(%rip), %rax -; LARGE-SMALL-DATA-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L19$pb, %rcx +; LARGE-SMALL-DATA-PIC-NEXT: .L20$pb: +; LARGE-SMALL-DATA-PIC-NEXT: leaq .L20$pb(%rip), %rax +; LARGE-SMALL-DATA-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L20$pb, %rcx ; LARGE-SMALL-DATA-PIC-NEXT: addq %rax, %rcx ; LARGE-SMALL-DATA-PIC-NEXT: movabsq $static_fn@GOTOFF, %rax ; LARGE-SMALL-DATA-PIC-NEXT: addq %rcx, %rax @@ -1088,9 +1147,9 @@ define dso_local ptr @lea_global_fn() #0 { ; ; LARGE-PIC-LABEL: lea_global_fn: ; LARGE-PIC: # %bb.0: -; LARGE-PIC-NEXT: .L20$pb: -; LARGE-PIC-NEXT: leaq .L20$pb(%rip), %rax -; LARGE-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L20$pb, %rcx +; LARGE-PIC-NEXT: .L21$pb: +; LARGE-PIC-NEXT: leaq .L21$pb(%rip), %rax +; LARGE-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L21$pb, %rcx ; LARGE-PIC-NEXT: addq %rax, %rcx ; LARGE-PIC-NEXT: movabsq $global_fn@GOTOFF, %rax ; LARGE-PIC-NEXT: addq %rcx, %rax @@ -1098,9 +1157,9 @@ define dso_local ptr @lea_global_fn() #0 { ; ; LARGE-SMALL-DATA-PIC-LABEL: lea_global_fn: ; LARGE-SMALL-DATA-PIC: # %bb.0: -; LARGE-SMALL-DATA-PIC-NEXT: .L20$pb: -; LARGE-SMALL-DATA-PIC-NEXT: leaq .L20$pb(%rip), %rax -; LARGE-SMALL-DATA-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L20$pb, %rcx +; LARGE-SMALL-DATA-PIC-NEXT: .L21$pb: +; LARGE-SMALL-DATA-PIC-NEXT: leaq .L21$pb(%rip), %rax +; LARGE-SMALL-DATA-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L21$pb, %rcx ; LARGE-SMALL-DATA-PIC-NEXT: addq %rax, %rcx ; LARGE-SMALL-DATA-PIC-NEXT: movabsq $global_fn@GOTOFF, %rax ; LARGE-SMALL-DATA-PIC-NEXT: addq %rcx, %rax @@ -1141,9 +1200,9 @@ define dso_local ptr @lea_extern_fn() #0 { ; ; LARGE-PIC-LABEL: lea_extern_fn: ; LARGE-PIC: # %bb.0: -; LARGE-PIC-NEXT: .L21$pb: -; LARGE-PIC-NEXT: leaq .L21$pb(%rip), %rax -; LARGE-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L21$pb, %rcx +; LARGE-PIC-NEXT: .L22$pb: +; LARGE-PIC-NEXT: leaq .L22$pb(%rip), %rax +; LARGE-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L22$pb, %rcx ; LARGE-PIC-NEXT: addq %rax, %rcx ; LARGE-PIC-NEXT: movabsq $extern_fn@GOT, %rax ; LARGE-PIC-NEXT: movq (%rcx,%rax), %rax @@ -1151,9 +1210,9 @@ define dso_local ptr @lea_extern_fn() #0 { ; ; LARGE-SMALL-DATA-PIC-LABEL: lea_extern_fn: ; LARGE-SMALL-DATA-PIC: # %bb.0: -; LARGE-SMALL-DATA-PIC-NEXT: .L21$pb: -; LARGE-SMALL-DATA-PIC-NEXT: leaq .L21$pb(%rip), %rax -; LARGE-SMALL-DATA-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L21$pb, %rcx +; LARGE-SMALL-DATA-PIC-NEXT: .L22$pb: +; LARGE-SMALL-DATA-PIC-NEXT: leaq .L22$pb(%rip), %rax +; LARGE-SMALL-DATA-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L22$pb, %rcx ; LARGE-SMALL-DATA-PIC-NEXT: addq %rax, %rcx ; LARGE-SMALL-DATA-PIC-NEXT: movabsq $extern_fn@GOT, %rax ; LARGE-SMALL-DATA-PIC-NEXT: movq (%rcx,%rax), %rax @@ -1194,9 +1253,9 @@ define dso_local ptr @lea_ifunc() #0 { ; ; LARGE-PIC-LABEL: lea_ifunc: ; LARGE-PIC: # %bb.0: -; LARGE-PIC-NEXT: .L22$pb: -; LARGE-PIC-NEXT: leaq .L22$pb(%rip), %rax -; LARGE-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L22$pb, %rcx +; LARGE-PIC-NEXT: .L23$pb: +; LARGE-PIC-NEXT: leaq .L23$pb(%rip), %rax +; LARGE-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L23$pb, %rcx ; LARGE-PIC-NEXT: addq %rax, %rcx ; LARGE-PIC-NEXT: movabsq $ifunc_func@GOT, %rax ; LARGE-PIC-NEXT: movq (%rcx,%rax), %rax @@ -1204,9 +1263,9 @@ define dso_local ptr @lea_ifunc() #0 { ; ; LARGE-SMALL-DATA-PIC-LABEL: lea_ifunc: ; LARGE-SMALL-DATA-PIC: # %bb.0: -; LARGE-SMALL-DATA-PIC-NEXT: .L22$pb: -; LARGE-SMALL-DATA-PIC-NEXT: leaq .L22$pb(%rip), %rax -; LARGE-SMALL-DATA-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L22$pb, %rcx +; LARGE-SMALL-DATA-PIC-NEXT: .L23$pb: +; LARGE-SMALL-DATA-PIC-NEXT: leaq .L23$pb(%rip), %rax +; LARGE-SMALL-DATA-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L23$pb, %rcx ; LARGE-SMALL-DATA-PIC-NEXT: addq %rax, %rcx ; LARGE-SMALL-DATA-PIC-NEXT: movabsq $ifunc_func@GOT, %rax ; LARGE-SMALL-DATA-PIC-NEXT: movq (%rcx,%rax), %rax @@ -1247,9 +1306,9 @@ define dso_local ptr @lea_dso_local_ifunc() #0 { ; ; LARGE-PIC-LABEL: lea_dso_local_ifunc: ; LARGE-PIC: # %bb.0: -; LARGE-PIC-NEXT: .L23$pb: -; LARGE-PIC-NEXT: leaq .L23$pb(%rip), %rax -; LARGE-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L23$pb, %rcx +; LARGE-PIC-NEXT: .L24$pb: +; LARGE-PIC-NEXT: leaq .L24$pb(%rip), %rax +; LARGE-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L24$pb, %rcx ; LARGE-PIC-NEXT: addq %rax, %rcx ; LARGE-PIC-NEXT: movabsq $dso_local_ifunc_func@GOTOFF, %rax ; LARGE-PIC-NEXT: addq %rcx, %rax @@ -1257,9 +1316,9 @@ define dso_local ptr @lea_dso_local_ifunc() #0 { ; ; LARGE-SMALL-DATA-PIC-LABEL: lea_dso_local_ifunc: ; LARGE-SMALL-DATA-PIC: # %bb.0: -; LARGE-SMALL-DATA-PIC-NEXT: .L23$pb: -; LARGE-SMALL-DATA-PIC-NEXT: leaq .L23$pb(%rip), %rax -; LARGE-SMALL-DATA-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L23$pb, %rcx +; LARGE-SMALL-DATA-PIC-NEXT: .L24$pb: +; LARGE-SMALL-DATA-PIC-NEXT: leaq .L24$pb(%rip), %rax +; LARGE-SMALL-DATA-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L24$pb, %rcx ; LARGE-SMALL-DATA-PIC-NEXT: addq %rax, %rcx ; LARGE-SMALL-DATA-PIC-NEXT: movabsq $dso_local_ifunc_func@GOTOFF, %rax ; LARGE-SMALL-DATA-PIC-NEXT: addq %rcx, %rax @@ -1334,9 +1393,9 @@ define dso_local float @load_constant_pool(float %x) #0 { ; ; LARGE-PIC-LABEL: load_constant_pool: ; LARGE-PIC: # %bb.0: -; LARGE-PIC-NEXT: .L25$pb: -; LARGE-PIC-NEXT: leaq .L25$pb(%rip), %rax -; LARGE-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L25$pb, %rcx +; LARGE-PIC-NEXT: .L26$pb: +; LARGE-PIC-NEXT: leaq .L26$pb(%rip), %rax +; LARGE-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L26$pb, %rcx ; LARGE-PIC-NEXT: addq %rax, %rcx ; LARGE-PIC-NEXT: movabsq ${{\.?LCPI[0-9]+_[0-9]+}}@GOTOFF, %rax ; LARGE-PIC-NEXT: addss (%rcx,%rax), %xmm0 @@ -1344,9 +1403,9 @@ define dso_local float @load_constant_pool(float %x) #0 { ; ; LARGE-SMALL-DATA-PIC-LABEL: load_constant_pool: ; LARGE-SMALL-DATA-PIC: # %bb.0: -; LARGE-SMALL-DATA-PIC-NEXT: .L25$pb: -; LARGE-SMALL-DATA-PIC-NEXT: leaq .L25$pb(%rip), %rax -; LARGE-SMALL-DATA-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L25$pb, %rcx +; LARGE-SMALL-DATA-PIC-NEXT: .L26$pb: +; LARGE-SMALL-DATA-PIC-NEXT: leaq .L26$pb(%rip), %rax +; LARGE-SMALL-DATA-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L26$pb, %rcx ; LARGE-SMALL-DATA-PIC-NEXT: addq %rax, %rcx ; LARGE-SMALL-DATA-PIC-NEXT: movabsq ${{\.?LCPI[0-9]+_[0-9]+}}@GOTOFF, %rax ; LARGE-SMALL-DATA-PIC-NEXT: addss (%rcx,%rax), %xmm0 diff --git a/llvm/test/CodeGen/X86/combine-pavg.ll b/llvm/test/CodeGen/X86/combine-pavg.ll index 0743592f3ca11bf42a81bc980170d3949b2b0158..9bb7fec7eeacbe3e6612835c1e0affa47dc47b68 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: 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/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/freeze-binary.ll b/llvm/test/CodeGen/X86/freeze-binary.ll index defd81e6ab7710257bcccf9d7645d7a1c6e036ea..b212e9438e1b52fcb221cea4c24320ceade47b99 100644 --- a/llvm/test/CodeGen/X86/freeze-binary.ll +++ b/llvm/test/CodeGen/X86/freeze-binary.ll @@ -488,6 +488,30 @@ define i32 @freeze_ashr_exact(i32 %a0) nounwind { ret i32 %z } +define i32 @freeze_ashr_exact_extra_use(i32 %a0, ptr %escape) nounwind { +; X86-LABEL: freeze_ashr_exact_extra_use: +; X86: # %bb.0: +; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: sarl $3, %eax +; X86-NEXT: movl %eax, (%ecx) +; X86-NEXT: sarl $6, %eax +; X86-NEXT: retl +; +; X64-LABEL: freeze_ashr_exact_extra_use: +; X64: # %bb.0: +; X64-NEXT: movl %edi, %eax +; X64-NEXT: sarl $3, %eax +; X64-NEXT: movl %eax, (%rsi) +; X64-NEXT: sarl $6, %eax +; X64-NEXT: retq + %x = ashr exact i32 %a0, 3 + %y = freeze i32 %x + %z = ashr i32 %y, 6 + store i32 %x, ptr %escape + ret i32 %z +} + define i32 @freeze_ashr_outofrange(i32 %a0) nounwind { ; X86-LABEL: freeze_ashr_outofrange: ; X86: # %bb.0: @@ -597,6 +621,30 @@ define i32 @freeze_lshr_exact(i32 %a0) nounwind { ret i32 %z } +define i32 @freeze_lshr_exact_extra_use(i32 %a0, ptr %escape) nounwind { +; X86-LABEL: freeze_lshr_exact_extra_use: +; X86: # %bb.0: +; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: shrl $3, %eax +; X86-NEXT: movl %eax, (%ecx) +; X86-NEXT: shrl $5, %eax +; X86-NEXT: retl +; +; X64-LABEL: freeze_lshr_exact_extra_use: +; X64: # %bb.0: +; X64-NEXT: movl %edi, %eax +; X64-NEXT: shrl $3, %eax +; X64-NEXT: movl %eax, (%rsi) +; X64-NEXT: shrl $5, %eax +; X64-NEXT: retq + %x = lshr exact i32 %a0, 3 + %y = freeze i32 %x + %z = lshr i32 %y, 5 + store i32 %x, ptr %escape + ret i32 %z +} + define i32 @freeze_lshr_outofrange(i32 %a0) nounwind { ; X86-LABEL: freeze_lshr_outofrange: ; X86: # %bb.0: 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/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/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/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/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/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/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-i16-stride-7.ll b/llvm/test/CodeGen/X86/vector-interleaved-store-i16-stride-7.ll index 79cc8e49f1fdb1d9e7ec92ca6fa4c7a4721343f8..9e70aef868858c9c0c7600d9ff488c7ea9e405d6 100644 --- a/llvm/test/CodeGen/X86/vector-interleaved-store-i16-stride-7.ll +++ b/llvm/test/CodeGen/X86/vector-interleaved-store-i16-stride-7.ll @@ -821,9 +821,8 @@ define void @store_i16_stride7_vf4(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX512BW-FCP-NEXT: vinserti128 $1, %xmm1, %ymm0, %ymm0 ; AVX512BW-FCP-NEXT: vpmovsxbq {{.*#+}} ymm1 = [0,2,4,0] ; AVX512BW-FCP-NEXT: vpermi2q %ymm3, %ymm0, %ymm1 -; AVX512BW-FCP-NEXT: vinserti64x4 $1, %ymm1, %zmm2, %zmm0 -; AVX512BW-FCP-NEXT: vpmovsxbw {{.*#+}} zmm1 = [0,4,8,12,16,20,24,1,5,9,13,17,21,25,2,6,10,14,18,22,26,3,7,11,15,19,23,27,0,0,0,0] -; AVX512BW-FCP-NEXT: vpermw %zmm0, %zmm1, %zmm0 +; AVX512BW-FCP-NEXT: vpmovsxbw {{.*#+}} zmm0 = [0,4,8,12,32,36,40,1,5,9,13,33,37,41,2,6,10,14,34,38,42,3,7,11,15,35,39,43,0,0,0,0] +; AVX512BW-FCP-NEXT: vpermi2w %zmm1, %zmm2, %zmm0 ; AVX512BW-FCP-NEXT: vextracti32x4 $2, %zmm0, 32(%rax) ; AVX512BW-FCP-NEXT: vextracti32x4 $3, %zmm0, %xmm1 ; AVX512BW-FCP-NEXT: vmovq %xmm1, 48(%rax) @@ -873,9 +872,8 @@ define void @store_i16_stride7_vf4(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX512DQ-BW-FCP-NEXT: vinserti128 $1, %xmm1, %ymm0, %ymm0 ; AVX512DQ-BW-FCP-NEXT: vpmovsxbq {{.*#+}} ymm1 = [0,2,4,0] ; AVX512DQ-BW-FCP-NEXT: vpermi2q %ymm3, %ymm0, %ymm1 -; AVX512DQ-BW-FCP-NEXT: vinserti64x4 $1, %ymm1, %zmm2, %zmm0 -; AVX512DQ-BW-FCP-NEXT: vpmovsxbw {{.*#+}} zmm1 = [0,4,8,12,16,20,24,1,5,9,13,17,21,25,2,6,10,14,18,22,26,3,7,11,15,19,23,27,0,0,0,0] -; AVX512DQ-BW-FCP-NEXT: vpermw %zmm0, %zmm1, %zmm0 +; AVX512DQ-BW-FCP-NEXT: vpmovsxbw {{.*#+}} zmm0 = [0,4,8,12,32,36,40,1,5,9,13,33,37,41,2,6,10,14,34,38,42,3,7,11,15,35,39,43,0,0,0,0] +; AVX512DQ-BW-FCP-NEXT: vpermi2w %zmm1, %zmm2, %zmm0 ; AVX512DQ-BW-FCP-NEXT: vextracti32x4 $2, %zmm0, 32(%rax) ; AVX512DQ-BW-FCP-NEXT: vextracti32x4 $3, %zmm0, %xmm1 ; AVX512DQ-BW-FCP-NEXT: vmovq %xmm1, 48(%rax) diff --git a/llvm/test/CodeGen/X86/vector-interleaved-store-i16-stride-8.ll b/llvm/test/CodeGen/X86/vector-interleaved-store-i16-stride-8.ll index 194b715b6594a6e273a99eaeb9c6ada643f82a1a..32825f291e98b6759aed8cfbf2f31ccd2dc83e3a 100644 --- a/llvm/test/CodeGen/X86/vector-interleaved-store-i16-stride-8.ll +++ b/llvm/test/CodeGen/X86/vector-interleaved-store-i16-stride-8.ll @@ -762,10 +762,9 @@ define void @store_i16_stride8_vf4(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX512BW-NEXT: vpunpcklqdq {{.*#+}} xmm3 = xmm4[0],xmm3[0] ; AVX512BW-NEXT: vinserti128 $1, %xmm3, %ymm2, %ymm2 ; AVX512BW-NEXT: vinserti128 $1, %xmm1, %ymm0, %ymm0 -; AVX512BW-NEXT: vinserti64x4 $1, %ymm2, %zmm0, %zmm0 -; AVX512BW-NEXT: vpmovsxbw {{.*#+}} zmm1 = [0,4,8,12,16,20,24,28,1,5,9,13,17,21,25,29,2,6,10,14,18,22,26,30,3,7,11,15,19,23,27,31] -; AVX512BW-NEXT: vpermw %zmm0, %zmm1, %zmm0 -; AVX512BW-NEXT: vmovdqa64 %zmm0, (%rax) +; AVX512BW-NEXT: vpmovsxbw {{.*#+}} zmm1 = [0,4,8,12,32,36,40,44,1,5,9,13,33,37,41,45,2,6,10,14,34,38,42,46,3,7,11,15,35,39,43,47] +; AVX512BW-NEXT: vpermi2w %zmm2, %zmm0, %zmm1 +; AVX512BW-NEXT: vmovdqa64 %zmm1, (%rax) ; AVX512BW-NEXT: vzeroupper ; AVX512BW-NEXT: retq ; @@ -788,10 +787,9 @@ define void @store_i16_stride8_vf4(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX512BW-FCP-NEXT: vpunpcklqdq {{.*#+}} xmm3 = xmm4[0],xmm3[0] ; AVX512BW-FCP-NEXT: vinserti128 $1, %xmm3, %ymm2, %ymm2 ; AVX512BW-FCP-NEXT: vinserti128 $1, %xmm1, %ymm0, %ymm0 -; AVX512BW-FCP-NEXT: vinserti64x4 $1, %ymm2, %zmm0, %zmm0 -; AVX512BW-FCP-NEXT: vpmovsxbw {{.*#+}} zmm1 = [0,4,8,12,16,20,24,28,1,5,9,13,17,21,25,29,2,6,10,14,18,22,26,30,3,7,11,15,19,23,27,31] -; AVX512BW-FCP-NEXT: vpermw %zmm0, %zmm1, %zmm0 -; AVX512BW-FCP-NEXT: vmovdqa64 %zmm0, (%rax) +; AVX512BW-FCP-NEXT: vpmovsxbw {{.*#+}} zmm1 = [0,4,8,12,32,36,40,44,1,5,9,13,33,37,41,45,2,6,10,14,34,38,42,46,3,7,11,15,35,39,43,47] +; AVX512BW-FCP-NEXT: vpermi2w %zmm2, %zmm0, %zmm1 +; AVX512BW-FCP-NEXT: vmovdqa64 %zmm1, (%rax) ; AVX512BW-FCP-NEXT: vzeroupper ; AVX512BW-FCP-NEXT: retq ; @@ -814,10 +812,9 @@ define void @store_i16_stride8_vf4(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX512DQ-BW-NEXT: vpunpcklqdq {{.*#+}} xmm3 = xmm4[0],xmm3[0] ; AVX512DQ-BW-NEXT: vinserti128 $1, %xmm3, %ymm2, %ymm2 ; AVX512DQ-BW-NEXT: vinserti128 $1, %xmm1, %ymm0, %ymm0 -; AVX512DQ-BW-NEXT: vinserti64x4 $1, %ymm2, %zmm0, %zmm0 -; AVX512DQ-BW-NEXT: vpmovsxbw {{.*#+}} zmm1 = [0,4,8,12,16,20,24,28,1,5,9,13,17,21,25,29,2,6,10,14,18,22,26,30,3,7,11,15,19,23,27,31] -; AVX512DQ-BW-NEXT: vpermw %zmm0, %zmm1, %zmm0 -; AVX512DQ-BW-NEXT: vmovdqa64 %zmm0, (%rax) +; AVX512DQ-BW-NEXT: vpmovsxbw {{.*#+}} zmm1 = [0,4,8,12,32,36,40,44,1,5,9,13,33,37,41,45,2,6,10,14,34,38,42,46,3,7,11,15,35,39,43,47] +; AVX512DQ-BW-NEXT: vpermi2w %zmm2, %zmm0, %zmm1 +; AVX512DQ-BW-NEXT: vmovdqa64 %zmm1, (%rax) ; AVX512DQ-BW-NEXT: vzeroupper ; AVX512DQ-BW-NEXT: retq ; @@ -840,10 +837,9 @@ define void @store_i16_stride8_vf4(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX512DQ-BW-FCP-NEXT: vpunpcklqdq {{.*#+}} xmm3 = xmm4[0],xmm3[0] ; AVX512DQ-BW-FCP-NEXT: vinserti128 $1, %xmm3, %ymm2, %ymm2 ; AVX512DQ-BW-FCP-NEXT: vinserti128 $1, %xmm1, %ymm0, %ymm0 -; AVX512DQ-BW-FCP-NEXT: vinserti64x4 $1, %ymm2, %zmm0, %zmm0 -; AVX512DQ-BW-FCP-NEXT: vpmovsxbw {{.*#+}} zmm1 = [0,4,8,12,16,20,24,28,1,5,9,13,17,21,25,29,2,6,10,14,18,22,26,30,3,7,11,15,19,23,27,31] -; AVX512DQ-BW-FCP-NEXT: vpermw %zmm0, %zmm1, %zmm0 -; AVX512DQ-BW-FCP-NEXT: vmovdqa64 %zmm0, (%rax) +; AVX512DQ-BW-FCP-NEXT: vpmovsxbw {{.*#+}} zmm1 = [0,4,8,12,32,36,40,44,1,5,9,13,33,37,41,45,2,6,10,14,34,38,42,46,3,7,11,15,35,39,43,47] +; AVX512DQ-BW-FCP-NEXT: vpermi2w %zmm2, %zmm0, %zmm1 +; AVX512DQ-BW-FCP-NEXT: vmovdqa64 %zmm1, (%rax) ; AVX512DQ-BW-FCP-NEXT: vzeroupper ; AVX512DQ-BW-FCP-NEXT: retq %in.vec0 = load <4 x i16>, ptr %in.vecptr0, align 64 diff --git a/llvm/test/CodeGen/X86/vector-interleaved-store-i32-stride-7.ll b/llvm/test/CodeGen/X86/vector-interleaved-store-i32-stride-7.ll index 837d990596a5afe0987492adb74ed201e9120ad7..45a76599d3e9d78196ddb8378ccb032d3a2cc239 100644 --- a/llvm/test/CodeGen/X86/vector-interleaved-store-i32-stride-7.ll +++ b/llvm/test/CodeGen/X86/vector-interleaved-store-i32-stride-7.ll @@ -227,9 +227,8 @@ define void @store_i32_stride7_vf2(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX512-FCP-NEXT: vinserti128 $1, %xmm1, %ymm0, %ymm0 ; AVX512-FCP-NEXT: vpmovsxbq {{.*#+}} ymm1 = [0,2,4,0] ; AVX512-FCP-NEXT: vpermi2q %ymm3, %ymm0, %ymm1 -; AVX512-FCP-NEXT: vinserti64x4 $1, %ymm1, %zmm2, %zmm0 -; AVX512-FCP-NEXT: vpmovsxbd {{.*#+}} zmm1 = [0,2,4,6,8,10,12,1,3,5,7,9,11,13,0,0] -; AVX512-FCP-NEXT: vpermd %zmm0, %zmm1, %zmm0 +; AVX512-FCP-NEXT: vpmovsxbd {{.*#+}} zmm0 = [0,2,4,6,16,18,20,1,3,5,7,17,19,21,0,0] +; AVX512-FCP-NEXT: vpermi2d %zmm1, %zmm2, %zmm0 ; AVX512-FCP-NEXT: vextracti32x4 $2, %zmm0, 32(%rax) ; AVX512-FCP-NEXT: vextracti32x4 $3, %zmm0, %xmm1 ; AVX512-FCP-NEXT: vmovq %xmm1, 48(%rax) @@ -279,9 +278,8 @@ define void @store_i32_stride7_vf2(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX512DQ-FCP-NEXT: vinserti128 $1, %xmm1, %ymm0, %ymm0 ; AVX512DQ-FCP-NEXT: vpmovsxbq {{.*#+}} ymm1 = [0,2,4,0] ; AVX512DQ-FCP-NEXT: vpermi2q %ymm3, %ymm0, %ymm1 -; AVX512DQ-FCP-NEXT: vinserti64x4 $1, %ymm1, %zmm2, %zmm0 -; AVX512DQ-FCP-NEXT: vpmovsxbd {{.*#+}} zmm1 = [0,2,4,6,8,10,12,1,3,5,7,9,11,13,0,0] -; AVX512DQ-FCP-NEXT: vpermd %zmm0, %zmm1, %zmm0 +; AVX512DQ-FCP-NEXT: vpmovsxbd {{.*#+}} zmm0 = [0,2,4,6,16,18,20,1,3,5,7,17,19,21,0,0] +; AVX512DQ-FCP-NEXT: vpermi2d %zmm1, %zmm2, %zmm0 ; AVX512DQ-FCP-NEXT: vextracti32x4 $2, %zmm0, 32(%rax) ; AVX512DQ-FCP-NEXT: vextracti32x4 $3, %zmm0, %xmm1 ; AVX512DQ-FCP-NEXT: vmovq %xmm1, 48(%rax) @@ -331,9 +329,8 @@ define void @store_i32_stride7_vf2(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX512BW-FCP-NEXT: vinserti128 $1, %xmm1, %ymm0, %ymm0 ; AVX512BW-FCP-NEXT: vpmovsxbq {{.*#+}} ymm1 = [0,2,4,0] ; AVX512BW-FCP-NEXT: vpermi2q %ymm3, %ymm0, %ymm1 -; AVX512BW-FCP-NEXT: vinserti64x4 $1, %ymm1, %zmm2, %zmm0 -; AVX512BW-FCP-NEXT: vpmovsxbd {{.*#+}} zmm1 = [0,2,4,6,8,10,12,1,3,5,7,9,11,13,0,0] -; AVX512BW-FCP-NEXT: vpermd %zmm0, %zmm1, %zmm0 +; AVX512BW-FCP-NEXT: vpmovsxbd {{.*#+}} zmm0 = [0,2,4,6,16,18,20,1,3,5,7,17,19,21,0,0] +; AVX512BW-FCP-NEXT: vpermi2d %zmm1, %zmm2, %zmm0 ; AVX512BW-FCP-NEXT: vextracti32x4 $2, %zmm0, 32(%rax) ; AVX512BW-FCP-NEXT: vextracti32x4 $3, %zmm0, %xmm1 ; AVX512BW-FCP-NEXT: vmovq %xmm1, 48(%rax) @@ -383,9 +380,8 @@ define void @store_i32_stride7_vf2(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX512DQ-BW-FCP-NEXT: vinserti128 $1, %xmm1, %ymm0, %ymm0 ; AVX512DQ-BW-FCP-NEXT: vpmovsxbq {{.*#+}} ymm1 = [0,2,4,0] ; AVX512DQ-BW-FCP-NEXT: vpermi2q %ymm3, %ymm0, %ymm1 -; AVX512DQ-BW-FCP-NEXT: vinserti64x4 $1, %ymm1, %zmm2, %zmm0 -; AVX512DQ-BW-FCP-NEXT: vpmovsxbd {{.*#+}} zmm1 = [0,2,4,6,8,10,12,1,3,5,7,9,11,13,0,0] -; AVX512DQ-BW-FCP-NEXT: vpermd %zmm0, %zmm1, %zmm0 +; AVX512DQ-BW-FCP-NEXT: vpmovsxbd {{.*#+}} zmm0 = [0,2,4,6,16,18,20,1,3,5,7,17,19,21,0,0] +; AVX512DQ-BW-FCP-NEXT: vpermi2d %zmm1, %zmm2, %zmm0 ; AVX512DQ-BW-FCP-NEXT: vextracti32x4 $2, %zmm0, 32(%rax) ; AVX512DQ-BW-FCP-NEXT: vextracti32x4 $3, %zmm0, %xmm1 ; AVX512DQ-BW-FCP-NEXT: vmovq %xmm1, 48(%rax) diff --git a/llvm/test/CodeGen/X86/vector-interleaved-store-i32-stride-8.ll b/llvm/test/CodeGen/X86/vector-interleaved-store-i32-stride-8.ll index 955927eb769126b1eb486f041cf68e001b57bb1c..265f6daeb2003829b972943b8284a35976088e83 100644 --- a/llvm/test/CodeGen/X86/vector-interleaved-store-i32-stride-8.ll +++ b/llvm/test/CodeGen/X86/vector-interleaved-store-i32-stride-8.ll @@ -160,24 +160,23 @@ define void @store_i32_stride8_vf2(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX512-NEXT: movq {{[0-9]+}}(%rsp), %rax ; AVX512-NEXT: movq {{[0-9]+}}(%rsp), %r10 ; AVX512-NEXT: movq {{[0-9]+}}(%rsp), %r11 -; AVX512-NEXT: vmovsd {{.*#+}} xmm0 = mem[0],zero -; AVX512-NEXT: vmovsd {{.*#+}} xmm1 = mem[0],zero -; AVX512-NEXT: vmovlhps {{.*#+}} xmm0 = xmm1[0],xmm0[0] -; AVX512-NEXT: vmovsd {{.*#+}} xmm1 = mem[0],zero -; AVX512-NEXT: vmovsd {{.*#+}} xmm2 = mem[0],zero -; AVX512-NEXT: vmovlhps {{.*#+}} xmm1 = xmm2[0],xmm1[0] -; AVX512-NEXT: vmovsd {{.*#+}} xmm2 = mem[0],zero -; AVX512-NEXT: vmovsd {{.*#+}} xmm3 = mem[0],zero -; AVX512-NEXT: vmovlhps {{.*#+}} xmm2 = xmm3[0],xmm2[0] -; AVX512-NEXT: vmovsd {{.*#+}} xmm3 = mem[0],zero -; AVX512-NEXT: vmovsd {{.*#+}} xmm4 = mem[0],zero -; AVX512-NEXT: vmovlhps {{.*#+}} xmm3 = xmm4[0],xmm3[0] -; AVX512-NEXT: vinsertf128 $1, %xmm3, %ymm2, %ymm2 -; AVX512-NEXT: vinsertf128 $1, %xmm1, %ymm0, %ymm0 -; AVX512-NEXT: vinsertf64x4 $1, %ymm2, %zmm0, %zmm0 -; AVX512-NEXT: vmovaps {{.*#+}} zmm1 = [0,2,4,6,8,10,12,14,1,3,5,7,9,11,13,15] -; AVX512-NEXT: vpermps %zmm0, %zmm1, %zmm0 -; AVX512-NEXT: vmovaps %zmm0, (%rax) +; AVX512-NEXT: vmovq {{.*#+}} xmm0 = mem[0],zero +; AVX512-NEXT: vmovq {{.*#+}} xmm1 = mem[0],zero +; AVX512-NEXT: vpunpcklqdq {{.*#+}} xmm0 = xmm1[0],xmm0[0] +; AVX512-NEXT: vmovq {{.*#+}} xmm1 = mem[0],zero +; AVX512-NEXT: vmovq {{.*#+}} xmm2 = mem[0],zero +; AVX512-NEXT: vpunpcklqdq {{.*#+}} xmm1 = xmm2[0],xmm1[0] +; AVX512-NEXT: vmovq {{.*#+}} xmm2 = mem[0],zero +; AVX512-NEXT: vmovq {{.*#+}} xmm3 = mem[0],zero +; AVX512-NEXT: vpunpcklqdq {{.*#+}} xmm2 = xmm3[0],xmm2[0] +; AVX512-NEXT: vmovq {{.*#+}} xmm3 = mem[0],zero +; AVX512-NEXT: vmovq {{.*#+}} xmm4 = mem[0],zero +; AVX512-NEXT: vpunpcklqdq {{.*#+}} xmm3 = xmm4[0],xmm3[0] +; AVX512-NEXT: vinserti128 $1, %xmm3, %ymm2, %ymm2 +; AVX512-NEXT: vinserti128 $1, %xmm1, %ymm0, %ymm0 +; AVX512-NEXT: vpmovsxbd {{.*#+}} zmm1 = [0,2,4,6,16,18,20,22,1,3,5,7,17,19,21,23] +; AVX512-NEXT: vpermi2d %zmm2, %zmm0, %zmm1 +; AVX512-NEXT: vmovdqa64 %zmm1, (%rax) ; AVX512-NEXT: vzeroupper ; AVX512-NEXT: retq ; @@ -186,24 +185,23 @@ define void @store_i32_stride8_vf2(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX512-FCP-NEXT: movq {{[0-9]+}}(%rsp), %rax ; AVX512-FCP-NEXT: movq {{[0-9]+}}(%rsp), %r10 ; AVX512-FCP-NEXT: movq {{[0-9]+}}(%rsp), %r11 -; AVX512-FCP-NEXT: vmovsd {{.*#+}} xmm0 = mem[0],zero -; AVX512-FCP-NEXT: vmovsd {{.*#+}} xmm1 = mem[0],zero -; AVX512-FCP-NEXT: vmovlhps {{.*#+}} xmm0 = xmm1[0],xmm0[0] -; AVX512-FCP-NEXT: vmovsd {{.*#+}} xmm1 = mem[0],zero -; AVX512-FCP-NEXT: vmovsd {{.*#+}} xmm2 = mem[0],zero -; AVX512-FCP-NEXT: vmovlhps {{.*#+}} xmm1 = xmm2[0],xmm1[0] -; AVX512-FCP-NEXT: vmovsd {{.*#+}} xmm2 = mem[0],zero -; AVX512-FCP-NEXT: vmovsd {{.*#+}} xmm3 = mem[0],zero -; AVX512-FCP-NEXT: vmovlhps {{.*#+}} xmm2 = xmm3[0],xmm2[0] -; AVX512-FCP-NEXT: vmovsd {{.*#+}} xmm3 = mem[0],zero -; AVX512-FCP-NEXT: vmovsd {{.*#+}} xmm4 = mem[0],zero -; AVX512-FCP-NEXT: vmovlhps {{.*#+}} xmm3 = xmm4[0],xmm3[0] -; AVX512-FCP-NEXT: vinsertf128 $1, %xmm3, %ymm2, %ymm2 -; AVX512-FCP-NEXT: vinsertf128 $1, %xmm1, %ymm0, %ymm0 -; AVX512-FCP-NEXT: vinsertf64x4 $1, %ymm2, %zmm0, %zmm0 -; AVX512-FCP-NEXT: vmovaps {{.*#+}} zmm1 = [0,2,4,6,8,10,12,14,1,3,5,7,9,11,13,15] -; AVX512-FCP-NEXT: vpermps %zmm0, %zmm1, %zmm0 -; AVX512-FCP-NEXT: vmovaps %zmm0, (%rax) +; AVX512-FCP-NEXT: vmovq {{.*#+}} xmm0 = mem[0],zero +; AVX512-FCP-NEXT: vmovq {{.*#+}} xmm1 = mem[0],zero +; AVX512-FCP-NEXT: vpunpcklqdq {{.*#+}} xmm0 = xmm1[0],xmm0[0] +; AVX512-FCP-NEXT: vmovq {{.*#+}} xmm1 = mem[0],zero +; AVX512-FCP-NEXT: vmovq {{.*#+}} xmm2 = mem[0],zero +; AVX512-FCP-NEXT: vpunpcklqdq {{.*#+}} xmm1 = xmm2[0],xmm1[0] +; AVX512-FCP-NEXT: vmovq {{.*#+}} xmm2 = mem[0],zero +; AVX512-FCP-NEXT: vmovq {{.*#+}} xmm3 = mem[0],zero +; AVX512-FCP-NEXT: vpunpcklqdq {{.*#+}} xmm2 = xmm3[0],xmm2[0] +; AVX512-FCP-NEXT: vmovq {{.*#+}} xmm3 = mem[0],zero +; AVX512-FCP-NEXT: vmovq {{.*#+}} xmm4 = mem[0],zero +; AVX512-FCP-NEXT: vpunpcklqdq {{.*#+}} xmm3 = xmm4[0],xmm3[0] +; AVX512-FCP-NEXT: vinserti128 $1, %xmm3, %ymm2, %ymm2 +; AVX512-FCP-NEXT: vinserti128 $1, %xmm1, %ymm0, %ymm0 +; AVX512-FCP-NEXT: vpmovsxbd {{.*#+}} zmm1 = [0,2,4,6,16,18,20,22,1,3,5,7,17,19,21,23] +; AVX512-FCP-NEXT: vpermi2d %zmm2, %zmm0, %zmm1 +; AVX512-FCP-NEXT: vmovdqa64 %zmm1, (%rax) ; AVX512-FCP-NEXT: vzeroupper ; AVX512-FCP-NEXT: retq ; @@ -212,24 +210,23 @@ define void @store_i32_stride8_vf2(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX512DQ-NEXT: movq {{[0-9]+}}(%rsp), %rax ; AVX512DQ-NEXT: movq {{[0-9]+}}(%rsp), %r10 ; AVX512DQ-NEXT: movq {{[0-9]+}}(%rsp), %r11 -; AVX512DQ-NEXT: vmovsd {{.*#+}} xmm0 = mem[0],zero -; AVX512DQ-NEXT: vmovsd {{.*#+}} xmm1 = mem[0],zero -; AVX512DQ-NEXT: vmovlhps {{.*#+}} xmm0 = xmm1[0],xmm0[0] -; AVX512DQ-NEXT: vmovsd {{.*#+}} xmm1 = mem[0],zero -; AVX512DQ-NEXT: vmovsd {{.*#+}} xmm2 = mem[0],zero -; AVX512DQ-NEXT: vmovlhps {{.*#+}} xmm1 = xmm2[0],xmm1[0] -; AVX512DQ-NEXT: vmovsd {{.*#+}} xmm2 = mem[0],zero -; AVX512DQ-NEXT: vmovsd {{.*#+}} xmm3 = mem[0],zero -; AVX512DQ-NEXT: vmovlhps {{.*#+}} xmm2 = xmm3[0],xmm2[0] -; AVX512DQ-NEXT: vmovsd {{.*#+}} xmm3 = mem[0],zero -; AVX512DQ-NEXT: vmovsd {{.*#+}} xmm4 = mem[0],zero -; AVX512DQ-NEXT: vmovlhps {{.*#+}} xmm3 = xmm4[0],xmm3[0] -; AVX512DQ-NEXT: vinsertf128 $1, %xmm3, %ymm2, %ymm2 -; AVX512DQ-NEXT: vinsertf128 $1, %xmm1, %ymm0, %ymm0 -; AVX512DQ-NEXT: vinsertf64x4 $1, %ymm2, %zmm0, %zmm0 -; AVX512DQ-NEXT: vmovaps {{.*#+}} zmm1 = [0,2,4,6,8,10,12,14,1,3,5,7,9,11,13,15] -; AVX512DQ-NEXT: vpermps %zmm0, %zmm1, %zmm0 -; AVX512DQ-NEXT: vmovaps %zmm0, (%rax) +; AVX512DQ-NEXT: vmovq {{.*#+}} xmm0 = mem[0],zero +; AVX512DQ-NEXT: vmovq {{.*#+}} xmm1 = mem[0],zero +; AVX512DQ-NEXT: vpunpcklqdq {{.*#+}} xmm0 = xmm1[0],xmm0[0] +; AVX512DQ-NEXT: vmovq {{.*#+}} xmm1 = mem[0],zero +; AVX512DQ-NEXT: vmovq {{.*#+}} xmm2 = mem[0],zero +; AVX512DQ-NEXT: vpunpcklqdq {{.*#+}} xmm1 = xmm2[0],xmm1[0] +; AVX512DQ-NEXT: vmovq {{.*#+}} xmm2 = mem[0],zero +; AVX512DQ-NEXT: vmovq {{.*#+}} xmm3 = mem[0],zero +; AVX512DQ-NEXT: vpunpcklqdq {{.*#+}} xmm2 = xmm3[0],xmm2[0] +; AVX512DQ-NEXT: vmovq {{.*#+}} xmm3 = mem[0],zero +; AVX512DQ-NEXT: vmovq {{.*#+}} xmm4 = mem[0],zero +; AVX512DQ-NEXT: vpunpcklqdq {{.*#+}} xmm3 = xmm4[0],xmm3[0] +; AVX512DQ-NEXT: vinserti128 $1, %xmm3, %ymm2, %ymm2 +; AVX512DQ-NEXT: vinserti128 $1, %xmm1, %ymm0, %ymm0 +; AVX512DQ-NEXT: vpmovsxbd {{.*#+}} zmm1 = [0,2,4,6,16,18,20,22,1,3,5,7,17,19,21,23] +; AVX512DQ-NEXT: vpermi2d %zmm2, %zmm0, %zmm1 +; AVX512DQ-NEXT: vmovdqa64 %zmm1, (%rax) ; AVX512DQ-NEXT: vzeroupper ; AVX512DQ-NEXT: retq ; @@ -238,24 +235,23 @@ define void @store_i32_stride8_vf2(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX512DQ-FCP-NEXT: movq {{[0-9]+}}(%rsp), %rax ; AVX512DQ-FCP-NEXT: movq {{[0-9]+}}(%rsp), %r10 ; AVX512DQ-FCP-NEXT: movq {{[0-9]+}}(%rsp), %r11 -; AVX512DQ-FCP-NEXT: vmovsd {{.*#+}} xmm0 = mem[0],zero -; AVX512DQ-FCP-NEXT: vmovsd {{.*#+}} xmm1 = mem[0],zero -; AVX512DQ-FCP-NEXT: vmovlhps {{.*#+}} xmm0 = xmm1[0],xmm0[0] -; AVX512DQ-FCP-NEXT: vmovsd {{.*#+}} xmm1 = mem[0],zero -; AVX512DQ-FCP-NEXT: vmovsd {{.*#+}} xmm2 = mem[0],zero -; AVX512DQ-FCP-NEXT: vmovlhps {{.*#+}} xmm1 = xmm2[0],xmm1[0] -; AVX512DQ-FCP-NEXT: vmovsd {{.*#+}} xmm2 = mem[0],zero -; AVX512DQ-FCP-NEXT: vmovsd {{.*#+}} xmm3 = mem[0],zero -; AVX512DQ-FCP-NEXT: vmovlhps {{.*#+}} xmm2 = xmm3[0],xmm2[0] -; AVX512DQ-FCP-NEXT: vmovsd {{.*#+}} xmm3 = mem[0],zero -; AVX512DQ-FCP-NEXT: vmovsd {{.*#+}} xmm4 = mem[0],zero -; AVX512DQ-FCP-NEXT: vmovlhps {{.*#+}} xmm3 = xmm4[0],xmm3[0] -; AVX512DQ-FCP-NEXT: vinsertf128 $1, %xmm3, %ymm2, %ymm2 -; AVX512DQ-FCP-NEXT: vinsertf128 $1, %xmm1, %ymm0, %ymm0 -; AVX512DQ-FCP-NEXT: vinsertf64x4 $1, %ymm2, %zmm0, %zmm0 -; AVX512DQ-FCP-NEXT: vmovaps {{.*#+}} zmm1 = [0,2,4,6,8,10,12,14,1,3,5,7,9,11,13,15] -; AVX512DQ-FCP-NEXT: vpermps %zmm0, %zmm1, %zmm0 -; AVX512DQ-FCP-NEXT: vmovaps %zmm0, (%rax) +; AVX512DQ-FCP-NEXT: vmovq {{.*#+}} xmm0 = mem[0],zero +; AVX512DQ-FCP-NEXT: vmovq {{.*#+}} xmm1 = mem[0],zero +; AVX512DQ-FCP-NEXT: vpunpcklqdq {{.*#+}} xmm0 = xmm1[0],xmm0[0] +; AVX512DQ-FCP-NEXT: vmovq {{.*#+}} xmm1 = mem[0],zero +; AVX512DQ-FCP-NEXT: vmovq {{.*#+}} xmm2 = mem[0],zero +; AVX512DQ-FCP-NEXT: vpunpcklqdq {{.*#+}} xmm1 = xmm2[0],xmm1[0] +; AVX512DQ-FCP-NEXT: vmovq {{.*#+}} xmm2 = mem[0],zero +; AVX512DQ-FCP-NEXT: vmovq {{.*#+}} xmm3 = mem[0],zero +; AVX512DQ-FCP-NEXT: vpunpcklqdq {{.*#+}} xmm2 = xmm3[0],xmm2[0] +; AVX512DQ-FCP-NEXT: vmovq {{.*#+}} xmm3 = mem[0],zero +; AVX512DQ-FCP-NEXT: vmovq {{.*#+}} xmm4 = mem[0],zero +; AVX512DQ-FCP-NEXT: vpunpcklqdq {{.*#+}} xmm3 = xmm4[0],xmm3[0] +; AVX512DQ-FCP-NEXT: vinserti128 $1, %xmm3, %ymm2, %ymm2 +; AVX512DQ-FCP-NEXT: vinserti128 $1, %xmm1, %ymm0, %ymm0 +; AVX512DQ-FCP-NEXT: vpmovsxbd {{.*#+}} zmm1 = [0,2,4,6,16,18,20,22,1,3,5,7,17,19,21,23] +; AVX512DQ-FCP-NEXT: vpermi2d %zmm2, %zmm0, %zmm1 +; AVX512DQ-FCP-NEXT: vmovdqa64 %zmm1, (%rax) ; AVX512DQ-FCP-NEXT: vzeroupper ; AVX512DQ-FCP-NEXT: retq ; @@ -264,24 +260,23 @@ define void @store_i32_stride8_vf2(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX512BW-NEXT: movq {{[0-9]+}}(%rsp), %rax ; AVX512BW-NEXT: movq {{[0-9]+}}(%rsp), %r10 ; AVX512BW-NEXT: movq {{[0-9]+}}(%rsp), %r11 -; AVX512BW-NEXT: vmovsd {{.*#+}} xmm0 = mem[0],zero -; AVX512BW-NEXT: vmovsd {{.*#+}} xmm1 = mem[0],zero -; AVX512BW-NEXT: vmovlhps {{.*#+}} xmm0 = xmm1[0],xmm0[0] -; AVX512BW-NEXT: vmovsd {{.*#+}} xmm1 = mem[0],zero -; AVX512BW-NEXT: vmovsd {{.*#+}} xmm2 = mem[0],zero -; AVX512BW-NEXT: vmovlhps {{.*#+}} xmm1 = xmm2[0],xmm1[0] -; AVX512BW-NEXT: vmovsd {{.*#+}} xmm2 = mem[0],zero -; AVX512BW-NEXT: vmovsd {{.*#+}} xmm3 = mem[0],zero -; AVX512BW-NEXT: vmovlhps {{.*#+}} xmm2 = xmm3[0],xmm2[0] -; AVX512BW-NEXT: vmovsd {{.*#+}} xmm3 = mem[0],zero -; AVX512BW-NEXT: vmovsd {{.*#+}} xmm4 = mem[0],zero -; AVX512BW-NEXT: vmovlhps {{.*#+}} xmm3 = xmm4[0],xmm3[0] -; AVX512BW-NEXT: vinsertf128 $1, %xmm3, %ymm2, %ymm2 -; AVX512BW-NEXT: vinsertf128 $1, %xmm1, %ymm0, %ymm0 -; AVX512BW-NEXT: vinsertf64x4 $1, %ymm2, %zmm0, %zmm0 -; AVX512BW-NEXT: vmovaps {{.*#+}} zmm1 = [0,2,4,6,8,10,12,14,1,3,5,7,9,11,13,15] -; AVX512BW-NEXT: vpermps %zmm0, %zmm1, %zmm0 -; AVX512BW-NEXT: vmovaps %zmm0, (%rax) +; AVX512BW-NEXT: vmovq {{.*#+}} xmm0 = mem[0],zero +; AVX512BW-NEXT: vmovq {{.*#+}} xmm1 = mem[0],zero +; AVX512BW-NEXT: vpunpcklqdq {{.*#+}} xmm0 = xmm1[0],xmm0[0] +; AVX512BW-NEXT: vmovq {{.*#+}} xmm1 = mem[0],zero +; AVX512BW-NEXT: vmovq {{.*#+}} xmm2 = mem[0],zero +; AVX512BW-NEXT: vpunpcklqdq {{.*#+}} xmm1 = xmm2[0],xmm1[0] +; AVX512BW-NEXT: vmovq {{.*#+}} xmm2 = mem[0],zero +; AVX512BW-NEXT: vmovq {{.*#+}} xmm3 = mem[0],zero +; AVX512BW-NEXT: vpunpcklqdq {{.*#+}} xmm2 = xmm3[0],xmm2[0] +; AVX512BW-NEXT: vmovq {{.*#+}} xmm3 = mem[0],zero +; AVX512BW-NEXT: vmovq {{.*#+}} xmm4 = mem[0],zero +; AVX512BW-NEXT: vpunpcklqdq {{.*#+}} xmm3 = xmm4[0],xmm3[0] +; AVX512BW-NEXT: vinserti128 $1, %xmm3, %ymm2, %ymm2 +; AVX512BW-NEXT: vinserti128 $1, %xmm1, %ymm0, %ymm0 +; AVX512BW-NEXT: vpmovsxbd {{.*#+}} zmm1 = [0,2,4,6,16,18,20,22,1,3,5,7,17,19,21,23] +; AVX512BW-NEXT: vpermi2d %zmm2, %zmm0, %zmm1 +; AVX512BW-NEXT: vmovdqa64 %zmm1, (%rax) ; AVX512BW-NEXT: vzeroupper ; AVX512BW-NEXT: retq ; @@ -290,24 +285,23 @@ define void @store_i32_stride8_vf2(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX512BW-FCP-NEXT: movq {{[0-9]+}}(%rsp), %rax ; AVX512BW-FCP-NEXT: movq {{[0-9]+}}(%rsp), %r10 ; AVX512BW-FCP-NEXT: movq {{[0-9]+}}(%rsp), %r11 -; AVX512BW-FCP-NEXT: vmovsd {{.*#+}} xmm0 = mem[0],zero -; AVX512BW-FCP-NEXT: vmovsd {{.*#+}} xmm1 = mem[0],zero -; AVX512BW-FCP-NEXT: vmovlhps {{.*#+}} xmm0 = xmm1[0],xmm0[0] -; AVX512BW-FCP-NEXT: vmovsd {{.*#+}} xmm1 = mem[0],zero -; AVX512BW-FCP-NEXT: vmovsd {{.*#+}} xmm2 = mem[0],zero -; AVX512BW-FCP-NEXT: vmovlhps {{.*#+}} xmm1 = xmm2[0],xmm1[0] -; AVX512BW-FCP-NEXT: vmovsd {{.*#+}} xmm2 = mem[0],zero -; AVX512BW-FCP-NEXT: vmovsd {{.*#+}} xmm3 = mem[0],zero -; AVX512BW-FCP-NEXT: vmovlhps {{.*#+}} xmm2 = xmm3[0],xmm2[0] -; AVX512BW-FCP-NEXT: vmovsd {{.*#+}} xmm3 = mem[0],zero -; AVX512BW-FCP-NEXT: vmovsd {{.*#+}} xmm4 = mem[0],zero -; AVX512BW-FCP-NEXT: vmovlhps {{.*#+}} xmm3 = xmm4[0],xmm3[0] -; AVX512BW-FCP-NEXT: vinsertf128 $1, %xmm3, %ymm2, %ymm2 -; AVX512BW-FCP-NEXT: vinsertf128 $1, %xmm1, %ymm0, %ymm0 -; AVX512BW-FCP-NEXT: vinsertf64x4 $1, %ymm2, %zmm0, %zmm0 -; AVX512BW-FCP-NEXT: vmovaps {{.*#+}} zmm1 = [0,2,4,6,8,10,12,14,1,3,5,7,9,11,13,15] -; AVX512BW-FCP-NEXT: vpermps %zmm0, %zmm1, %zmm0 -; AVX512BW-FCP-NEXT: vmovaps %zmm0, (%rax) +; AVX512BW-FCP-NEXT: vmovq {{.*#+}} xmm0 = mem[0],zero +; AVX512BW-FCP-NEXT: vmovq {{.*#+}} xmm1 = mem[0],zero +; AVX512BW-FCP-NEXT: vpunpcklqdq {{.*#+}} xmm0 = xmm1[0],xmm0[0] +; AVX512BW-FCP-NEXT: vmovq {{.*#+}} xmm1 = mem[0],zero +; AVX512BW-FCP-NEXT: vmovq {{.*#+}} xmm2 = mem[0],zero +; AVX512BW-FCP-NEXT: vpunpcklqdq {{.*#+}} xmm1 = xmm2[0],xmm1[0] +; AVX512BW-FCP-NEXT: vmovq {{.*#+}} xmm2 = mem[0],zero +; AVX512BW-FCP-NEXT: vmovq {{.*#+}} xmm3 = mem[0],zero +; AVX512BW-FCP-NEXT: vpunpcklqdq {{.*#+}} xmm2 = xmm3[0],xmm2[0] +; AVX512BW-FCP-NEXT: vmovq {{.*#+}} xmm3 = mem[0],zero +; AVX512BW-FCP-NEXT: vmovq {{.*#+}} xmm4 = mem[0],zero +; AVX512BW-FCP-NEXT: vpunpcklqdq {{.*#+}} xmm3 = xmm4[0],xmm3[0] +; AVX512BW-FCP-NEXT: vinserti128 $1, %xmm3, %ymm2, %ymm2 +; AVX512BW-FCP-NEXT: vinserti128 $1, %xmm1, %ymm0, %ymm0 +; AVX512BW-FCP-NEXT: vpmovsxbd {{.*#+}} zmm1 = [0,2,4,6,16,18,20,22,1,3,5,7,17,19,21,23] +; AVX512BW-FCP-NEXT: vpermi2d %zmm2, %zmm0, %zmm1 +; AVX512BW-FCP-NEXT: vmovdqa64 %zmm1, (%rax) ; AVX512BW-FCP-NEXT: vzeroupper ; AVX512BW-FCP-NEXT: retq ; @@ -316,24 +310,23 @@ define void @store_i32_stride8_vf2(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX512DQ-BW-NEXT: movq {{[0-9]+}}(%rsp), %rax ; AVX512DQ-BW-NEXT: movq {{[0-9]+}}(%rsp), %r10 ; AVX512DQ-BW-NEXT: movq {{[0-9]+}}(%rsp), %r11 -; AVX512DQ-BW-NEXT: vmovsd {{.*#+}} xmm0 = mem[0],zero -; AVX512DQ-BW-NEXT: vmovsd {{.*#+}} xmm1 = mem[0],zero -; AVX512DQ-BW-NEXT: vmovlhps {{.*#+}} xmm0 = xmm1[0],xmm0[0] -; AVX512DQ-BW-NEXT: vmovsd {{.*#+}} xmm1 = mem[0],zero -; AVX512DQ-BW-NEXT: vmovsd {{.*#+}} xmm2 = mem[0],zero -; AVX512DQ-BW-NEXT: vmovlhps {{.*#+}} xmm1 = xmm2[0],xmm1[0] -; AVX512DQ-BW-NEXT: vmovsd {{.*#+}} xmm2 = mem[0],zero -; AVX512DQ-BW-NEXT: vmovsd {{.*#+}} xmm3 = mem[0],zero -; AVX512DQ-BW-NEXT: vmovlhps {{.*#+}} xmm2 = xmm3[0],xmm2[0] -; AVX512DQ-BW-NEXT: vmovsd {{.*#+}} xmm3 = mem[0],zero -; AVX512DQ-BW-NEXT: vmovsd {{.*#+}} xmm4 = mem[0],zero -; AVX512DQ-BW-NEXT: vmovlhps {{.*#+}} xmm3 = xmm4[0],xmm3[0] -; AVX512DQ-BW-NEXT: vinsertf128 $1, %xmm3, %ymm2, %ymm2 -; AVX512DQ-BW-NEXT: vinsertf128 $1, %xmm1, %ymm0, %ymm0 -; AVX512DQ-BW-NEXT: vinsertf64x4 $1, %ymm2, %zmm0, %zmm0 -; AVX512DQ-BW-NEXT: vmovaps {{.*#+}} zmm1 = [0,2,4,6,8,10,12,14,1,3,5,7,9,11,13,15] -; AVX512DQ-BW-NEXT: vpermps %zmm0, %zmm1, %zmm0 -; AVX512DQ-BW-NEXT: vmovaps %zmm0, (%rax) +; AVX512DQ-BW-NEXT: vmovq {{.*#+}} xmm0 = mem[0],zero +; AVX512DQ-BW-NEXT: vmovq {{.*#+}} xmm1 = mem[0],zero +; AVX512DQ-BW-NEXT: vpunpcklqdq {{.*#+}} xmm0 = xmm1[0],xmm0[0] +; AVX512DQ-BW-NEXT: vmovq {{.*#+}} xmm1 = mem[0],zero +; AVX512DQ-BW-NEXT: vmovq {{.*#+}} xmm2 = mem[0],zero +; AVX512DQ-BW-NEXT: vpunpcklqdq {{.*#+}} xmm1 = xmm2[0],xmm1[0] +; AVX512DQ-BW-NEXT: vmovq {{.*#+}} xmm2 = mem[0],zero +; AVX512DQ-BW-NEXT: vmovq {{.*#+}} xmm3 = mem[0],zero +; AVX512DQ-BW-NEXT: vpunpcklqdq {{.*#+}} xmm2 = xmm3[0],xmm2[0] +; AVX512DQ-BW-NEXT: vmovq {{.*#+}} xmm3 = mem[0],zero +; AVX512DQ-BW-NEXT: vmovq {{.*#+}} xmm4 = mem[0],zero +; AVX512DQ-BW-NEXT: vpunpcklqdq {{.*#+}} xmm3 = xmm4[0],xmm3[0] +; AVX512DQ-BW-NEXT: vinserti128 $1, %xmm3, %ymm2, %ymm2 +; AVX512DQ-BW-NEXT: vinserti128 $1, %xmm1, %ymm0, %ymm0 +; AVX512DQ-BW-NEXT: vpmovsxbd {{.*#+}} zmm1 = [0,2,4,6,16,18,20,22,1,3,5,7,17,19,21,23] +; AVX512DQ-BW-NEXT: vpermi2d %zmm2, %zmm0, %zmm1 +; AVX512DQ-BW-NEXT: vmovdqa64 %zmm1, (%rax) ; AVX512DQ-BW-NEXT: vzeroupper ; AVX512DQ-BW-NEXT: retq ; @@ -342,24 +335,23 @@ define void @store_i32_stride8_vf2(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX512DQ-BW-FCP-NEXT: movq {{[0-9]+}}(%rsp), %rax ; AVX512DQ-BW-FCP-NEXT: movq {{[0-9]+}}(%rsp), %r10 ; AVX512DQ-BW-FCP-NEXT: movq {{[0-9]+}}(%rsp), %r11 -; AVX512DQ-BW-FCP-NEXT: vmovsd {{.*#+}} xmm0 = mem[0],zero -; AVX512DQ-BW-FCP-NEXT: vmovsd {{.*#+}} xmm1 = mem[0],zero -; AVX512DQ-BW-FCP-NEXT: vmovlhps {{.*#+}} xmm0 = xmm1[0],xmm0[0] -; AVX512DQ-BW-FCP-NEXT: vmovsd {{.*#+}} xmm1 = mem[0],zero -; AVX512DQ-BW-FCP-NEXT: vmovsd {{.*#+}} xmm2 = mem[0],zero -; AVX512DQ-BW-FCP-NEXT: vmovlhps {{.*#+}} xmm1 = xmm2[0],xmm1[0] -; AVX512DQ-BW-FCP-NEXT: vmovsd {{.*#+}} xmm2 = mem[0],zero -; AVX512DQ-BW-FCP-NEXT: vmovsd {{.*#+}} xmm3 = mem[0],zero -; AVX512DQ-BW-FCP-NEXT: vmovlhps {{.*#+}} xmm2 = xmm3[0],xmm2[0] -; AVX512DQ-BW-FCP-NEXT: vmovsd {{.*#+}} xmm3 = mem[0],zero -; AVX512DQ-BW-FCP-NEXT: vmovsd {{.*#+}} xmm4 = mem[0],zero -; AVX512DQ-BW-FCP-NEXT: vmovlhps {{.*#+}} xmm3 = xmm4[0],xmm3[0] -; AVX512DQ-BW-FCP-NEXT: vinsertf128 $1, %xmm3, %ymm2, %ymm2 -; AVX512DQ-BW-FCP-NEXT: vinsertf128 $1, %xmm1, %ymm0, %ymm0 -; AVX512DQ-BW-FCP-NEXT: vinsertf64x4 $1, %ymm2, %zmm0, %zmm0 -; AVX512DQ-BW-FCP-NEXT: vmovaps {{.*#+}} zmm1 = [0,2,4,6,8,10,12,14,1,3,5,7,9,11,13,15] -; AVX512DQ-BW-FCP-NEXT: vpermps %zmm0, %zmm1, %zmm0 -; AVX512DQ-BW-FCP-NEXT: vmovaps %zmm0, (%rax) +; AVX512DQ-BW-FCP-NEXT: vmovq {{.*#+}} xmm0 = mem[0],zero +; AVX512DQ-BW-FCP-NEXT: vmovq {{.*#+}} xmm1 = mem[0],zero +; AVX512DQ-BW-FCP-NEXT: vpunpcklqdq {{.*#+}} xmm0 = xmm1[0],xmm0[0] +; AVX512DQ-BW-FCP-NEXT: vmovq {{.*#+}} xmm1 = mem[0],zero +; AVX512DQ-BW-FCP-NEXT: vmovq {{.*#+}} xmm2 = mem[0],zero +; AVX512DQ-BW-FCP-NEXT: vpunpcklqdq {{.*#+}} xmm1 = xmm2[0],xmm1[0] +; AVX512DQ-BW-FCP-NEXT: vmovq {{.*#+}} xmm2 = mem[0],zero +; AVX512DQ-BW-FCP-NEXT: vmovq {{.*#+}} xmm3 = mem[0],zero +; AVX512DQ-BW-FCP-NEXT: vpunpcklqdq {{.*#+}} xmm2 = xmm3[0],xmm2[0] +; AVX512DQ-BW-FCP-NEXT: vmovq {{.*#+}} xmm3 = mem[0],zero +; AVX512DQ-BW-FCP-NEXT: vmovq {{.*#+}} xmm4 = mem[0],zero +; AVX512DQ-BW-FCP-NEXT: vpunpcklqdq {{.*#+}} xmm3 = xmm4[0],xmm3[0] +; AVX512DQ-BW-FCP-NEXT: vinserti128 $1, %xmm3, %ymm2, %ymm2 +; AVX512DQ-BW-FCP-NEXT: vinserti128 $1, %xmm1, %ymm0, %ymm0 +; AVX512DQ-BW-FCP-NEXT: vpmovsxbd {{.*#+}} zmm1 = [0,2,4,6,16,18,20,22,1,3,5,7,17,19,21,23] +; AVX512DQ-BW-FCP-NEXT: vpermi2d %zmm2, %zmm0, %zmm1 +; AVX512DQ-BW-FCP-NEXT: vmovdqa64 %zmm1, (%rax) ; AVX512DQ-BW-FCP-NEXT: vzeroupper ; AVX512DQ-BW-FCP-NEXT: retq %in.vec0 = load <2 x i32>, ptr %in.vecptr0, align 64 diff --git a/llvm/test/CodeGen/X86/vector-interleaved-store-i64-stride-4.ll b/llvm/test/CodeGen/X86/vector-interleaved-store-i64-stride-4.ll index 38623c6ce0cb054d123a40669756afe3967ae409..ded7c002c8735b69bf28d1b86910981e4c2dfc8b 100644 --- a/llvm/test/CodeGen/X86/vector-interleaved-store-i64-stride-4.ll +++ b/llvm/test/CodeGen/X86/vector-interleaved-store-i64-stride-4.ll @@ -94,105 +94,97 @@ define void @store_i64_stride4_vf2(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; ; AVX512-LABEL: store_i64_stride4_vf2: ; AVX512: # %bb.0: -; AVX512-NEXT: vmovaps (%rdi), %xmm0 -; AVX512-NEXT: vmovaps (%rdx), %xmm1 -; AVX512-NEXT: vinsertf128 $1, (%rcx), %ymm1, %ymm1 -; AVX512-NEXT: vinsertf128 $1, (%rsi), %ymm0, %ymm0 -; AVX512-NEXT: vinsertf64x4 $1, %ymm1, %zmm0, %zmm0 -; AVX512-NEXT: vmovaps {{.*#+}} zmm1 = [0,2,4,6,1,3,5,7] -; AVX512-NEXT: vpermpd %zmm0, %zmm1, %zmm0 -; AVX512-NEXT: vmovaps %zmm0, (%r8) +; AVX512-NEXT: vmovdqa (%rdi), %xmm0 +; AVX512-NEXT: vmovdqa (%rdx), %xmm1 +; AVX512-NEXT: vinserti128 $1, (%rcx), %ymm1, %ymm1 +; AVX512-NEXT: vinserti128 $1, (%rsi), %ymm0, %ymm0 +; AVX512-NEXT: vpmovsxbq {{.*#+}} zmm2 = [0,2,8,10,1,3,9,11] +; AVX512-NEXT: vpermi2q %zmm1, %zmm0, %zmm2 +; AVX512-NEXT: vmovdqa64 %zmm2, (%r8) ; AVX512-NEXT: vzeroupper ; AVX512-NEXT: retq ; ; AVX512-FCP-LABEL: store_i64_stride4_vf2: ; AVX512-FCP: # %bb.0: -; AVX512-FCP-NEXT: vmovaps (%rdi), %xmm0 -; AVX512-FCP-NEXT: vmovaps (%rdx), %xmm1 -; AVX512-FCP-NEXT: vinsertf128 $1, (%rcx), %ymm1, %ymm1 -; AVX512-FCP-NEXT: vinsertf128 $1, (%rsi), %ymm0, %ymm0 -; AVX512-FCP-NEXT: vinsertf64x4 $1, %ymm1, %zmm0, %zmm0 -; AVX512-FCP-NEXT: vmovaps {{.*#+}} zmm1 = [0,2,4,6,1,3,5,7] -; AVX512-FCP-NEXT: vpermpd %zmm0, %zmm1, %zmm0 -; AVX512-FCP-NEXT: vmovaps %zmm0, (%r8) +; AVX512-FCP-NEXT: vmovdqa (%rdi), %xmm0 +; AVX512-FCP-NEXT: vmovdqa (%rdx), %xmm1 +; AVX512-FCP-NEXT: vinserti128 $1, (%rcx), %ymm1, %ymm1 +; AVX512-FCP-NEXT: vinserti128 $1, (%rsi), %ymm0, %ymm0 +; AVX512-FCP-NEXT: vpmovsxbq {{.*#+}} zmm2 = [0,2,8,10,1,3,9,11] +; AVX512-FCP-NEXT: vpermi2q %zmm1, %zmm0, %zmm2 +; AVX512-FCP-NEXT: vmovdqa64 %zmm2, (%r8) ; AVX512-FCP-NEXT: vzeroupper ; AVX512-FCP-NEXT: retq ; ; AVX512DQ-LABEL: store_i64_stride4_vf2: ; AVX512DQ: # %bb.0: -; AVX512DQ-NEXT: vmovaps (%rdi), %xmm0 -; AVX512DQ-NEXT: vmovaps (%rdx), %xmm1 -; AVX512DQ-NEXT: vinsertf128 $1, (%rcx), %ymm1, %ymm1 -; AVX512DQ-NEXT: vinsertf128 $1, (%rsi), %ymm0, %ymm0 -; AVX512DQ-NEXT: vinsertf64x4 $1, %ymm1, %zmm0, %zmm0 -; AVX512DQ-NEXT: vmovaps {{.*#+}} zmm1 = [0,2,4,6,1,3,5,7] -; AVX512DQ-NEXT: vpermpd %zmm0, %zmm1, %zmm0 -; AVX512DQ-NEXT: vmovaps %zmm0, (%r8) +; AVX512DQ-NEXT: vmovdqa (%rdi), %xmm0 +; AVX512DQ-NEXT: vmovdqa (%rdx), %xmm1 +; AVX512DQ-NEXT: vinserti128 $1, (%rcx), %ymm1, %ymm1 +; AVX512DQ-NEXT: vinserti128 $1, (%rsi), %ymm0, %ymm0 +; AVX512DQ-NEXT: vpmovsxbq {{.*#+}} zmm2 = [0,2,8,10,1,3,9,11] +; AVX512DQ-NEXT: vpermi2q %zmm1, %zmm0, %zmm2 +; AVX512DQ-NEXT: vmovdqa64 %zmm2, (%r8) ; AVX512DQ-NEXT: vzeroupper ; AVX512DQ-NEXT: retq ; ; AVX512DQ-FCP-LABEL: store_i64_stride4_vf2: ; AVX512DQ-FCP: # %bb.0: -; AVX512DQ-FCP-NEXT: vmovaps (%rdi), %xmm0 -; AVX512DQ-FCP-NEXT: vmovaps (%rdx), %xmm1 -; AVX512DQ-FCP-NEXT: vinsertf128 $1, (%rcx), %ymm1, %ymm1 -; AVX512DQ-FCP-NEXT: vinsertf128 $1, (%rsi), %ymm0, %ymm0 -; AVX512DQ-FCP-NEXT: vinsertf64x4 $1, %ymm1, %zmm0, %zmm0 -; AVX512DQ-FCP-NEXT: vmovaps {{.*#+}} zmm1 = [0,2,4,6,1,3,5,7] -; AVX512DQ-FCP-NEXT: vpermpd %zmm0, %zmm1, %zmm0 -; AVX512DQ-FCP-NEXT: vmovaps %zmm0, (%r8) +; AVX512DQ-FCP-NEXT: vmovdqa (%rdi), %xmm0 +; AVX512DQ-FCP-NEXT: vmovdqa (%rdx), %xmm1 +; AVX512DQ-FCP-NEXT: vinserti128 $1, (%rcx), %ymm1, %ymm1 +; AVX512DQ-FCP-NEXT: vinserti128 $1, (%rsi), %ymm0, %ymm0 +; AVX512DQ-FCP-NEXT: vpmovsxbq {{.*#+}} zmm2 = [0,2,8,10,1,3,9,11] +; AVX512DQ-FCP-NEXT: vpermi2q %zmm1, %zmm0, %zmm2 +; AVX512DQ-FCP-NEXT: vmovdqa64 %zmm2, (%r8) ; AVX512DQ-FCP-NEXT: vzeroupper ; AVX512DQ-FCP-NEXT: retq ; ; AVX512BW-LABEL: store_i64_stride4_vf2: ; AVX512BW: # %bb.0: -; AVX512BW-NEXT: vmovaps (%rdi), %xmm0 -; AVX512BW-NEXT: vmovaps (%rdx), %xmm1 -; AVX512BW-NEXT: vinsertf128 $1, (%rcx), %ymm1, %ymm1 -; AVX512BW-NEXT: vinsertf128 $1, (%rsi), %ymm0, %ymm0 -; AVX512BW-NEXT: vinsertf64x4 $1, %ymm1, %zmm0, %zmm0 -; AVX512BW-NEXT: vmovaps {{.*#+}} zmm1 = [0,2,4,6,1,3,5,7] -; AVX512BW-NEXT: vpermpd %zmm0, %zmm1, %zmm0 -; AVX512BW-NEXT: vmovaps %zmm0, (%r8) +; AVX512BW-NEXT: vmovdqa (%rdi), %xmm0 +; AVX512BW-NEXT: vmovdqa (%rdx), %xmm1 +; AVX512BW-NEXT: vinserti128 $1, (%rcx), %ymm1, %ymm1 +; AVX512BW-NEXT: vinserti128 $1, (%rsi), %ymm0, %ymm0 +; AVX512BW-NEXT: vpmovsxbq {{.*#+}} zmm2 = [0,2,8,10,1,3,9,11] +; AVX512BW-NEXT: vpermi2q %zmm1, %zmm0, %zmm2 +; AVX512BW-NEXT: vmovdqa64 %zmm2, (%r8) ; AVX512BW-NEXT: vzeroupper ; AVX512BW-NEXT: retq ; ; AVX512BW-FCP-LABEL: store_i64_stride4_vf2: ; AVX512BW-FCP: # %bb.0: -; AVX512BW-FCP-NEXT: vmovaps (%rdi), %xmm0 -; AVX512BW-FCP-NEXT: vmovaps (%rdx), %xmm1 -; AVX512BW-FCP-NEXT: vinsertf128 $1, (%rcx), %ymm1, %ymm1 -; AVX512BW-FCP-NEXT: vinsertf128 $1, (%rsi), %ymm0, %ymm0 -; AVX512BW-FCP-NEXT: vinsertf64x4 $1, %ymm1, %zmm0, %zmm0 -; AVX512BW-FCP-NEXT: vmovaps {{.*#+}} zmm1 = [0,2,4,6,1,3,5,7] -; AVX512BW-FCP-NEXT: vpermpd %zmm0, %zmm1, %zmm0 -; AVX512BW-FCP-NEXT: vmovaps %zmm0, (%r8) +; AVX512BW-FCP-NEXT: vmovdqa (%rdi), %xmm0 +; AVX512BW-FCP-NEXT: vmovdqa (%rdx), %xmm1 +; AVX512BW-FCP-NEXT: vinserti128 $1, (%rcx), %ymm1, %ymm1 +; AVX512BW-FCP-NEXT: vinserti128 $1, (%rsi), %ymm0, %ymm0 +; AVX512BW-FCP-NEXT: vpmovsxbq {{.*#+}} zmm2 = [0,2,8,10,1,3,9,11] +; AVX512BW-FCP-NEXT: vpermi2q %zmm1, %zmm0, %zmm2 +; AVX512BW-FCP-NEXT: vmovdqa64 %zmm2, (%r8) ; AVX512BW-FCP-NEXT: vzeroupper ; AVX512BW-FCP-NEXT: retq ; ; AVX512DQ-BW-LABEL: store_i64_stride4_vf2: ; AVX512DQ-BW: # %bb.0: -; AVX512DQ-BW-NEXT: vmovaps (%rdi), %xmm0 -; AVX512DQ-BW-NEXT: vmovaps (%rdx), %xmm1 -; AVX512DQ-BW-NEXT: vinsertf128 $1, (%rcx), %ymm1, %ymm1 -; AVX512DQ-BW-NEXT: vinsertf128 $1, (%rsi), %ymm0, %ymm0 -; AVX512DQ-BW-NEXT: vinsertf64x4 $1, %ymm1, %zmm0, %zmm0 -; AVX512DQ-BW-NEXT: vmovaps {{.*#+}} zmm1 = [0,2,4,6,1,3,5,7] -; AVX512DQ-BW-NEXT: vpermpd %zmm0, %zmm1, %zmm0 -; AVX512DQ-BW-NEXT: vmovaps %zmm0, (%r8) +; AVX512DQ-BW-NEXT: vmovdqa (%rdi), %xmm0 +; AVX512DQ-BW-NEXT: vmovdqa (%rdx), %xmm1 +; AVX512DQ-BW-NEXT: vinserti128 $1, (%rcx), %ymm1, %ymm1 +; AVX512DQ-BW-NEXT: vinserti128 $1, (%rsi), %ymm0, %ymm0 +; AVX512DQ-BW-NEXT: vpmovsxbq {{.*#+}} zmm2 = [0,2,8,10,1,3,9,11] +; AVX512DQ-BW-NEXT: vpermi2q %zmm1, %zmm0, %zmm2 +; AVX512DQ-BW-NEXT: vmovdqa64 %zmm2, (%r8) ; AVX512DQ-BW-NEXT: vzeroupper ; AVX512DQ-BW-NEXT: retq ; ; AVX512DQ-BW-FCP-LABEL: store_i64_stride4_vf2: ; AVX512DQ-BW-FCP: # %bb.0: -; AVX512DQ-BW-FCP-NEXT: vmovaps (%rdi), %xmm0 -; AVX512DQ-BW-FCP-NEXT: vmovaps (%rdx), %xmm1 -; AVX512DQ-BW-FCP-NEXT: vinsertf128 $1, (%rcx), %ymm1, %ymm1 -; AVX512DQ-BW-FCP-NEXT: vinsertf128 $1, (%rsi), %ymm0, %ymm0 -; AVX512DQ-BW-FCP-NEXT: vinsertf64x4 $1, %ymm1, %zmm0, %zmm0 -; AVX512DQ-BW-FCP-NEXT: vmovaps {{.*#+}} zmm1 = [0,2,4,6,1,3,5,7] -; AVX512DQ-BW-FCP-NEXT: vpermpd %zmm0, %zmm1, %zmm0 -; AVX512DQ-BW-FCP-NEXT: vmovaps %zmm0, (%r8) +; AVX512DQ-BW-FCP-NEXT: vmovdqa (%rdi), %xmm0 +; AVX512DQ-BW-FCP-NEXT: vmovdqa (%rdx), %xmm1 +; AVX512DQ-BW-FCP-NEXT: vinserti128 $1, (%rcx), %ymm1, %ymm1 +; AVX512DQ-BW-FCP-NEXT: vinserti128 $1, (%rsi), %ymm0, %ymm0 +; AVX512DQ-BW-FCP-NEXT: vpmovsxbq {{.*#+}} zmm2 = [0,2,8,10,1,3,9,11] +; AVX512DQ-BW-FCP-NEXT: vpermi2q %zmm1, %zmm0, %zmm2 +; AVX512DQ-BW-FCP-NEXT: vmovdqa64 %zmm2, (%r8) ; AVX512DQ-BW-FCP-NEXT: vzeroupper ; AVX512DQ-BW-FCP-NEXT: retq %in.vec0 = load <2 x i64>, 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/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/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/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/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/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-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/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..84a7cf52fa30e06b646179dff09ec71bc3ed7e1e 100644 --- a/llvm/test/MC/ARM/basic-arm-instructions.s +++ b/llvm/test/MC/ARM/basic-arm-instructions.s @@ -1774,6 +1774,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 +1785,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 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/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/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/Mips/mips32/nal.s b/llvm/test/MC/Mips/mips32/nal.s new file mode 100644 index 0000000000000000000000000000000000000000..72c72310858631ffdcad656106a69d5eb8c8ae51 --- /dev/null +++ b/llvm/test/MC/Mips/mips32/nal.s @@ -0,0 +1,14 @@ +# RUN: llvm-mc %s -triple=mipsel-linux-gnu -filetype=obj -o - | \ +# RUN: llvm-objdump --no-print-imm-hex -d - | FileCheck %s --check-prefix=MIPS32-EL +# RUN: llvm-mc %s -triple=mips-linux-gnu -filetype=obj -o - | \ +# RUN: llvm-objdump --no-print-imm-hex -d - | FileCheck %s --check-prefix=MIPS32-EB + +# Whether it is a macro or an actual instruction, it always has a delay slot. +# Ensure the delay slot is filled correctly. +# MIPS32-EL: 00 00 10 04 bltzal $zero, 0x4 +# MIPS32-EL-NEXT: 00 00 00 00 nop +# MIPS32-EB: 04 10 00 00 bltzal $zero, 0x4 +# MIPS32-EB-NEXT: 00 00 00 00 nop + +nal_test: + nal diff --git a/llvm/test/MC/Mips/mips32r6/nal.s b/llvm/test/MC/Mips/mips32r6/nal.s new file mode 100644 index 0000000000000000000000000000000000000000..94c1a774f47ee97e71613a6afc2b57ca5f35b2e5 --- /dev/null +++ b/llvm/test/MC/Mips/mips32r6/nal.s @@ -0,0 +1,21 @@ +# RUN: llvm-mc %s -triple=mipsisa32r6el-linux-gnu -filetype=obj -o - | \ +# RUN: llvm-objdump --no-print-imm-hex -d - | FileCheck %s --check-prefix=MIPS32R6-EL +# RUN: llvm-mc %s -triple=mipsisa32r6-linux-gnu -filetype=obj -o - | \ +# RUN: llvm-objdump --no-print-imm-hex -d - | FileCheck %s --check-prefix=MIPS32R6-EB + +# Whether it is a macro or an actual instruction, it always has a delay slot. +# Ensure the delay slot is filled correctly. +# Also ensure that NAL does not reside in a forbidden slot. +# MIPS32R6-EL: 00 00 80 f8 bnezc $4, 0x4 +# MIPS32R6-EL-NEXT: 00 00 00 00 nop +# MIPS32R6-EL: 00 00 10 04 nal +# MIPS32R6-EL-NEXT: 00 00 00 00 nop +# MIPS32R6-EB: f8 80 00 00 bnezc $4, 0x4 +# MIPS32R6-EB-NEXT: 00 00 00 00 nop +# MIPS32R6-EB: 04 10 00 00 nal +# MIPS32R6-EB-NEXT: 00 00 00 00 nop + +nal_test: + # We generate a fobidden solt just for testing. + bnezc $a0, 0 + nal 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/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/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/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_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/MachineVerifier/test_g_vscale.mir b/llvm/test/MachineVerifier/test_g_vscale.mir new file mode 100644 index 0000000000000000000000000000000000000000..78854620913a166fea5ab3a36499635181ecba35 --- /dev/null +++ b/llvm/test/MachineVerifier/test_g_vscale.mir @@ -0,0 +1,15 @@ +# RUN: not --crash llc -verify-machineinstrs -run-pass none -o /dev/null %s 2>&1 | FileCheck %s + +--- +name: g_vscale +body: | + bb.0: + + %1:_(s32) = G_CONSTANT i32 4 + + ; CHECK: G_VSCALE operand must be cimm + %2:_(s32) = G_VSCALE %1 + + ; CHECK: G_VSCALE immediate cannot be zero + %3:_(s32) = G_VSCALE i32 0 +... 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/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/MacroFusion.td b/llvm/test/TableGen/MacroFusion.td index ce76e7f0f7fa64ed205f9c7fda42eb95e9cead24..b54b0506c56359584ae075433271303a59f9094d 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 @@ -78,7 +96,7 @@ 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, @@ -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: 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: 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..7b65e483c39d0d406c974629ec59473d8cad006d 100644 --- a/llvm/test/TableGen/x86-fold-tables.inc +++ b/llvm/test/TableGen/x86-fold-tables.inc @@ -1937,8 +1937,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/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/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/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/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/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/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/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/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/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/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/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/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/icmp-and-lowbit-mask.ll b/llvm/test/Transforms/InstCombine/icmp-and-lowbit-mask.ll index 640a95b05616023f8459181ef245201bf14eb73b..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 @@ -453,6 +452,42 @@ define i1 @src_is_notmask_shl(i8 %x_in, i8 %y, i1 %cond) { ret i1 %r } +define i1 @src_is_notmask_x_xor_neg_x(i8 %x_in, i8 %y, i1 %cond) { +; CHECK-LABEL: @src_is_notmask_x_xor_neg_x( +; 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 %x, %notmask + %r = icmp eq i8 %and, 0 + 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 @@ -554,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 @@ -639,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-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/mul.ll b/llvm/test/Transforms/InstCombine/mul.ll index e7141d7c25ad21c348329d2f475cf5229cfa9e8c..a176d16f2cdfb697595aff79fc6c7da9b6744e76 100644 --- a/llvm/test/Transforms/InstCombine/mul.ll +++ b/llvm/test/Transforms/InstCombine/mul.ll @@ -2049,3 +2049,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/powi.ll b/llvm/test/Transforms/InstCombine/powi.ll index 89efbb6f45361133f9da38fe4d95765e27595797..43e34c889106e1b942e59898563f6d73cbd6235f 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 } @@ -333,11 +381,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/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/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/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/LoopStrengthReduce/pr84709.ll b/llvm/test/Transforms/LoopStrengthReduce/pr84709.ll new file mode 100644 index 0000000000000000000000000000000000000000..99794d01242c2a900880df938003f70498a80199 --- /dev/null +++ b/llvm/test/Transforms/LoopStrengthReduce/pr84709.ll @@ -0,0 +1,34 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 +; RUN: opt -S -passes=loop-reduce < %s | FileCheck %s + +; Make sure it does not assert. +define i64 @test() { +; CHECK-LABEL: define i64 @test() { +; CHECK-NEXT: bb: +; CHECK-NEXT: br label [[BB1:%.*]] +; CHECK: bb1: +; CHECK-NEXT: br label [[BB2:%.*]] +; CHECK: bb2: +; CHECK-NEXT: br i1 true, label [[BB5:%.*]], label [[BB2]] +; CHECK: bb5: +; CHECK-NEXT: br label [[BB1]] +; +bb: + br label %bb1 + +bb1: + %phi = phi i8 [ %zext6, %bb5 ], [ 0, %bb ] + br label %bb2 + +bb2: + %phi3 = phi i8 [ %add, %bb2 ], [ %phi, %bb1 ] + %phi4 = phi i32 [ 0, %bb2 ], [ 1, %bb1 ] + %add = add i8 %phi3, 1 + br i1 true, label %bb5, label %bb2 + +bb5: + %zext = zext i8 %add to i32 + %icmp = icmp sge i32 %phi4, 0 + %zext6 = zext i1 %icmp to i8 + br label %bb1 +} 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-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/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/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/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/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..0e7461c2612b9fe1a303b44f7dcd83840c4321db 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,15 +31,15 @@ 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: ret i32 undef 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/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/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/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/partial-vec-invalid-cost.ll b/llvm/test/Transforms/SLPVectorizer/RISCV/partial-vec-invalid-cost.ll new file mode 100644 index 0000000000000000000000000000000000000000..31f16801b7a64ee3c37e00968ea3d523de3a8e46 --- /dev/null +++ b/llvm/test/Transforms/SLPVectorizer/RISCV/partial-vec-invalid-cost.ll @@ -0,0 +1,57 @@ +; 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: [[LSHR_1:%.*]] = lshr i96 0, 0 +; CHECK-NEXT: [[LSHR_2:%.*]] = lshr i96 0, 0 +; CHECK-NEXT: [[TRUNC_I96_1:%.*]] = trunc i96 [[LSHR_1]] to i32 +; CHECK-NEXT: [[TRUNC_I96_2:%.*]] = trunc i96 [[LSHR_2]] to i32 +; CHECK-NEXT: [[TRUNC_I96_3:%.*]] = trunc i96 0 to i32 +; CHECK-NEXT: [[TRUNC_I96_4:%.*]] = trunc i96 0 to i32 +; CHECK-NEXT: [[TMP0:%.*]] = call i32 @llvm.vector.reduce.or.v4i32(<4 x i32> zeroinitializer) +; CHECK-NEXT: [[OP_RDX:%.*]] = or i32 [[TMP0]], [[TRUNC_I96_2]] +; CHECK-NEXT: [[OP_RDX1:%.*]] = or i32 [[TRUNC_I96_1]], [[TRUNC_I96_3]] +; CHECK-NEXT: [[OP_RDX2:%.*]] = or i32 [[OP_RDX]], [[OP_RDX1]] +; CHECK-NEXT: [[OP_RDX3:%.*]] = or i32 [[OP_RDX2]], [[TRUNC_I96_4]] +; 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/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/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/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..5ee80160765387795d99481fadd5c9cb5e8db9e8 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=-6 < %s | FileCheck %s define void @t(i64 %v) { ; CHECK-LABEL: define void @t( 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-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..4a23abf182e888791ae5b98da86144c73678d3e7 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,111 @@ 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: [[TMP4:%.*]] = zext <4 x i32> [[TMP3]] to <4 x i64> +; CHECK-NEXT: [[TMP5:%.*]] = udiv <4 x i64> [[TMP4]], <i64 1, i64 2, i64 1, i64 2> +; 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: 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: [[TMP4:%.*]] = zext <4 x i32> [[TMP3]] to <4 x i64> +; CHECK-NEXT: [[TMP5:%.*]] = urem <4 x i64> [[TMP4]], <i64 1, i64 2, i64 1, i64 1> +; 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: 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..dce85b4b2a195e0a20f36be7b2e7c002c8783bcf 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 nsw <4 x i16> [[TMP7]], [[TMP8]] +; CHECK-NEXT: [[TMP10:%.*]] = sub nsw <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 nsw <4 x i16> zeroinitializer, [[TMP11]] +; CHECK-NEXT: [[TMP13:%.*]] = sub nsw <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/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/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/alternate-non-profitable.ll b/llvm/test/Transforms/SLPVectorizer/alternate-non-profitable.ll new file mode 100644 index 0000000000000000000000000000000000000000..c6e2cf5543e12e014be532dabb46e309a4f28458 --- /dev/null +++ b/llvm/test/Transforms/SLPVectorizer/alternate-non-profitable.ll @@ -0,0 +1,190 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 +; RUN: opt -S -passes=slp-vectorizer -slp-threshold=-10000 < %s | FileCheck %s + +define <2 x float> @test_fdiv(float %a, i1 %cmp) { +; CHECK-LABEL: define <2 x float> @test_fdiv( +; CHECK-SAME: float [[A:%.*]], i1 [[CMP:%.*]]) { +; CHECK-NEXT: [[TMP1:%.*]] = fdiv float [[A]], 3.000000e+00 +; CHECK-NEXT: [[TMP2:%.*]] = insertelement <2 x float> poison, float [[TMP1]], i64 1 +; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[CMP]], <2 x float> <float 7.700000e+01, float 9.900000e+01>, <2 x float> [[TMP2]] +; CHECK-NEXT: ret <2 x float> [[TMP3]] +; + %1 = fdiv float %a, 3.000000e+00 + %2 = insertelement <2 x float> poison, float %1, i64 1 + %3 = select i1 %cmp, <2 x float> <float 7.700000e+01, float 9.900000e+01>, <2 x float> %2 + ret <2 x float> %3 +} + +define <2 x float> @test_frem(float %a, i1 %cmp) { +; CHECK-LABEL: define <2 x float> @test_frem( +; CHECK-SAME: float [[A:%.*]], i1 [[CMP:%.*]]) { +; CHECK-NEXT: [[TMP1:%.*]] = frem float [[A]], 3.000000e+00 +; CHECK-NEXT: [[TMP2:%.*]] = insertelement <2 x float> poison, float [[TMP1]], i64 1 +; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[CMP]], <2 x float> <float 7.700000e+01, float 9.900000e+01>, <2 x float> [[TMP2]] +; CHECK-NEXT: ret <2 x float> [[TMP3]] +; + %1 = frem float %a, 3.000000e+00 + %2 = insertelement <2 x float> poison, float %1, i64 1 + %3 = select i1 %cmp, <2 x float> <float 7.700000e+01, float 9.900000e+01>, <2 x float> %2 + ret <2 x float> %3 +} + +define <2 x float> @replace_through_casts(i16 %inp) { +; CHECK-LABEL: define <2 x float> @replace_through_casts( +; CHECK-SAME: i16 [[INP:%.*]]) { +; CHECK-NEXT: [[ADD:%.*]] = add nsw i16 [[INP]], -10 +; CHECK-NEXT: [[TMP1:%.*]] = insertelement <2 x i16> poison, i16 [[INP]], i32 0 +; CHECK-NEXT: [[TMP2:%.*]] = insertelement <2 x i16> [[TMP1]], i16 [[ADD]], i32 1 +; CHECK-NEXT: [[TMP3:%.*]] = uitofp <2 x i16> [[TMP2]] to <2 x float> +; CHECK-NEXT: [[TMP4:%.*]] = sitofp <2 x i16> [[TMP2]] to <2 x float> +; CHECK-NEXT: [[R:%.*]] = shufflevector <2 x float> [[TMP3]], <2 x float> [[TMP4]], <2 x i32> <i32 0, i32 3> +; CHECK-NEXT: ret <2 x float> [[R]] +; + %add = add nsw i16 %inp, -10 + %1 = uitofp i16 %inp to float + %2 = sitofp i16 %add to float + %3 = insertelement <2 x float> poison, float %1, i64 0 + %r = insertelement <2 x float> %3, float %2, i64 1 + ret <2 x float> %r +} + +define <2 x float> @replace_through_casts_and_binop(i16 %inp) { +; CHECK-LABEL: define <2 x float> @replace_through_casts_and_binop( +; CHECK-SAME: i16 [[INP:%.*]]) { +; CHECK-NEXT: [[ADD:%.*]] = add nsw i16 [[INP]], -10 +; CHECK-NEXT: [[MUL:%.*]] = mul nsw i16 [[INP]], 5 +; CHECK-NEXT: [[TMP1:%.*]] = uitofp i16 [[MUL]] to float +; CHECK-NEXT: [[TMP2:%.*]] = fadd float [[TMP1]], 2.000000e+00 +; CHECK-NEXT: [[TMP3:%.*]] = sitofp i16 [[ADD]] to float +; CHECK-NEXT: [[TMP4:%.*]] = insertelement <2 x float> poison, float [[TMP2]], i64 0 +; CHECK-NEXT: [[R:%.*]] = insertelement <2 x float> [[TMP4]], float [[TMP3]], i64 1 +; CHECK-NEXT: ret <2 x float> [[R]] +; + %add = add nsw i16 %inp, -10 + %mul = mul nsw i16 %inp, 5 + %1 = uitofp i16 %mul to float + %2 = fadd float %1, 2.000000e+00 + %3 = sitofp i16 %add to float + %4 = insertelement <2 x float> poison, float %2, i64 0 + %r = insertelement <2 x float> %4, float %3, i64 1 + ret <2 x float> %r +} + +define <2 x float> @replace_through_casts_and_binop_and_unop(i16 %inp) { +; CHECK-LABEL: define <2 x float> @replace_through_casts_and_binop_and_unop( +; CHECK-SAME: i16 [[INP:%.*]]) { +; CHECK-NEXT: [[ADD:%.*]] = add nsw i16 [[INP]], -10 +; CHECK-NEXT: [[TMP1:%.*]] = sitofp i16 [[ADD]] to float +; CHECK-NEXT: [[TMP2:%.*]] = fneg float [[TMP1]] +; CHECK-NEXT: [[TMP3:%.*]] = uitofp i16 [[ADD]] to float +; CHECK-NEXT: [[TMP4:%.*]] = fadd float [[TMP3]], 2.000000e+00 +; CHECK-NEXT: [[TMP5:%.*]] = insertelement <2 x float> poison, float [[TMP4]], i64 0 +; CHECK-NEXT: [[R:%.*]] = insertelement <2 x float> [[TMP5]], float [[TMP2]], i64 1 +; CHECK-NEXT: ret <2 x float> [[R]] +; + %add = add nsw i16 %inp, -10 + %1 = sitofp i16 %add to float + %2 = fneg float %1 + %3 = uitofp i16 %add to float + %4 = fadd float %3, 2.000000e+00 + %5 = insertelement <2 x float> poison, float %4, i64 0 + %r = insertelement <2 x float> %5, float %2, i64 1 + ret <2 x float> %r +} + +define <2 x float> @replace_through_casts_through_splat(i16 %inp) { +; CHECK-LABEL: define <2 x float> @replace_through_casts_through_splat( +; CHECK-SAME: i16 [[INP:%.*]]) { +; CHECK-NEXT: [[ADD:%.*]] = add nsw i16 [[INP]], -10 +; CHECK-NEXT: [[TMP1:%.*]] = uitofp i16 [[ADD]] to float +; CHECK-NEXT: [[TMP2:%.*]] = fadd float [[TMP1]], 2.000000e+00 +; CHECK-NEXT: [[TMP3:%.*]] = sitofp i16 [[ADD]] to float +; CHECK-NEXT: [[TMP4:%.*]] = fneg float [[TMP3]] +; CHECK-NEXT: [[TMP5:%.*]] = insertelement <2 x float> poison, float [[TMP2]], i64 0 +; CHECK-NEXT: [[R:%.*]] = insertelement <2 x float> [[TMP5]], float [[TMP4]], i64 1 +; CHECK-NEXT: ret <2 x float> [[R]] +; + %add = add nsw i16 %inp, -10 + %1 = uitofp i16 %add to float + %2 = fadd float %1, 2.000000e+00 + %3 = sitofp i16 %add to float + %4 = fneg float %3 + %5 = insertelement <2 x float> poison, float %2, i64 0 + %r = insertelement <2 x float> %5, float %4, i64 1 + ret <2 x float> %r +} + +define <2 x i32> @replace_through_int_casts(i16 %inp, <2 x i16> %dead) { +; CHECK-LABEL: define <2 x i32> @replace_through_int_casts( +; CHECK-SAME: i16 [[INP:%.*]], <2 x i16> [[DEAD:%.*]]) { +; CHECK-NEXT: [[ADD:%.*]] = add nsw i16 [[INP]], -10 +; CHECK-NEXT: [[TMP1:%.*]] = insertelement <2 x i16> poison, i16 [[INP]], i32 0 +; CHECK-NEXT: [[TMP2:%.*]] = insertelement <2 x i16> [[TMP1]], i16 [[ADD]], i32 1 +; CHECK-NEXT: [[TMP3:%.*]] = zext <2 x i16> [[TMP2]] to <2 x i32> +; CHECK-NEXT: [[TMP4:%.*]] = sext <2 x i16> [[TMP2]] to <2 x i32> +; CHECK-NEXT: [[R:%.*]] = shufflevector <2 x i32> [[TMP3]], <2 x i32> [[TMP4]], <2 x i32> <i32 0, i32 3> +; CHECK-NEXT: ret <2 x i32> [[R]] +; + %add = add nsw i16 %inp, -10 + %1 = zext i16 %inp to i32 + %2 = sext i16 %add to i32 + %3 = insertelement <2 x i32> poison, i32 %1, i64 0 + %r = insertelement <2 x i32> %3, i32 %2, i64 1 + ret <2 x i32> %r +} + +define <2 x i32> @replace_through_int_casts_ele0_only(i16 %inp, <2 x i16> %dead) { +; CHECK-LABEL: define <2 x i32> @replace_through_int_casts_ele0_only( +; CHECK-SAME: i16 [[INP:%.*]], <2 x i16> [[DEAD:%.*]]) { +; CHECK-NEXT: [[TMP1:%.*]] = insertelement <2 x i16> poison, i16 [[INP]], i32 0 +; CHECK-NEXT: [[TMP2:%.*]] = shufflevector <2 x i16> [[TMP1]], <2 x i16> poison, <2 x i32> zeroinitializer +; CHECK-NEXT: [[TMP3:%.*]] = zext <2 x i16> [[TMP2]] to <2 x i32> +; CHECK-NEXT: [[TMP4:%.*]] = sext <2 x i16> [[TMP2]] to <2 x i32> +; CHECK-NEXT: [[R:%.*]] = shufflevector <2 x i32> [[TMP3]], <2 x i32> [[TMP4]], <2 x i32> <i32 0, i32 3> +; CHECK-NEXT: ret <2 x i32> [[R]] +; + %2 = sext i16 %inp to i32 + %4 = zext i16 %inp to i32 + %5 = insertelement <2 x i32> poison, i32 %4, i64 0 + %r = insertelement <2 x i32> %5, i32 %2, i64 1 + ret <2 x i32> %r +} + +define <2 x i8> @replace_through_binop_fail_cant_speculate(i8 %inp, <2 x i8> %d, <2 x i8> %any) { +; CHECK-LABEL: define <2 x i8> @replace_through_binop_fail_cant_speculate( +; CHECK-SAME: i8 [[INP:%.*]], <2 x i8> [[D:%.*]], <2 x i8> [[ANY:%.*]]) { +; CHECK-NEXT: [[ADD:%.*]] = add i8 [[INP]], 5 +; CHECK-NEXT: [[V0:%.*]] = insertelement <2 x i8> poison, i8 [[INP]], i64 0 +; CHECK-NEXT: [[V:%.*]] = insertelement <2 x i8> [[V0]], i8 [[ADD]], i64 1 +; CHECK-NEXT: [[DIV0:%.*]] = sdiv <2 x i8> <i8 -128, i8 -128>, [[V]] +; CHECK-NEXT: [[TMP1:%.*]] = xor i8 [[INP]], 123 +; CHECK-NEXT: [[R:%.*]] = insertelement <2 x i8> [[DIV0]], i8 [[TMP1]], i64 0 +; CHECK-NEXT: ret <2 x i8> [[R]] +; + %add = add i8 %inp, 5 + %v0 = insertelement <2 x i8> poison, i8 %inp, i64 0 + %v = insertelement <2 x i8> %v0, i8 %add, i64 1 + %div0 = sdiv <2 x i8> <i8 -128, i8 -128>, %v + %1 = xor i8 %inp, 123 + %r = insertelement <2 x i8> %div0, i8 %1, i64 0 + ret <2 x i8> %r +} + +define <2 x i8> @replace_through_binop_preserve_flags(i8 %inp, <2 x i8> %d, <2 x i8> %any) { +; CHECK-LABEL: define <2 x i8> @replace_through_binop_preserve_flags( +; CHECK-SAME: i8 [[INP:%.*]], <2 x i8> [[D:%.*]], <2 x i8> [[ANY:%.*]]) { +; CHECK-NEXT: [[ADD:%.*]] = xor i8 [[INP]], 5 +; CHECK-NEXT: [[TMP1:%.*]] = insertelement <2 x i8> poison, i8 [[INP]], i32 0 +; CHECK-NEXT: [[TMP2:%.*]] = insertelement <2 x i8> [[TMP1]], i8 [[ADD]], i32 1 +; CHECK-NEXT: [[TMP3:%.*]] = xor <2 x i8> [[TMP2]], <i8 123, i8 1> +; CHECK-NEXT: [[TMP4:%.*]] = add nsw <2 x i8> [[TMP2]], <i8 123, i8 1> +; CHECK-NEXT: [[R:%.*]] = shufflevector <2 x i8> [[TMP3]], <2 x i8> [[TMP4]], <2 x i32> <i32 0, i32 3> +; CHECK-NEXT: ret <2 x i8> [[R]] +; + %add = xor i8 %inp, 5 + %1 = xor i8 %inp, 123 + %2 = add nsw i8 %add, 1 + %3 = insertelement <2 x i8> poison, i8 %1, i64 0 + %r = insertelement <2 x i8> %3, i8 %2, i64 1 + ret <2 x i8> %r +} 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/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/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/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/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/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-dlltool/arm64ec.test b/llvm/test/tools/llvm-dlltool/arm64ec.test index e742a77ff78a5241956af71f5a6f6e5e8aa58fbf..b03b4eaf7b2d0e0ed92dbaf37665c8c078b422a4 100644 --- a/llvm/test/tools/llvm-dlltool/arm64ec.test +++ b/llvm/test/tools/llvm-dlltool/arm64ec.test @@ -12,9 +12,12 @@ ARMAP-NEXT: test_NULL_THUNK_DATA in test.dll ARMAP-EMPTY: ARMAP-NEXT: Archive EC map ARMAP-NEXT: #func in test.dll +ARMAP-NEXT: __IMPORT_DESCRIPTOR_test in test.dll +ARMAP-NEXT: __NULL_IMPORT_DESCRIPTOR in test.dll ARMAP-NEXT: __imp_aux_func in test.dll ARMAP-NEXT: __imp_func in test.dll ARMAP-NEXT: func in test.dll +ARMAP-NEXT: test_NULL_THUNK_DATA in test.dll RUN: llvm-dlltool -m arm64ec -d test.def -N test2.def -l test2.lib RUN: llvm-nm --print-armap test2.lib | FileCheck --check-prefix=ARMAP2 %s @@ -28,9 +31,12 @@ ARMAP2-NEXT: test_NULL_THUNK_DATA in test.dll ARMAP2-EMPTY: ARMAP2-NEXT: Archive EC map ARMAP2-NEXT: #func in test.dll +ARMAP2-NEXT: __IMPORT_DESCRIPTOR_test in test.dll +ARMAP2-NEXT: __NULL_IMPORT_DESCRIPTOR in test.dll ARMAP2-NEXT: __imp_aux_func in test.dll ARMAP2-NEXT: __imp_func in test.dll ARMAP2-NEXT: func in test.dll +ARMAP2-NEXT: test_NULL_THUNK_DATA in test.dll RUN: llvm-dlltool -m arm64ec -d test.def --input-native-def test2.def -l test3.lib RUN: llvm-nm --print-armap test3.lib | FileCheck --check-prefix=ARMAP2 %s diff --git a/llvm/test/tools/llvm-lib/arm64ec-implib.test b/llvm/test/tools/llvm-lib/arm64ec-implib.test index 77bdc23589fd25f264c80db437ce1b56b66cfc8c..9ce53fe0fea07734c99b334a3916219bb0a9c153 100644 --- a/llvm/test/tools/llvm-lib/arm64ec-implib.test +++ b/llvm/test/tools/llvm-lib/arm64ec-implib.test @@ -16,6 +16,8 @@ ARMAP-NEXT: #funcexp in test.dll ARMAP-NEXT: #mangledfunc 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 +ARMAP-NEXT: __NULL_IMPORT_DESCRIPTOR in test.dll ARMAP-NEXT: __imp_?test_cpp_func@@YAHPEAX@Z in test.dll ARMAP-NEXT: __imp_aux_?test_cpp_func@@YAHPEAX@Z in test.dll ARMAP-NEXT: __imp_aux_expname in test.dll @@ -28,20 +30,21 @@ ARMAP-NEXT: __imp_mangledfunc in test.dll ARMAP-NEXT: expname in test.dll ARMAP-NEXT: funcexp in test.dll ARMAP-NEXT: mangledfunc 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 @@ -93,6 +96,11 @@ READOBJ-NEXT: Name type: name READOBJ-NEXT: Export name: dataexp READOBJ-NEXT: Symbol: __imp_dataexp +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 RUN: llvm-nm --print-armap test2.lib | FileCheck -check-prefix=ARMAP %s @@ -122,6 +130,8 @@ ARMAPX-NEXT: #funcexp in test.dll ARMAPX-NEXT: #mangledfunc 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 +ARMAPX-NEXT: __NULL_IMPORT_DESCRIPTOR in test.dll ARMAPX-NEXT: __imp_?test_cpp_func@@YAHPEAX@Z in test.dll ARMAPX-NEXT: __imp_aux_?test_cpp_func@@YAHPEAX@Z in test.dll ARMAPX-NEXT: __imp_aux_expname in test.dll @@ -134,6 +144,7 @@ ARMAPX-NEXT: __imp_mangledfunc in test.dll ARMAPX-NEXT: expname in test.dll ARMAPX-NEXT: funcexp in test.dll ARMAPX-NEXT: mangledfunc in test.dll +ARMAPX-NEXT: test_NULL_THUNK_DATA in test.dll RUN: llvm-readobj testx.lib | FileCheck -check-prefix=READOBJX %s @@ -240,7 +251,9 @@ READOBJX-NEXT: Symbol: __imp_dataexp 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 @@ -255,6 +268,8 @@ ARMAPX2-NEXT: #funcexp in test2.dll ARMAPX2-NEXT: #mangledfunc 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 +ARMAPX2-NEXT: __NULL_IMPORT_DESCRIPTOR in test2.dll ARMAPX2-NEXT: __imp_?test_cpp_func@@YAHPEAX@Z in test2.dll ARMAPX2-NEXT: __imp_aux_?test_cpp_func@@YAHPEAX@Z in test2.dll ARMAPX2-NEXT: __imp_aux_expname in test2.dll @@ -267,6 +282,7 @@ ARMAPX2-NEXT: __imp_mangledfunc in test2.dll ARMAPX2-NEXT: expname in test2.dll ARMAPX2-NEXT: funcexp in test2.dll ARMAPX2-NEXT: mangledfunc in test2.dll +ARMAPX2-NEXT: test2_NULL_THUNK_DATA in test2.dll ARMAPX2: test2.dll: ARMAPX2: 00000000 T #funcexp @@ -309,6 +325,8 @@ EXPAS-ARMAP-NEXT: #func1 in test.dll EXPAS-ARMAP-NEXT: #func2 in test.dll EXPAS-ARMAP-NEXT: #func3 in test.dll EXPAS-ARMAP-NEXT: #func4 in test.dll +EXPAS-ARMAP-NEXT: __IMPORT_DESCRIPTOR_test in test.dll +EXPAS-ARMAP-NEXT: __NULL_IMPORT_DESCRIPTOR in test.dll EXPAS-ARMAP-NEXT: __imp_aux_func1 in test.dll EXPAS-ARMAP-NEXT: __imp_aux_func2 in test.dll EXPAS-ARMAP-NEXT: __imp_aux_func3 in test.dll @@ -323,6 +341,7 @@ EXPAS-ARMAP-NEXT: func1 in test.dll EXPAS-ARMAP-NEXT: func2 in test.dll EXPAS-ARMAP-NEXT: func3 in test.dll EXPAS-ARMAP-NEXT: func4 in test.dll +EXPAS-ARMAP-NEXT: test_NULL_THUNK_DATA in test.dll EXPAS-READOBJ: File: test.dll EXPAS-READOBJ-NEXT: Format: COFF-import-file-ARM64EC 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/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-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/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-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-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..78ccaf12a380b5b02f53dae687388ecfb2612f74 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,38 @@ 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)) + LLVMDIBuilderInsertDeclareRecordAtEnd( + DIB, LLVMConstInt(LLVMInt64Type(), 0, false), FooParamVar1, + FooParamExpression, FooParamLocation, FooEntryBlock); + else + LLVMDIBuilderInsertDeclareAtEnd( + 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)) + LLVMDIBuilderInsertDeclareRecordAtEnd( + DIB, LLVMConstInt(LLVMInt64Type(), 0, false), FooParamVar2, + FooParamExpression, FooParamLocation, FooEntryBlock); + else + LLVMDIBuilderInsertDeclareAtEnd( + 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)) + LLVMDIBuilderInsertDeclareRecordAtEnd( + DIB, LLVMConstInt(LLVMInt64Type(), 0, false), FooParamVar3, + FooParamExpression, FooParamLocation, FooEntryBlock); + else + LLVMDIBuilderInsertDeclareAtEnd( + DIB, LLVMConstInt(LLVMInt64Type(), 0, false), FooParamVar3, + FooParamExpression, FooParamLocation, FooEntryBlock); LLVMSetSubprogram(FooFunction, FunctionMetadata); @@ -166,9 +184,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.txt b/llvm/tools/llvm-debuginfo-analyzer/README.txt index e6c20db7cd7121b51ca0c7281f5d31e02270d06b..ce7569d2722452d03c3378a484ef92f5bfd44576 100644 --- a/llvm/tools/llvm-debuginfo-analyzer/README.txt +++ b/llvm/tools/llvm-debuginfo-analyzer/README.txt @@ -31,11 +31,11 @@ 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 + 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/ELFReader.test + llvm-project/llvm/test/DebugInfo/LogicalView/DWARFReader.test //===----------------------------------------------------------------------===// // Eliminate calls to 'getInputFileDirectory()' in the unit tests. @@ -210,9 +210,6 @@ The following DWARF debug location operands are not supported: //===----------------------------------------------------------------------===// // Add support for additional binary formats. //===----------------------------------------------------------------------===// -- WebAssembly (Wasm). - https://github.com/llvm/llvm-project/issues/57040#issuecomment-1211336680 - - Extended COFF (XCOFF) //===----------------------------------------------------------------------===// 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 5c9848f3c688855a5147e69fae0bb91439a427b7..498308e2edbe1fd541c27221dcff61c7164c2129 100644 --- a/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp +++ b/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp @@ -278,59 +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; - - 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); - // 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 @@ -338,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))); @@ -395,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)); @@ -408,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; @@ -415,8 +440,8 @@ private: setrlimit(RLIMIT_CORE, &rlim); } - [[noreturn]] void prepareAndRunBenchmark(int Pipe, - const BenchmarkKey &Key) 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 @@ -473,7 +498,7 @@ private: Expected<int> AuxMemFDOrError = SubprocessMemory::setupAuxiliaryMemoryInSubprocess( - Key.MemoryValues, ParentPID, CounterFileDescriptor); + Key.MemoryValues, ParentPID, ParentTID, CounterFileDescriptor); if (!AuxMemFDOrError) exit(ChildProcessExitCodeE::AuxiliaryMemorySetupFailed); diff --git a/llvm/tools/llvm-exegesis/lib/SubprocessMemory.cpp b/llvm/tools/llvm-exegesis/lib/SubprocessMemory.cpp index a49fa077257d002590335a44dbc7c4a536daf415..1fd81bd407becba50d1ca4c769c99c4aad72459c 100644 --- a/llvm/tools/llvm-exegesis/lib/SubprocessMemory.cpp +++ b/llvm/tools/llvm-exegesis/lib/SubprocessMemory.cpp @@ -9,11 +9,13 @@ #include "SubprocessMemory.h" #include "Error.h" #include "llvm/Support/Error.h" +#include "llvm/Support/FormatVariadic.h" #include <cerrno> #ifdef __linux__ #include <fcntl.h> #include <sys/mman.h> +#include <sys/syscall.h> #include <unistd.h> #endif @@ -22,12 +24,21 @@ 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. // This comes up particularly often when running the exegesis tests with - // llvm-lit - std::string AuxiliaryMemoryName = "/auxmem" + std::to_string(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}", getCurrentTID(), ProcessID); int AuxiliaryMemoryFD = shm_open(AuxiliaryMemoryName.c_str(), O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); if (AuxiliaryMemoryFD == -1) @@ -47,8 +58,8 @@ Error SubprocessMemory::addMemoryDefinition( pid_t ProcessPID) { SharedMemoryNames.reserve(MemoryDefinitions.size()); for (auto &[Name, MemVal] : MemoryDefinitions) { - std::string SharedMemoryName = "/" + std::to_string(ProcessPID) + "memdef" + - std::to_string(MemVal.Index); + std::string SharedMemoryName = + 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); @@ -82,8 +93,9 @@ Error SubprocessMemory::addMemoryDefinition( Expected<int> SubprocessMemory::setupAuxiliaryMemoryInSubprocess( std::unordered_map<std::string, MemoryValue> MemoryDefinitions, - pid_t ParentPID, int CounterFileDescriptor) { - std::string AuxiliaryMemoryName = "/auxmem" + std::to_string(ParentPID); + 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) @@ -97,8 +109,8 @@ Expected<int> SubprocessMemory::setupAuxiliaryMemoryInSubprocess( return make_error<Failure>("Mapping auxiliary memory failed"); AuxiliaryMemoryMapping[0] = CounterFileDescriptor; for (auto &[Name, MemVal] : MemoryDefinitions) { - std::string MemoryValueName = "/" + std::to_string(ParentPID) + "memdef" + - std::to_string(MemVal.Index); + std::string MemoryValueName = + formatv("/{0}t{1}memdef{2}", ParentPID, ParentTID, MemVal.Index); AuxiliaryMemoryMapping[AuxiliaryMemoryOffset + MemVal.Index] = shm_open(MemoryValueName.c_str(), O_RDWR, S_IRUSR | S_IWUSR); if (AuxiliaryMemoryMapping[AuxiliaryMemoryOffset + MemVal.Index] == -1) @@ -133,7 +145,7 @@ Error SubprocessMemory::addMemoryDefinition( Expected<int> SubprocessMemory::setupAuxiliaryMemoryInSubprocess( std::unordered_map<std::string, MemoryValue> MemoryDefinitions, - pid_t ParentPID, 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 e20b50cdc8118f6571d9277347b32820a0ae30f1..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, 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-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-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/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp index e78732353cc8776385d93e89e5c2d3c30ecb8e72..d1c05f437042de8826a8d0172f1c6a7ead62bdbd 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" @@ -2824,6 +2825,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, 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/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..83cbb02e0f58b36e0d8ac443dd75e44dcaf6829d 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; @@ -2911,6 +2913,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 +3049,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/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/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/ProfileData/InstrProfTest.cpp b/llvm/unittests/ProfileData/InstrProfTest.cpp index cd4552a039b36b034b185c5decae3c5adb5ffbfd..c9323420bda79bf3d503c0cc921d68abd6da4371 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; 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/KnownBitsTest.cpp b/llvm/unittests/Support/KnownBitsTest.cpp index d3177ce7e98371fc003cfc17da4cef40ef5515f9..48de0889fdf3326e5e6a0958b4fed1ecd291f8c7 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,18 +552,14 @@ 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); - }, + KnownBits::mulhs, [](const APInt &N1, const APInt &N2) { unsigned Bits = N1.getBitWidth(); return (N1.sext(2 * Bits) * N2.sext(2 * Bits)).extractBits(Bits, Bits); }, checkCorrectnessOnlyBinary); testBinaryOpExhaustive( - [](const KnownBits &Known1, const KnownBits &Known2) { - return KnownBits::mulhu(Known1, Known2); - }, + KnownBits::mulhu, [](const APInt &N1, const APInt &N2) { unsigned Bits = N1.getBitWidth(); return (N1.zext(2 * Bits) * N2.zext(2 * Bits)).extractBits(Bits, Bits); 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/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..fae0eee06e4b0c145d697901cad53a303a98fbbf 100644 --- a/llvm/unittests/TableGen/CMakeLists.txt +++ b/llvm/unittests/TableGen/CMakeLists.txt @@ -15,4 +15,4 @@ add_llvm_unittest(TableGenTests DISABLE_LLVM_LINK_LLVM_DYLIB 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..a7d0b1687a7f916cf737faaf3883beded755c01a 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; 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/tools/llvm-exegesis/X86/SubprocessMemoryTest.cpp b/llvm/unittests/tools/llvm-exegesis/X86/SubprocessMemoryTest.cpp index c07ec188a602c44509c28aa0fba55b8041a15c21..7c23e7b7e9c5a5706982ab438a76c229a6cf9ea0 100644 --- a/llvm/unittests/tools/llvm-exegesis/X86/SubprocessMemoryTest.cpp +++ b/llvm/unittests/tools/llvm-exegesis/X86/SubprocessMemoryTest.cpp @@ -17,6 +17,7 @@ #include <endian.h> #include <fcntl.h> #include <sys/mman.h> +#include <sys/syscall.h> #include <unistd.h> #endif // __linux__ @@ -49,7 +50,9 @@ protected: std::string getSharedMemoryName(const unsigned TestNumber, const unsigned DefinitionNumber) { - return "/" + std::to_string(getSharedMemoryNumber(TestNumber)) + "memdef" + + long CurrentTID = syscall(SYS_gettid); + return "/" + std::to_string(getSharedMemoryNumber(TestNumber)) + "t" + + std::to_string(CurrentTID) + "memdef" + std::to_string(DefinitionNumber); } 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..0440f027f28659bcbd9c476e8a4c9df1762130f4 --- /dev/null +++ b/llvm/utils/TableGen/Common/CMakeLists.txt @@ -0,0 +1,49 @@ +# 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/CXXPredicates.cpp + GlobalISel/GlobalISelMatchTable.cpp + GlobalISel/GlobalISelMatchTableExecutorEmitter.cpp + GlobalISel/MatchDataInfo.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 99% rename from llvm/utils/TableGen/CodeGenRegisters.cpp rename to llvm/utils/TableGen/Common/CodeGenRegisters.cpp index 40af0d3077b2dec2345ad678b17e40be5bfd739f..e851d4c16bf7b6f66dbe2ed18db1b41b8888744b 100644 --- a/llvm/utils/TableGen/CodeGenRegisters.cpp +++ b/llvm/utils/TableGen/Common/CodeGenRegisters.cpp @@ -1400,11 +1400,11 @@ CodeGenSubRegIndex *CodeGenRegBank::getConcatSubRegIndex( // None exists, synthesize one. std::string Name = Parts.front()->getName(); // Determine whether all parts are contiguous. - bool isContinuous = true; + 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(); @@ -1413,13 +1413,13 @@ CodeGenSubRegIndex *CodeGenRegBank::getConcatSubRegIndex( else Size += Parts[i]->Size; if (LastSize == UnknownSize || Parts[i]->Offset != (LastOffset + LastSize)) - isContinuous = false; + 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->Offset = IsContinuous ? Parts.front()->Offset : -1; Idx->ConcatenationOf.assign(Parts.begin(), Parts.end()); return Idx; } diff --git a/llvm/utils/TableGen/CodeGenRegisters.h b/llvm/utils/TableGen/Common/CodeGenRegisters.h similarity index 100% rename from llvm/utils/TableGen/CodeGenRegisters.h rename to llvm/utils/TableGen/Common/CodeGenRegisters.h 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/GlobalISel/CombinerUtils.h b/llvm/utils/TableGen/Common/GlobalISel/CombinerUtils.h similarity index 100% rename from llvm/utils/TableGen/GlobalISel/CombinerUtils.h rename to llvm/utils/TableGen/Common/GlobalISel/CombinerUtils.h 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..193f95443b16ef71da57390c67caf85fd55c4486 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" 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/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 98% rename from llvm/utils/TableGen/InfoByHwMode.cpp rename to llvm/utils/TableGen/Common/InfoByHwMode.cpp index 4a64421c013c5f778ac318c62cf6df1909044054..5496408bb0d306cc0f0057e8939730eb536058a8 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; } diff --git a/llvm/utils/TableGen/InfoByHwMode.h b/llvm/utils/TableGen/Common/InfoByHwMode.h similarity index 99% rename from llvm/utils/TableGen/InfoByHwMode.h rename to llvm/utils/TableGen/Common/InfoByHwMode.h index 001509e5317f95724ceb88d8916451480ffb9ba0..1909913c50c6e0c6dcfeaf138815f7b02df3dd0e 100644 --- a/llvm/utils/TableGen/InfoByHwMode.h +++ b/llvm/utils/TableGen/Common/InfoByHwMode.h @@ -181,7 +181,7 @@ struct RegSizeInfo { 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 { 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 fc958f5328736c81ee88ae23e4421033bcfa30f2..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" @@ -22,6 +22,7 @@ #include "llvm/Support/DXILABI.h" #include "llvm/TableGen/Record.h" #include "llvm/TableGen/TableGenBackend.h" +#include <string> using namespace llvm; using namespace llvm::dxil; @@ -38,8 +39,8 @@ struct DXILOperationDesc { int OpCode; // ID of DXIL operation StringRef OpClass; // name of the opcode class StringRef Doc; // the documentation description of this instruction - SmallVector<MVT::SimpleValueType> OpTypes; // Vector of operand types - - // return type is at index 0 + SmallVector<Record *> OpTypes; // Vector of operand type records - + // return type is at index 0 SmallVector<std::string> OpAttributes; // operation attribute represented as strings StringRef Intrinsic; // The llvm intrinsic map to OpName. Default is "" which @@ -57,28 +58,29 @@ struct DXILOperationDesc { DXILShaderModel ShaderModel; // minimum shader model required DXILShaderModel ShaderModelTranslated; // minimum shader model required with // translation by linker - int OverloadParamIndex; // parameter index which control the overload. - // When < 0, should be only 1 overload type. + int OverloadParamIndex; // Index of parameter with overload type. + // -1 : no overload types SmallVector<StringRef, 4> counters; // counters for this inst. DXILOperationDesc(const Record *); }; } // end anonymous namespace -/// Convert DXIL type name string to dxil::ParameterKind +/// Return dxil::ParameterKind corresponding to input LLVMType record /// -/// \param VT Simple Value Type +/// \param R TableGen def record of class LLVMType /// \return ParameterKind As defined in llvm/Support/DXILABI.h -static ParameterKind getParameterKind(MVT::SimpleValueType VT) { - switch (VT) { +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: @@ -89,7 +91,13 @@ static ParameterKind getParameterKind(MVT::SimpleValueType VT) { 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; + } + LLVM_FALLTHROUGH; default: llvm_unreachable("Support for specified DXIL Type not yet implemented"); } @@ -106,45 +114,80 @@ DXILOperationDesc::DXILOperationDesc(const Record *R) { Doc = R->getValueAsString("Doc"); + auto TypeRecs = R->getValueAsListOfDefs("OpTypes"); + unsigned TypeRecsSize = TypeRecs.size(); + // Populate OpTypes with return type and parameter types + + // Parameter indices of overloaded parameters. + // 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 + SmallVector<int> OverloadParamIndices; + for (unsigned i = 0; i < TypeRecsSize; i++) { + auto TR = TypeRecs[i]; + // Track operation parameter indices of any overload types + auto isAny = TR->getValueAsInt("isAny"); + if (isAny == 1) { + // TODO: At present it is expected that all overload types in a DXIL Op + // are of the same type. Hence, OverloadParamIndices will have only one + // element. This implies we do not need a vector. However, until more + // (all?) DXIL Ops are added in DXIL.td, a vector is being used to flag + // cases this assumption would not hold. + if (!OverloadParamIndices.empty()) { + bool knownType = true; + // Ensure that the same overload type registered earlier is being used + for (auto Idx : OverloadParamIndices) { + if (TR != TypeRecs[Idx]) { + knownType = false; + break; + } + } + if (!knownType) { + report_fatal_error("Specification of multiple differing overload " + "parameter types not yet supported", + false); + } + } else { + OverloadParamIndices.push_back(i); + } + } + // Populate OpTypes array according to the type specification + if (TR->isAnonymous()) { + // Check prior overload types exist + assert(!OverloadParamIndices.empty() && + "No prior overloaded parameter found to match."); + // Get the parameter index of anonymous type, TR, references + auto OLParamIndex = TR->getValueAsInt("Number"); + // Resolve and insert the type to that at OLParamIndex + OpTypes.emplace_back(TypeRecs[OLParamIndex]); + } else { + // A non-anonymous type. Just record it in OpTypes + OpTypes.emplace_back(TR); + } + } + + // Set the index of the overload parameter, if any. + OverloadParamIndex = -1; // default; indicating none + if (!OverloadParamIndices.empty()) { + if (OverloadParamIndices.size() > 1) + report_fatal_error("Multiple overload type specification not supported", + false); + OverloadParamIndex = OverloadParamIndices[0]; + } + // Get the operation class + OpClass = R->getValueAsDef("OpClass")->getName(); + if (R->getValue("LLVMIntrinsic")) { auto *IntrinsicDef = R->getValueAsDef("LLVMIntrinsic"); auto DefName = IntrinsicDef->getName(); assert(DefName.starts_with("int_") && "invalid intrinsic name"); // Remove the int_ from intrinsic name. Intrinsic = DefName.substr(4); - // TODO: It is expected that return type and parameter types of - // DXIL Operation are the same as that of the intrinsic. Deviations - // are expected to be encoded in TableGen record specification and - // handled accordingly here. Support to be added later, as needed. - // Get parameter type list of the intrinsic. Types attribute contains - // the list of as [returnType, param1Type,, param2Type, ...] - - OverloadParamIndex = -1; - auto TypeRecs = IntrinsicDef->getValueAsListOfDefs("Types"); - unsigned TypeRecsSize = TypeRecs.size(); - // Populate return type and parameter type names - for (unsigned i = 0; i < TypeRecsSize; i++) { - auto TR = TypeRecs[i]; - OpTypes.emplace_back(getValueType(TR->getValueAsDef("VT"))); - // Get the overload parameter index. - // TODO : Seems hacky. Is it possible that more than one parameter can - // be of overload kind?? - // TODO: Check for any additional constraints specified for DXIL operation - // restricting return type. - if (i > 0) { - auto &CurParam = OpTypes.back(); - if (getParameterKind(CurParam) >= ParameterKind::OVERLOAD) { - OverloadParamIndex = i; - } - } - } - // Get the operation class - OpClass = R->getValueAsDef("OpClass")->getName(); - - // NOTE: For now, assume that attributes of DXIL Operation are the same as + // TODO: For now, assume that attributes of DXIL Operation are the same as // that of the intrinsic. Deviations are expected to be encoded in TableGen // record specification and handled accordingly here. Support to be added - // later. + // as needed. auto IntrPropList = IntrinsicDef->getValueAsListInit("IntrProperties"); auto IntrPropListSize = IntrPropList->size(); for (unsigned i = 0; i < IntrPropListSize; i++) { @@ -158,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: @@ -178,25 +221,26 @@ 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"); } /// Return a string representation of OverloadKind enum that maps to -/// input Simple Value Type enum -/// \param VT Simple Value Type enum +/// input LLVMType record +/// \param R TableGen def record of class LLVMType /// \return std::string string representation of OverloadKind -static std::string getOverloadKindStr(MVT::SimpleValueType VT) { - switch (VT) { +static std::string getOverloadKindStr(const Record *R) { + auto VTRec = R->getValueAsDef("VT"); + switch (getValueType(VTRec)) { case MVT::isVoid: return "OverloadKind::VOID"; case MVT::f16: @@ -219,6 +263,16 @@ static std::string getOverloadKindStr(MVT::SimpleValueType VT) { return "OverloadKind::I16 | OverloadKind::I32 | OverloadKind::I64"; case MVT::fAny: return "OverloadKind::HALF | OverloadKind::FLOAT | OverloadKind::DOUBLE"; + case MVT::Other: + // Handle DXIL-specific overload types + { + if (R->getValueAsInt("isHalfOrFloat")) { + return "OverloadKind::HALF | OverloadKind::FLOAT"; + } else if (R->getValueAsInt("isI16OrI32")) { + return "OverloadKind::I16 | OverloadKind::I32"; + } + } + LLVM_FALLTHROUGH; default: llvm_unreachable( "Support for specified parameter OverloadKind not yet implemented"); @@ -344,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"; @@ -398,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 88f2452381382803502666b97a812a0c30a0b129..494dc93faacef8d008b6847116809c5d1948826d 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" @@ -226,7 +226,7 @@ static BitsInit &getBitsField(const Record &def, StringRef str) { VarLenInst VLI = VarLenInst(cast<DagInit>(RV->getValue()), RV); SmallVector<Init *, 16> Bits; - for (auto &SI : VLI) { + for (const auto &SI : VLI) { if (const BitsInit *BI = dyn_cast<BitsInit>(SI.Value)) { for (unsigned Idx = 0U; Idx < BI->getNumBits(); ++Idx) { Bits.push_back(BI->getBit(Idx)); @@ -441,16 +441,15 @@ public: protected: // Populates the insn given the uid. void insnWithID(insn_t &Insn, unsigned Opcode) const { - BitsInit &Bits = getBitsField(*AllInstructions[Opcode].EncodingDef, "Inst"); - Insn.resize(BitWidth > Bits.getNumBits() ? BitWidth : Bits.getNumBits(), - BIT_UNSET); + const Record *EncodingDef = AllInstructions[Opcode].EncodingDef; + BitsInit &Bits = getBitsField(*EncodingDef, "Inst"); + Insn.resize(std::max(BitWidth, Bits.getNumBits()), BIT_UNSET); // We may have a SoftFail bitmask, which specifies a mask where an encoding // may differ from the value in "Inst" and yet still be valid, but the // disassembler should return SoftFail instead of Success. // // This is used for marking UNPREDICTABLE instructions in the ARM world. - const RecordVal *RV = - AllInstructions[Opcode].EncodingDef->getValue("SoftFail"); + const RecordVal *RV = EncodingDef->getValue("SoftFail"); const BitsInit *SFBits = RV ? dyn_cast<BitsInit>(RV->getValue()) : nullptr; for (unsigned i = 0; i < Bits.getNumBits(); ++i) { if (SFBits && bitFromBits(*SFBits, i) == BIT_TRUE) @@ -472,10 +471,11 @@ protected: // Populates the field of the insn given the start position and the number of // consecutive bits to scan for. // - // Returns false if there exists any uninitialized bit value in the range. - // Returns true, otherwise. - bool fieldFromInsn(uint64_t &Field, insn_t &Insn, unsigned StartBit, - unsigned NumBits) const; + // Returns a pair of values (indicator, field), where the indicator is false + // if there exists any uninitialized bit value in the range and true if all + // bits are well-known. The second value is the potentially populated field. + std::pair<bool, uint64_t> fieldFromInsn(const insn_t &Insn, unsigned StartBit, + unsigned NumBits) const; /// dumpFilterArray - dumpFilterArray prints out debugging info for the given /// filter array as a series of chars. @@ -581,26 +581,25 @@ Filter::Filter(FilterChooser &owner, unsigned startBit, unsigned numBits, NumFiltered = 0; LastOpcFiltered = {0, 0}; - for (unsigned i = 0, e = Owner->Opcodes.size(); i != e; ++i) { + for (const auto &OpcPair : Owner->Opcodes) { insn_t Insn; // Populates the insn given the uid. - Owner->insnWithID(Insn, Owner->Opcodes[i].EncodingID); + Owner->insnWithID(Insn, OpcPair.EncodingID); - uint64_t Field; // Scans the segment for possibly well-specified encoding bits. - bool ok = Owner->fieldFromInsn(Field, Insn, StartBit, NumBits); + auto [Ok, Field] = Owner->fieldFromInsn(Insn, StartBit, NumBits); - if (ok) { + if (Ok) { // The encoding bits are well-known. Lets add the uid of the // instruction into the bucket keyed off the constant field value. - LastOpcFiltered = Owner->Opcodes[i]; + LastOpcFiltered = OpcPair; FilteredInstructions[Field].push_back(LastOpcFiltered); ++NumFiltered; } else { // Some of the encoding bit(s) are unspecified. This contributes to // one additional member of "Variable" instructions. - VariableInstructions.push_back(Owner->Opcodes[i]); + VariableInstructions.push_back(OpcPair); } } @@ -699,7 +698,7 @@ void Filter::emitTableEntry(DecoderTableInfo &TableInfo) const { size_t PrevFilter = 0; bool HasFallthrough = false; - for (auto &Filter : FilterChooserMap) { + for (const auto &Filter : FilterChooserMap) { // Field value -1 implies a non-empty set of variable instructions. // See also recurse(). if (Filter.first == NO_FIXED_SEGMENTS_SENTINEL) { @@ -784,7 +783,7 @@ void DecoderEmitter::emitTable(formatted_raw_ostream &OS, DecoderTable &Table, // is used below to index into NumberedEncodings. DenseMap<unsigned, unsigned> OpcodeToEncodingID; OpcodeToEncodingID.reserve(EncodingIDs.size()); - for (auto &EI : EncodingIDs) + for (const auto &EI : EncodingIDs) OpcodeToEncodingID[EI.Opcode] = EI.EncodingID; OS.indent(Indentation) << "static const uint8_t DecoderTable" << Namespace @@ -935,7 +934,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) { @@ -948,7 +947,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) { @@ -1038,27 +1037,29 @@ void DecoderEmitter::emitDecoderFunction(formatted_raw_ostream &OS, } OS.indent(Indentation) << "}\n"; Indentation -= 2; - OS.indent(Indentation) << "}\n\n"; + OS.indent(Indentation) << "}\n"; } // Populates the field of the insn given the start position and the number of // consecutive bits to scan for. // -// Returns false if and on the first uninitialized bit value encountered. -// Returns true, otherwise. -bool FilterChooser::fieldFromInsn(uint64_t &Field, insn_t &Insn, - unsigned StartBit, unsigned NumBits) const { - Field = 0; +// Returns a pair of values (indicator, field), where the indicator is false +// if there exists any uninitialized bit value in the range and true if all +// bits are well-known. The second value is the potentially populated field. +std::pair<bool, uint64_t> FilterChooser::fieldFromInsn(const insn_t &Insn, + unsigned StartBit, + unsigned NumBits) const { + uint64_t Field = 0; for (unsigned i = 0; i < NumBits; ++i) { if (Insn[StartBit + i] == BIT_UNSET) - return false; + return {false, Field}; if (Insn[StartBit + i] == BIT_TRUE) Field = Field | (1ULL << i); } - return true; + return {true, Field}; } /// dumpFilterArray - dumpFilterArray prints out debugging info for the given @@ -1246,14 +1247,14 @@ unsigned FilterChooser::getDecoderIndex(DecoderSet &Decoders, unsigned Opc, // If ParenIfBinOp is true, print a surrounding () if Val uses && or ||. bool FilterChooser::emitPredicateMatchAux(const Init &Val, bool ParenIfBinOp, raw_ostream &OS) const { - if (auto *D = dyn_cast<DefInit>(&Val)) { + if (const auto *D = dyn_cast<DefInit>(&Val)) { if (!D->getDef()->isSubClassOf("SubtargetFeature")) return true; OS << "Bits[" << Emitter->PredicateNamespace << "::" << D->getAsString() << "]"; return false; } - if (auto *D = dyn_cast<DagInit>(&Val)) { + if (const auto *D = dyn_cast<DagInit>(&Val)) { std::string Op = D->getOperator()->getAsString(); if (Op == "not" && D->getNumArgs() == 1) { OS << '!'; @@ -1350,9 +1351,9 @@ void FilterChooser::emitPredicateTableEntry(DecoderTableInfo &TableInfo, encodeULEB128(PIdx, S); TableInfo.Table.push_back(MCD::OPC_CheckPredicate); - // Predicate index - for (unsigned i = 0, e = PBytes.size(); i != e; ++i) - TableInfo.Table.push_back(PBytes[i]); + // Predicate index. + for (const auto PB : PBytes) + TableInfo.Table.push_back(PB); // Push location for NumToSkip backpatching. TableInfo.FixupStack.back().push_back(TableInfo.Table.size()); TableInfo.Table.push_back(0); @@ -1362,13 +1363,13 @@ void FilterChooser::emitPredicateTableEntry(DecoderTableInfo &TableInfo, void FilterChooser::emitSoftFailTableEntry(DecoderTableInfo &TableInfo, unsigned Opc) const { - const RecordVal *RV = AllInstructions[Opc].EncodingDef->getValue("SoftFail"); + const Record *EncodingDef = AllInstructions[Opc].EncodingDef; + const RecordVal *RV = EncodingDef->getValue("SoftFail"); BitsInit *SFBits = RV ? dyn_cast<BitsInit>(RV->getValue()) : nullptr; if (!SFBits) return; - BitsInit *InstBits = - AllInstructions[Opc].EncodingDef->getValueAsBitsInit("Inst"); + BitsInit *InstBits = EncodingDef->getValueAsBitsInit("Inst"); APInt PositiveMask(BitWidth, 0ULL); APInt NegativeMask(BitWidth, 0ULL); @@ -1495,9 +1496,9 @@ void FilterChooser::emitSingletonTableEntry(DecoderTableInfo &TableInfo, raw_svector_ostream S(Bytes); encodeULEB128(DIdx, S); - // Decoder index - for (unsigned i = 0, e = Bytes.size(); i != e; ++i) - TableInfo.Table.push_back(Bytes[i]); + // Decoder index. + for (const auto B : Bytes) + TableInfo.Table.push_back(B); if (!HasCompleteDecoder) { // Push location for NumToSkip backpatching. @@ -1566,7 +1567,7 @@ bool FilterChooser::filterProcessor(bool AllowMixed, bool Greedy) { if (AllowMixed && !Greedy) { assert(numInstructions == 3); - for (auto Opcode : Opcodes) { + for (const auto &Opcode : Opcodes) { std::vector<unsigned> StartBits; std::vector<unsigned> EndBits; std::vector<uint64_t> FieldVals; @@ -1613,10 +1614,10 @@ bool FilterChooser::filterProcessor(bool AllowMixed, bool Greedy) { else bitAttrs.push_back(ATTR_NONE); - for (unsigned InsnIndex = 0; InsnIndex < numInstructions; ++InsnIndex) { + for (const auto &OpcPair : Opcodes) { insn_t insn; - insnWithID(insn, Opcodes[InsnIndex].EncodingID); + insnWithID(insn, OpcPair.EncodingID); for (BitIndex = 0; BitIndex < BitWidth; ++BitIndex) { switch (bitAttrs[BitIndex]) { @@ -1760,14 +1761,14 @@ bool FilterChooser::filterProcessor(bool AllowMixed, bool Greedy) { bool AllUseless = true; unsigned BestScore = 0; - for (unsigned i = 0, e = Filters.size(); i != e; ++i) { - unsigned Usefulness = Filters[i].usefulness(); + for (const auto &[Idx, Filter] : enumerate(Filters)) { + unsigned Usefulness = Filter.usefulness(); if (Usefulness) AllUseless = false; if (Usefulness > BestScore) { - BestIndex = i; + BestIndex = Idx; BestScore = Usefulness; } } @@ -1892,8 +1893,7 @@ void parseVarLenInstOperand(const Record &Def, VarLenInst VLI(cast<DagInit>(RV->getValue()), RV); SmallVector<int> TiedTo; - for (unsigned Idx = 0; Idx < CGI.Operands.size(); ++Idx) { - auto &Op = CGI.Operands[Idx]; + for (const auto &[Idx, Op] : enumerate(CGI.Operands)) { if (Op.MIOperandInfo && Op.MIOperandInfo->getNumArgs() > 0) for (auto *Arg : Op.MIOperandInfo->getArgs()) Operands.push_back(getOpInfo(cast<DefInit>(Arg)->getDef())); @@ -1909,7 +1909,7 @@ void parseVarLenInstOperand(const Record &Def, } unsigned CurrBitPos = 0; - for (auto &EncodingSegment : VLI) { + for (const auto &EncodingSegment : VLI) { unsigned Offset = 0; StringRef OpName; @@ -2028,26 +2028,23 @@ populateInstruction(CodeGenTarget &Target, const Record &EncodingDef, std::vector<std::pair<Init *, StringRef>> InOutOperands; DagInit *Out = Def.getValueAsDag("OutOperandList"); DagInit *In = Def.getValueAsDag("InOperandList"); - for (unsigned i = 0; i < Out->getNumArgs(); ++i) - InOutOperands.push_back(std::pair(Out->getArg(i), Out->getArgNameStr(i))); - for (unsigned i = 0; i < In->getNumArgs(); ++i) - InOutOperands.push_back(std::pair(In->getArg(i), In->getArgNameStr(i))); + for (const auto &[Idx, Arg] : enumerate(Out->getArgs())) + InOutOperands.push_back(std::pair(Arg, Out->getArgNameStr(Idx))); + for (const auto &[Idx, Arg] : enumerate(In->getArgs())) + InOutOperands.push_back(std::pair(Arg, In->getArgNameStr(Idx))); // Search for tied operands, so that we can correctly instantiate // operands that are not explicitly represented in the encoding. std::map<std::string, std::string> TiedNames; - for (unsigned i = 0; i < CGI.Operands.size(); ++i) { - auto &Op = CGI.Operands[i]; - for (unsigned j = 0; j < Op.Constraints.size(); ++j) { - const CGIOperandList::ConstraintInfo &CI = Op.Constraints[j]; + for (const auto &[I, Op] : enumerate(CGI.Operands)) { + for (const auto &[J, CI] : enumerate(Op.Constraints)) { if (CI.isTied()) { - int tiedTo = CI.getTiedOperand(); std::pair<unsigned, unsigned> SO = - CGI.Operands.getSubOperandNumber(tiedTo); + CGI.Operands.getSubOperandNumber(CI.getTiedOperand()); std::string TiedName = CGI.Operands[SO.first].SubOpNames[SO.second]; if (TiedName.empty()) TiedName = CGI.Operands[SO.first].Name; - std::string MyName = Op.SubOpNames[j]; + std::string MyName = Op.SubOpNames[J]; if (MyName.empty()) MyName = Op.Name; @@ -2099,10 +2096,9 @@ populateInstruction(CodeGenTarget &Target, const Record &EncodingDef, // Decode each of the sub-ops separately. assert(SubOps && SubArgDag->getNumArgs() == SubOps->getNumArgs()); - for (unsigned i = 0; i < SubOps->getNumArgs(); ++i) { - StringRef SubOpName = SubArgDag->getArgNameStr(i); - OperandInfo SubOpInfo = - getOpInfo(cast<DefInit>(SubOps->getArg(i))->getDef()); + for (const auto &[I, Arg] : enumerate(SubOps->getArgs())) { + StringRef SubOpName = SubArgDag->getArgNameStr(I); + OperandInfo SubOpInfo = getOpInfo(cast<DefInit>(Arg)->getDef()); addOneOperandFields(EncodingDef, Bits, TiedNames, SubOpName, SubOpInfo); @@ -2169,273 +2165,240 @@ populateInstruction(CodeGenTarget &Target, const Record &EncodingDef, // using the VS compiler. It has a bug which causes the function // to be optimized out in some circumstances. See llvm.org/pr38292 static void emitFieldFromInstruction(formatted_raw_ostream &OS) { - OS << "// Helper functions for extracting fields from encoded instructions.\n" - << "// InsnType must either be integral or an APInt-like object that " - "must:\n" - << "// * be default-constructible and copy-constructible\n" - << "// * be constructible from an APInt (this can be private)\n" - << "// * Support insertBits(bits, startBit, numBits)\n" - << "// * Support extractBitsAsZExtValue(numBits, startBit)\n" - << "// * Support the ~, &, ==, and != operators with other objects of " - "the same type\n" - << "// * Support the != and bitwise & with uint64_t\n" - << "// * Support put (<<) to raw_ostream&\n" - << "template <typename InsnType>\n" - << "#if defined(_MSC_VER) && !defined(__clang__)\n" - << "__declspec(noinline)\n" - << "#endif\n" - << "static std::enable_if_t<std::is_integral<InsnType>::value, InsnType>\n" - << "fieldFromInstruction(const InsnType &insn, unsigned startBit,\n" - << " unsigned numBits) {\n" - << " assert(startBit + numBits <= 64 && \"Cannot support >64-bit " - "extractions!\");\n" - << " assert(startBit + numBits <= (sizeof(InsnType) * 8) &&\n" - << " \"Instruction field out of bounds!\");\n" - << " InsnType fieldMask;\n" - << " if (numBits == sizeof(InsnType) * 8)\n" - << " fieldMask = (InsnType)(-1LL);\n" - << " else\n" - << " fieldMask = (((InsnType)1 << numBits) - 1) << startBit;\n" - << " return (insn & fieldMask) >> startBit;\n" - << "}\n" - << "\n" - << "template <typename InsnType>\n" - << "static std::enable_if_t<!std::is_integral<InsnType>::value, " - "uint64_t>\n" - << "fieldFromInstruction(const InsnType &insn, unsigned startBit,\n" - << " unsigned numBits) {\n" - << " return insn.extractBitsAsZExtValue(numBits, startBit);\n" - << "}\n\n"; + OS << R"( +// Helper functions for extracting fields from encoded instructions. +// InsnType must either be integral or an APInt-like object that must: +// * be default-constructible and copy-constructible +// * be constructible from an APInt (this can be private) +// * Support insertBits(bits, startBit, numBits) +// * Support extractBitsAsZExtValue(numBits, startBit) +// * Support the ~, &, ==, and != operators with other objects of the same type +// * Support the != and bitwise & with uint64_t +// * Support put (<<) to raw_ostream& +template <typename InsnType> +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(noinline) +#endif +static std::enable_if_t<std::is_integral<InsnType>::value, InsnType> +fieldFromInstruction(const InsnType &insn, unsigned startBit, + unsigned numBits) { + assert(startBit + numBits <= 64 && "Cannot support >64-bit extractions!"); + assert(startBit + numBits <= (sizeof(InsnType) * 8) && + "Instruction field out of bounds!"); + InsnType fieldMask; + if (numBits == sizeof(InsnType) * 8) + fieldMask = (InsnType)(-1LL); + else + fieldMask = (((InsnType)1 << numBits) - 1) << startBit; + return (insn & fieldMask) >> startBit; +} + +template <typename InsnType> +static std::enable_if_t<!std::is_integral<InsnType>::value, uint64_t> +fieldFromInstruction(const InsnType &insn, unsigned startBit, + unsigned numBits) { + return insn.extractBitsAsZExtValue(numBits, startBit); +} +)"; } // emitInsertBits - Emit the templated helper function insertBits(). static void emitInsertBits(formatted_raw_ostream &OS) { - OS << "// Helper function for inserting bits extracted from an encoded " - "instruction into\n" - << "// a field.\n" - << "template <typename InsnType>\n" - << "static std::enable_if_t<std::is_integral<InsnType>::value>\n" - << "insertBits(InsnType &field, InsnType bits, unsigned startBit, " - "unsigned numBits) {\n" - << " assert(startBit + numBits <= sizeof field * 8);\n" - << " field |= (InsnType)bits << startBit;\n" - << "}\n" - << "\n" - << "template <typename InsnType>\n" - << "static std::enable_if_t<!std::is_integral<InsnType>::value>\n" - << "insertBits(InsnType &field, uint64_t bits, unsigned startBit, " - "unsigned numBits) {\n" - << " field.insertBits(bits, startBit, numBits);\n" - << "}\n\n"; + OS << R"( +// Helper function for inserting bits extracted from an encoded instruction into +// a field. +template <typename InsnType> +static std::enable_if_t<std::is_integral<InsnType>::value> +insertBits(InsnType &field, InsnType bits, unsigned startBit, unsigned numBits) { + assert(startBit + numBits <= sizeof field * 8); + field |= (InsnType)bits << startBit; +} + +template <typename InsnType> +static std::enable_if_t<!std::is_integral<InsnType>::value> +insertBits(InsnType &field, uint64_t bits, unsigned startBit, unsigned numBits) { + field.insertBits(bits, startBit, numBits); +} +)"; } // emitDecodeInstruction - Emit the templated helper function // decodeInstruction(). static void emitDecodeInstruction(formatted_raw_ostream &OS, bool IsVarLenInst) { - OS << "template <typename InsnType>\n" - << "static DecodeStatus decodeInstruction(const uint8_t DecodeTable[], " - "MCInst &MI,\n" - << " InsnType insn, uint64_t " - "Address,\n" - << " const MCDisassembler *DisAsm,\n" - << " const MCSubtargetInfo &STI"; + OS << R"( +template <typename InsnType> +static DecodeStatus decodeInstruction(const uint8_t DecodeTable[], MCInst &MI, + InsnType insn, uint64_t Address, + const MCDisassembler *DisAsm, + const MCSubtargetInfo &STI)"; if (IsVarLenInst) { - OS << ",\n" - << " llvm::function_ref<void(APInt " - "&," - << " uint64_t)> makeUp"; + OS << ",\n " + "llvm::function_ref<void(APInt &, uint64_t)> makeUp"; } - OS << ") {\n" - << " const FeatureBitset &Bits = STI.getFeatureBits();\n" - << "\n" - << " const uint8_t *Ptr = DecodeTable;\n" - << " uint64_t CurFieldValue = 0;\n" - << " DecodeStatus S = MCDisassembler::Success;\n" - << " while (true) {\n" - << " ptrdiff_t Loc = Ptr - DecodeTable;\n" - << " switch (*Ptr) {\n" - << " default:\n" - << " errs() << Loc << \": Unexpected decode table opcode!\\n\";\n" - << " return MCDisassembler::Fail;\n" - << " case MCD::OPC_ExtractField: {\n" - << " // Decode the start value.\n" - << " unsigned DecodedLen;\n" - << " unsigned Start = decodeULEB128(++Ptr, &DecodedLen);\n" - << " Ptr += DecodedLen;\n" - << " unsigned Len = *Ptr++;\n"; + OS << R"() { + const FeatureBitset &Bits = STI.getFeatureBits(); + + const uint8_t *Ptr = DecodeTable; + uint64_t CurFieldValue = 0; + DecodeStatus S = MCDisassembler::Success; + while (true) { + ptrdiff_t Loc = Ptr - DecodeTable; + switch (*Ptr) { + default: + errs() << Loc << ": Unexpected decode table opcode!\n"; + return MCDisassembler::Fail; + case MCD::OPC_ExtractField: { + // Decode the start value. + unsigned DecodedLen; + unsigned Start = decodeULEB128(++Ptr, &DecodedLen); + Ptr += DecodedLen; + unsigned Len = *Ptr++;)"; if (IsVarLenInst) - OS << " makeUp(insn, Start + Len);\n"; - OS << " CurFieldValue = fieldFromInstruction(insn, Start, Len);\n" - << " LLVM_DEBUG(dbgs() << Loc << \": OPC_ExtractField(\" << Start << " - "\", \"\n" - << " << Len << \"): \" << CurFieldValue << \"\\n\");\n" - << " break;\n" - << " }\n" - << " case MCD::OPC_FilterValue: {\n" - << " // Decode the field value.\n" - << " unsigned Len;\n" - << " uint64_t Val = decodeULEB128(++Ptr, &Len);\n" - << " Ptr += Len;\n" - << " // NumToSkip is a plain 24-bit integer.\n" - << " unsigned NumToSkip = *Ptr++;\n" - << " NumToSkip |= (*Ptr++) << 8;\n" - << " NumToSkip |= (*Ptr++) << 16;\n" - << "\n" - << " // Perform the filter operation.\n" - << " if (Val != CurFieldValue)\n" - << " Ptr += NumToSkip;\n" - << " LLVM_DEBUG(dbgs() << Loc << \": OPC_FilterValue(\" << Val << " - "\", \" << NumToSkip\n" - << " << \"): \" << ((Val != CurFieldValue) ? \"FAIL:\" " - ": \"PASS:\")\n" - << " << \" continuing at \" << (Ptr - DecodeTable) << " - "\"\\n\");\n" - << "\n" - << " break;\n" - << " }\n" - << " case MCD::OPC_CheckField: {\n" - << " // Decode the start value.\n" - << " unsigned Len;\n" - << " unsigned Start = decodeULEB128(++Ptr, &Len);\n" - << " Ptr += Len;\n" - << " Len = *Ptr;\n"; + OS << "\n makeUp(insn, Start + Len);"; + OS << R"( + CurFieldValue = fieldFromInstruction(insn, Start, Len); + LLVM_DEBUG(dbgs() << Loc << ": OPC_ExtractField(" << Start << ", " + << Len << "): " << CurFieldValue << "\n"); + break; + } + case MCD::OPC_FilterValue: { + // Decode the field value. + unsigned Len; + uint64_t Val = decodeULEB128(++Ptr, &Len); + Ptr += Len; + // NumToSkip is a plain 24-bit integer. + unsigned NumToSkip = *Ptr++; + NumToSkip |= (*Ptr++) << 8; + NumToSkip |= (*Ptr++) << 16; + + // Perform the filter operation. + if (Val != CurFieldValue) + Ptr += NumToSkip; + LLVM_DEBUG(dbgs() << Loc << ": OPC_FilterValue(" << Val << ", " << NumToSkip + << "): " << ((Val != CurFieldValue) ? "FAIL:" : "PASS:") + << " continuing at " << (Ptr - DecodeTable) << "\n"); + + break; + } + case MCD::OPC_CheckField: { + // Decode the start value. + unsigned Start = decodeULEB128AndInc(++Ptr); + unsigned Len = *Ptr;)"; if (IsVarLenInst) - OS << " makeUp(insn, Start + Len);\n"; - OS << " uint64_t FieldValue = fieldFromInstruction(insn, Start, Len);\n" - << " // Decode the field value.\n" - << " unsigned PtrLen = 0;\n" - << " uint64_t ExpectedValue = decodeULEB128(++Ptr, &PtrLen);\n" - << " Ptr += PtrLen;\n" - << " // NumToSkip is a plain 24-bit integer.\n" - << " unsigned NumToSkip = *Ptr++;\n" - << " NumToSkip |= (*Ptr++) << 8;\n" - << " NumToSkip |= (*Ptr++) << 16;\n" - << "\n" - << " // If the actual and expected values don't match, skip.\n" - << " if (ExpectedValue != FieldValue)\n" - << " Ptr += NumToSkip;\n" - << " LLVM_DEBUG(dbgs() << Loc << \": OPC_CheckField(\" << Start << " - "\", \"\n" - << " << Len << \", \" << ExpectedValue << \", \" << " - "NumToSkip\n" - << " << \"): FieldValue = \" << FieldValue << \", " - "ExpectedValue = \"\n" - << " << ExpectedValue << \": \"\n" - << " << ((ExpectedValue == FieldValue) ? \"PASS\\n\" : " - "\"FAIL\\n\"));\n" - << " break;\n" - << " }\n" - << " case MCD::OPC_CheckPredicate: {\n" - << " unsigned Len;\n" - << " // Decode the Predicate Index value.\n" - << " unsigned PIdx = decodeULEB128(++Ptr, &Len);\n" - << " Ptr += Len;\n" - << " // NumToSkip is a plain 24-bit integer.\n" - << " unsigned NumToSkip = *Ptr++;\n" - << " NumToSkip |= (*Ptr++) << 8;\n" - << " NumToSkip |= (*Ptr++) << 16;\n" - << " // Check the predicate.\n" - << " bool Pred;\n" - << " if (!(Pred = checkDecoderPredicate(PIdx, Bits)))\n" - << " Ptr += NumToSkip;\n" - << " (void)Pred;\n" - << " LLVM_DEBUG(dbgs() << Loc << \": OPC_CheckPredicate(\" << PIdx " - "<< \"): \"\n" - << " << (Pred ? \"PASS\\n\" : \"FAIL\\n\"));\n" - << "\n" - << " break;\n" - << " }\n" - << " case MCD::OPC_Decode: {\n" - << " unsigned Len;\n" - << " // Decode the Opcode value.\n" - << " unsigned Opc = decodeULEB128(++Ptr, &Len);\n" - << " Ptr += Len;\n" - << " unsigned DecodeIdx = decodeULEB128(Ptr, &Len);\n" - << " Ptr += Len;\n" - << "\n" - << " MI.clear();\n" - << " MI.setOpcode(Opc);\n" - << " bool DecodeComplete;\n"; + OS << "\n makeUp(insn, Start + Len);"; + OS << R"( + uint64_t FieldValue = fieldFromInstruction(insn, Start, Len); + // Decode the field value. + unsigned PtrLen = 0; + uint64_t ExpectedValue = decodeULEB128(++Ptr, &PtrLen); + Ptr += PtrLen; + // NumToSkip is a plain 24-bit integer. + unsigned NumToSkip = *Ptr++; + NumToSkip |= (*Ptr++) << 8; + NumToSkip |= (*Ptr++) << 16; + + // If the actual and expected values don't match, skip. + if (ExpectedValue != FieldValue) + Ptr += NumToSkip; + LLVM_DEBUG(dbgs() << Loc << ": OPC_CheckField(" << Start << ", " + << Len << ", " << ExpectedValue << ", " << NumToSkip + << "): FieldValue = " << FieldValue << ", ExpectedValue = " + << ExpectedValue << ": " + << ((ExpectedValue == FieldValue) ? "PASS\n" : "FAIL\n")); + break; + } + case MCD::OPC_CheckPredicate: { + // Decode the Predicate Index value. + unsigned PIdx = decodeULEB128AndInc(++Ptr); + // NumToSkip is a plain 24-bit integer. + unsigned NumToSkip = *Ptr++; + NumToSkip |= (*Ptr++) << 8; + NumToSkip |= (*Ptr++) << 16; + // Check the predicate. + bool Pred; + if (!(Pred = checkDecoderPredicate(PIdx, Bits))) + Ptr += NumToSkip; + (void)Pred; + LLVM_DEBUG(dbgs() << Loc << ": OPC_CheckPredicate(" << PIdx << "): " + << (Pred ? "PASS\n" : "FAIL\n")); + + break; + } + case MCD::OPC_Decode: { + // Decode the Opcode value. + unsigned Opc = decodeULEB128AndInc(++Ptr); + unsigned DecodeIdx = decodeULEB128AndInc(Ptr); + + MI.clear(); + MI.setOpcode(Opc); + bool DecodeComplete;)"; if (IsVarLenInst) { - OS << " Len = InstrLenTable[Opc];\n" - << " makeUp(insn, Len);\n"; + OS << "\n unsigned Len = InstrLenTable[Opc];\n" + << " makeUp(insn, Len);"; + } + OS << R"( + S = decodeToMCInst(S, DecodeIdx, insn, MI, Address, DisAsm, DecodeComplete); + assert(DecodeComplete); + + LLVM_DEBUG(dbgs() << Loc << ": OPC_Decode: opcode " << Opc + << ", using decoder " << DecodeIdx << ": " + << (S != MCDisassembler::Fail ? "PASS" : "FAIL") << "\n"); + return S; + } + case MCD::OPC_TryDecode: { + // Decode the Opcode value. + unsigned Opc = decodeULEB128AndInc(++Ptr); + unsigned DecodeIdx = decodeULEB128AndInc(Ptr); + // NumToSkip is a plain 24-bit integer. + unsigned NumToSkip = *Ptr++; + NumToSkip |= (*Ptr++) << 8; + NumToSkip |= (*Ptr++) << 16; + + // Perform the decode operation. + MCInst TmpMI; + TmpMI.setOpcode(Opc); + bool DecodeComplete; + S = decodeToMCInst(S, DecodeIdx, insn, TmpMI, Address, DisAsm, DecodeComplete); + LLVM_DEBUG(dbgs() << Loc << ": OPC_TryDecode: opcode " << Opc + << ", using decoder " << DecodeIdx << ": "); + + if (DecodeComplete) { + // Decoding complete. + LLVM_DEBUG(dbgs() << (S != MCDisassembler::Fail ? "PASS" : "FAIL") << "\n"); + MI = TmpMI; + return S; + } else { + assert(S == MCDisassembler::Fail); + // If the decoding was incomplete, skip. + Ptr += NumToSkip; + LLVM_DEBUG(dbgs() << "FAIL: continuing at " << (Ptr - DecodeTable) << "\n"); + // Reset decode status. This also drops a SoftFail status that could be + // set before the decode attempt. + S = MCDisassembler::Success; + } + break; + } + case MCD::OPC_SoftFail: { + // Decode the mask values. + uint64_t PositiveMask = decodeULEB128AndInc(++Ptr); + uint64_t NegativeMask = decodeULEB128AndInc(Ptr); + bool Fail = (insn & PositiveMask) != 0 || (~insn & NegativeMask) != 0; + if (Fail) + S = MCDisassembler::SoftFail; + LLVM_DEBUG(dbgs() << Loc << ": OPC_SoftFail: " << (Fail ? "FAIL\n" : "PASS\n")); + break; + } + case MCD::OPC_Fail: { + LLVM_DEBUG(dbgs() << Loc << ": OPC_Fail\n"); + return MCDisassembler::Fail; + } + } } - OS << " S = decodeToMCInst(S, DecodeIdx, insn, MI, Address, DisAsm, " - "DecodeComplete);\n" - << " assert(DecodeComplete);\n" - << "\n" - << " LLVM_DEBUG(dbgs() << Loc << \": OPC_Decode: opcode \" << Opc\n" - << " << \", using decoder \" << DecodeIdx << \": \"\n" - << " << (S != MCDisassembler::Fail ? \"PASS\" : " - "\"FAIL\") << \"\\n\");\n" - << " return S;\n" - << " }\n" - << " case MCD::OPC_TryDecode: {\n" - << " unsigned Len;\n" - << " // Decode the Opcode value.\n" - << " unsigned Opc = decodeULEB128(++Ptr, &Len);\n" - << " Ptr += Len;\n" - << " unsigned DecodeIdx = decodeULEB128(Ptr, &Len);\n" - << " Ptr += Len;\n" - << " // NumToSkip is a plain 24-bit integer.\n" - << " unsigned NumToSkip = *Ptr++;\n" - << " NumToSkip |= (*Ptr++) << 8;\n" - << " NumToSkip |= (*Ptr++) << 16;\n" - << "\n" - << " // Perform the decode operation.\n" - << " MCInst TmpMI;\n" - << " TmpMI.setOpcode(Opc);\n" - << " bool DecodeComplete;\n" - << " S = decodeToMCInst(S, DecodeIdx, insn, TmpMI, Address, DisAsm, " - "DecodeComplete);\n" - << " LLVM_DEBUG(dbgs() << Loc << \": OPC_TryDecode: opcode \" << " - "Opc\n" - << " << \", using decoder \" << DecodeIdx << \": \");\n" - << "\n" - << " if (DecodeComplete) {\n" - << " // Decoding complete.\n" - << " LLVM_DEBUG(dbgs() << (S != MCDisassembler::Fail ? \"PASS\" : " - "\"FAIL\") << \"\\n\");\n" - << " MI = TmpMI;\n" - << " return S;\n" - << " } else {\n" - << " assert(S == MCDisassembler::Fail);\n" - << " // If the decoding was incomplete, skip.\n" - << " Ptr += NumToSkip;\n" - << " LLVM_DEBUG(dbgs() << \"FAIL: continuing at \" << (Ptr - " - "DecodeTable) << \"\\n\");\n" - << " // Reset decode status. This also drops a SoftFail status " - "that could be\n" - << " // set before the decode attempt.\n" - << " S = MCDisassembler::Success;\n" - << " }\n" - << " break;\n" - << " }\n" - << " case MCD::OPC_SoftFail: {\n" - << " // Decode the mask values.\n" - << " unsigned Len;\n" - << " uint64_t PositiveMask = decodeULEB128(++Ptr, &Len);\n" - << " Ptr += Len;\n" - << " uint64_t NegativeMask = decodeULEB128(Ptr, &Len);\n" - << " Ptr += Len;\n" - << " bool Fail = (insn & PositiveMask) != 0 || (~insn & " - "NegativeMask) != 0;\n" - << " if (Fail)\n" - << " S = MCDisassembler::SoftFail;\n" - << " LLVM_DEBUG(dbgs() << Loc << \": OPC_SoftFail: \" << (Fail ? " - "\"FAIL\\n\" : \"PASS\\n\"));\n" - << " break;\n" - << " }\n" - << " case MCD::OPC_Fail: {\n" - << " LLVM_DEBUG(dbgs() << Loc << \": OPC_Fail\\n\");\n" - << " return MCDisassembler::Fail;\n" - << " }\n" - << " }\n" - << " }\n" - << " llvm_unreachable(\"bogosity detected in disassembler state " - "machine!\");\n" - << "}\n\n"; + llvm_unreachable("bogosity detected in disassembler state machine!"); +} + +)"; } // Helper to propagate SoftFail status. Returns false if the status is Fail; @@ -2443,10 +2406,13 @@ static void emitDecodeInstruction(formatted_raw_ostream &OS, // is correct to propagate the values of this enum; see comment on 'enum // DecodeStatus'.) static void emitCheck(formatted_raw_ostream &OS) { - OS << "static bool Check(DecodeStatus &Out, DecodeStatus In) {\n" - << " Out = static_cast<DecodeStatus>(Out & In);\n" - << " return Out != MCDisassembler::Fail;\n" - << "}\n\n"; + OS << R"( +static bool Check(DecodeStatus &Out, DecodeStatus In) { + Out = static_cast<DecodeStatus>(Out & In); + return Out != MCDisassembler::Fail; +} + +)"; } // Collect all HwModes referenced by the target for encoding purposes, @@ -2469,16 +2435,18 @@ collectHwModesReferencedForEncodings(const CodeGenHwModes &HWM, // Emits disassembler code for instruction decoding. void DecoderEmitter::run(raw_ostream &o) { formatted_raw_ostream OS(o); - OS << "#include \"llvm/MC/MCInst.h\"\n"; - OS << "#include \"llvm/MC/MCSubtargetInfo.h\"\n"; - OS << "#include \"llvm/Support/DataTypes.h\"\n"; - OS << "#include \"llvm/Support/Debug.h\"\n"; - OS << "#include \"llvm/Support/LEB128.h\"\n"; - OS << "#include \"llvm/Support/raw_ostream.h\"\n"; - OS << "#include \"llvm/TargetParser/SubtargetFeature.h\"\n"; - OS << "#include <assert.h>\n"; - OS << '\n'; - OS << "namespace llvm {\n\n"; + OS << R"( +#include "llvm/MC/MCInst.h" +#include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/Support/DataTypes.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/LEB128.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/TargetParser/SubtargetFeature.h" +#include <assert.h> + +namespace llvm { +)"; emitFieldFromInstruction(OS); emitInsertBits(OS); @@ -2533,9 +2501,9 @@ void DecoderEmitter::run(raw_ostream &o) { bool IsVarLenInst = Target.hasVariableLengthEncodings(); unsigned MaxInstLen = 0; - for (unsigned i = 0; i < NumberedEncodings.size(); ++i) { - const Record *EncodingDef = NumberedEncodings[i].EncodingDef; - const CodeGenInstruction *Inst = NumberedEncodings[i].Inst; + for (const auto &[NEI, NumberedEncoding] : enumerate(NumberedEncodings)) { + const Record *EncodingDef = NumberedEncoding.EncodingDef; + const CodeGenInstruction *Inst = NumberedEncoding.Inst; const Record *Def = Inst->TheDef; unsigned Size = EncodingDef->getValueAsInt("Size"); if (Def->getValueAsString("Namespace") == "TargetOpcode" || @@ -2546,7 +2514,7 @@ void DecoderEmitter::run(raw_ostream &o) { continue; } - if (i < NumberedInstructions.size()) + if (NEI < NumberedInstructions.size()) NumInstructions++; NumEncodings++; @@ -2556,19 +2524,19 @@ void DecoderEmitter::run(raw_ostream &o) { if (IsVarLenInst) InstrLen.resize(NumberedInstructions.size(), 0); - if (unsigned Len = populateInstruction(Target, *EncodingDef, *Inst, i, + if (unsigned Len = populateInstruction(Target, *EncodingDef, *Inst, NEI, Operands, IsVarLenInst)) { if (IsVarLenInst) { MaxInstLen = std::max(MaxInstLen, Len); - InstrLen[i] = Len; + InstrLen[NEI] = Len; } std::string DecoderNamespace = std::string(EncodingDef->getValueAsString("DecoderNamespace")); - if (!NumberedEncodings[i].HwModeName.empty()) + if (!NumberedEncoding.HwModeName.empty()) DecoderNamespace += - std::string("_") + NumberedEncodings[i].HwModeName.str(); + std::string("_") + NumberedEncoding.HwModeName.str(); OpcMap[std::pair(DecoderNamespace, Size)].emplace_back( - i, Target.getInstrIntValue(Def)); + NEI, Target.getInstrIntValue(Def)); } else { NumEncodingsOmitted++; } 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..39b9f8a2ae176448ee49205990020107a72ba80d 100644 --- a/llvm/utils/TableGen/GlobalISelCombinerEmitter.cpp +++ b/llvm/utils/TableGen/GlobalISelCombinerEmitter.cpp @@ -26,18 +26,18 @@ /// //===----------------------------------------------------------------------===// -#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/Patterns.h" +#include "Common/SubtargetFeatureInfo.h" #include "llvm/ADT/APInt.h" #include "llvm/ADT/EquivalenceClasses.h" #include "llvm/ADT/Hashing.h" 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..e9e63fa8d0de8c736df34f8d01d517adfd3fd3d4 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,6 +101,7 @@ 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"; @@ -111,7 +110,7 @@ void MacroFusionPredicatorEmitter::emitMacroFusionImpl( OS.indent(4) << "const MachineInstr &SecondMI) {\n"; OS.indent(2) << "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 +121,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 +138,7 @@ void MacroFusionPredicatorEmitter::emitPredicates( } void MacroFusionPredicatorEmitter::emitFirstPredicate(Record *Predicate, + bool IsCommutable, PredicateExpander &PE, raw_ostream &OS) { if (Predicate->isSubClassOf("WildcardPred")) { @@ -170,6 +171,7 @@ void MacroFusionPredicatorEmitter::emitFirstPredicate(Record *Predicate, } void MacroFusionPredicatorEmitter::emitSecondPredicate(Record *Predicate, + bool IsCommutable, PredicateExpander &PE, raw_ostream &OS) { if (Predicate->isSubClassOf("FusionPredicateWithMCInstPredicate")) { @@ -182,6 +184,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 +222,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 +239,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..a1259bff6ba8b0ff977e1e7bbbddb98cf819b3d9 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,16 @@ 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"; + 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 SubRegIndex lane masks, including 0. OS << "\nstatic const LaneBitmask SubRegIndexLaneMaskTable[] = {\n " "LaneBitmask::getAll(),\n"; @@ -1634,8 +1633,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 +1643,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 +1659,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); 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/git/code-format-helper.py b/llvm/utils/git/code-format-helper.py index 1113bf02570b94fbffc23a377ee365ba26084ece..af1bb3b5aec58d565ba4129fed89cff06986e6de 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,13 @@ 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: + 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 +320,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 +362,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 +375,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..42a658cefac327787fb95bc2c8c45ea2b2526c86 100755 --- a/llvm/utils/git/github-automation.py +++ b/llvm/utils/git/github-automation.py @@ -24,12 +24,13 @@ 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. """ 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 9c240cff18163475215a5ef6e331551feb8402bd..adaf6c476dfeccf97f8205e8ded4d808b69a566b 100644 --- a/llvm/utils/gn/secondary/clang/unittests/StaticAnalyzer/BUILD.gn +++ b/llvm/utils/gn/secondary/clang/unittests/StaticAnalyzer/BUILD.gn @@ -20,6 +20,7 @@ unittest("StaticAnalysisTests") { "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..ac111f902513525284c6272ba70ebe90daeb3ab1 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", @@ -824,10 +825,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 +841,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 +865,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..12d875cf40c98b88a604c5a50d980618ac230f30 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,7 @@ static_library("MCTargetDesc") { "AMDGPUInstPrinter.cpp", "AMDGPUMCAsmInfo.cpp", "AMDGPUMCCodeEmitter.cpp", + "AMDGPUMCExpr.cpp", "AMDGPUMCTargetDesc.cpp", "AMDGPUTargetStreamer.cpp", "R600InstPrinter.cpp", diff --git a/llvm/utils/gn/secondary/llvm/lib/Target/BPF/BUILD.gn b/llvm/utils/gn/secondary/llvm/lib/Target/BPF/BUILD.gn index 668512ecba88e32b39d99190ebfb919abd4f7fc0..aa594df8c164a1f8cd350778c59c4f91af223c55 100644 --- a/llvm/utils/gn/secondary/llvm/lib/Target/BPF/BUILD.gn +++ b/llvm/utils/gn/secondary/llvm/lib/Target/BPF/BUILD.gn @@ -60,6 +60,7 @@ static_library("LLVMBPFCodeGen") { ] include_dirs = [ "." ] sources = [ + "BPFASpaceCastSimplifyPass.cpp", "BPFAbstractMemberAccess.cpp", "BPFAdjustOpt.cpp", "BPFAsmPrinter.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..c0ea62716fd20a3f61a21ec7764f3f9d455cc557 --- /dev/null +++ b/llvm/utils/gn/secondary/llvm/utils/TableGen/Common/BUILD.gn @@ -0,0 +1,32 @@ +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/GlobalISelMatchTable.cpp", + "GlobalISel/GlobalISelMatchTableExecutorEmitter.cpp", + "GlobalISel/MatchDataInfo.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..86ad51a517ae7dbcbb7abbc75c1a87c6f785e49f 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 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..6c83ff0f46c878a90db2145214df25b377cb24d5 100644 --- a/mlir/examples/transform/Ch4/include/MyExtension.td +++ b/mlir/examples/transform/Ch4/include/MyExtension.td @@ -16,7 +16,7 @@ include "mlir/Dialect/Transform/IR/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/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..7e7ee3a2f780f6333c654b05b3116ef184d5ee3f 100644 --- a/mlir/include/mlir/Conversion/Passes.td +++ b/mlir/include/mlir/Conversion/Passes.td @@ -753,6 +753,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/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/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/LLVMInterfaces.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMInterfaces.td index 3b2a132a881e4edcec2146e3d7b22d0918e8ba75..e7a1da8ee560ef149a16f142955c6e8c670a9aeb 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. // //===----------------------------------------------------------------------===// @@ -319,4 +319,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/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 32b5a1c016b6f8f12bddf0b672eb2c84993b3a2b..1dabf5d7979b70751ccfb2ca0634ed5cafb98079 100644 --- a/mlir/include/mlir/Dialect/LLVMIR/ROCDLOps.td +++ b/mlir/include/mlir/Dialect/LLVMIR/ROCDLOps.td @@ -158,6 +158,24 @@ Arguments<(ins I32:$index, }]; } +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}, {$_resultType}); + }]; + + let assemblyFormat = "$pred attr-dict `:` type($res)"; +} //===----------------------------------------------------------------------===// // Thread index and Block index 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/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/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..6f94cee5b01911b9d377feff334667356df1f7fd 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" diff --git a/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVLogicalOps.td b/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVLogicalOps.td index e48a56f0625d3f1ca6c46b41f6f0a37f74afb8c5..14d639bc26f26a753b59e824bc8f21547bc6e66a 100644 --- a/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVLogicalOps.td +++ b/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVLogicalOps.td @@ -716,6 +716,8 @@ def SPIRV_SLessThanOp : SPIRV_LogicalBinaryOp<"SLessThan", ``` }]; + + let hasFolder = 1; } // ----- @@ -745,6 +747,8 @@ def SPIRV_SLessThanEqualOp : SPIRV_LogicalBinaryOp<"SLessThanEqual", %5 = spirv.SLessThanEqual %2, %3 : vector<4xi32> ``` }]; + + let hasFolder = 1; } // ----- @@ -800,6 +804,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; } // ----- @@ -884,6 +890,8 @@ def SPIRV_ULessThanOp : SPIRV_LogicalBinaryOp<"ULessThan", %5 = spirv.ULessThan %2, %3 : vector<4xi32> ``` }]; + + let hasFolder = 1; } // ----- @@ -947,6 +955,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/SparseTensor/IR/SparseTensorOps.td b/mlir/include/mlir/Dialect/SparseTensor/IR/SparseTensorOps.td index feed15d6af0544184e787563c6ef31a842a185ea..29cf8c32447ecf5e55d256a32128bc898b4edde6 100644 --- a/mlir/include/mlir/Dialect/SparseTensor/IR/SparseTensorOps.td +++ b/mlir/include/mlir/Dialect/SparseTensor/IR/SparseTensorOps.td @@ -668,48 +668,6 @@ def SparseTensor_CrdTranslateOp : SparseTensor_Op<"crd_translate", [Pure]>, // refined over time as our sparse abstractions evolve. //===----------------------------------------------------------------------===// -def SparseTensor_InsertOp : SparseTensor_Op<"insert", - [TypesMatchWith<"value type matches element type of tensor", - "tensor", "value", - "::llvm::cast<ShapedType>($_self).getElementType()">, - AllTypesMatch<["tensor", "result"]>]>, - Arguments<(ins AnyType:$value, - AnySparseTensor:$tensor, - Variadic<Index>:$lvlCoords)>, - Results<(outs AnySparseTensor:$result)> { - string summary = "Inserts a value into the sparse tensor"; - string description = [{ - Inserts the value into the underlying storage of the tensor at the - given level-coordinates. The arity of `lvlCoords` must match the - level-rank of the tensor. This operation can only be applied when - the tensor materializes unintialized from a `tensor.empty` operation - and the final tensor is constructed with a `load` operation which - has the `hasInserts` attribute set. - - The level-properties of the sparse tensor type fully describe what - kind of insertion order is allowed. When all levels have "unique" - and "ordered" properties, for example, insertions should occur in - strict lexicographical level-coordinate order. Other properties - define different insertion regimens. Inserting in a way contrary - to these properties results in undefined behavior. - - Note that this operation is "impure" in the sense that even though - the result is modeled through an SSA value, the insertion is eventually - done "in place", and referencing the old SSA value is undefined behavior. - This operation is scheduled to be unified with the dense counterpart - `tensor.insert` that has pure SSA semantics. - - Example: - - ```mlir - %result = sparse_tensor.insert %val into %tensor[%i,%j] : tensor<1024x1024xf64, #CSR> - ``` - }]; - let assemblyFormat = "$value `into` $tensor `[` $lvlCoords `]` attr-dict" - "`:` type($tensor)"; - let hasVerifier = 1; -} - def SparseTensor_PushBackOp : SparseTensor_Op<"push_back", [TypesMatchWith<"value type matches element type of inBuffer", "inBuffer", "value", @@ -1461,7 +1419,7 @@ def SparseTensor_ForeachOp : SparseTensor_Op<"foreach", } //===----------------------------------------------------------------------===// -// Sparse Tensor Debugging Operations. +// Sparse Tensor Debugging and Test-Only Operations. //===----------------------------------------------------------------------===// def SparseTensor_PrintOp : SparseTensor_Op<"print">, @@ -1482,4 +1440,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..54a9e2aec80501f1d55200da99d767e69023b9fa 100644 --- a/mlir/include/mlir/Dialect/SparseTensor/TransformOps/SparseTensorTransformOps.h +++ b/mlir/include/mlir/Dialect/SparseTensor/TransformOps/SparseTensorTransformOps.h @@ -12,7 +12,7 @@ #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/TransformInterfaces.h" #include "mlir/IR/OpImplementation.h" #include "mlir/IR/RegionKindInterface.h" 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/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..05abe5adbe80830c9d10eff51da5e57490ea98e7 100644 --- a/mlir/include/mlir/Dialect/Transform/DebugExtension/DebugExtensionOps.h +++ b/mlir/include/mlir/Dialect/Transform/DebugExtension/DebugExtensionOps.h @@ -12,7 +12,7 @@ #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/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..dc9b7c4229ac0385fb572c78bbd01d2c374007f1 100644 --- a/mlir/include/mlir/Dialect/Transform/DebugExtension/DebugExtensionOps.td +++ b/mlir/include/mlir/Dialect/Transform/DebugExtension/DebugExtensionOps.td @@ -17,7 +17,7 @@ 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/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..3ccac2f5c165f5736eae0541d64bd66d7040ff72 100644 --- a/mlir/include/mlir/Dialect/Transform/IR/CMakeLists.txt +++ b/mlir/include/mlir/Dialect/Transform/IR/CMakeLists.txt @@ -24,17 +24,7 @@ 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/MatchInterfaces.h b/mlir/include/mlir/Dialect/Transform/IR/MatchInterfaces.h index 36aeb4583029c9691aed72081eaf4840b7edf467..13a52b54201e6c383801b7492a040120eba556ea 100644 --- a/mlir/include/mlir/Dialect/Transform/IR/MatchInterfaces.h +++ b/mlir/include/mlir/Dialect/Transform/IR/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" diff --git a/mlir/include/mlir/Dialect/Transform/IR/MatchInterfaces.td b/mlir/include/mlir/Dialect/Transform/IR/MatchInterfaces.td index be92e4d91b42b32357e4c92094212c7935d37231..56d2ac64859976ded6823d080fb4735bc2198c53 100644 --- a/mlir/include/mlir/Dialect/Transform/IR/MatchInterfaces.td +++ b/mlir/include/mlir/Dialect/Transform/IR/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/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..6c10fcf75804e7336e5de381f9a2e3e69c71caf3 100644 --- a/mlir/include/mlir/Dialect/Transform/IR/TransformOps.h +++ b/mlir/include/mlir/Dialect/Transform/IR/TransformOps.h @@ -13,8 +13,8 @@ #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/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..9caa7632c177deedc78be300044912594d5e63a9 100644 --- a/mlir/include/mlir/Dialect/Transform/IR/TransformOps.td +++ b/mlir/include/mlir/Dialect/Transform/IR/TransformOps.td @@ -21,7 +21,7 @@ include "mlir/IR/SymbolInterfaces.td" include "mlir/Dialect/Transform/IR/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, 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..b3396b67b4f780b779fd45102ca51e26653ec3d6 --- /dev/null +++ b/mlir/include/mlir/Dialect/Transform/Interfaces/CMakeLists.txt @@ -0,0 +1,11 @@ +# 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) 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..2c548fb67402514ef0a47ab5aa0cb4c9b390d8a0 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,75 @@ 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; +}; + } // 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..773957a8b51162f71cfbc81fb94203bf8b1a34c6 100644 --- a/mlir/include/mlir/ExecutionEngine/SparseTensor/Storage.h +++ b/mlir/include/mlir/ExecutionEngine/SparseTensor/Storage.h @@ -197,37 +197,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. + /// 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, - bool initializeValuesIfAllDense); + const uint64_t *lvl2dim, SparseTensorCOO<V> *lvlCOO); /// 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. - 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); - - /// 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 +229,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; @@ -337,16 +320,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 +529,10 @@ 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); - } - } - } - std::vector<std::vector<P>> positions; std::vector<std::vector<C>> coordinates; std::vector<V> values; std::vector<uint64_t> lvlCursor; - SparseTensorCOO<V> *coo; }; //===----------------------------------------------------------------------===// @@ -621,9 +546,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 +556,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 +583,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 +616,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/IR/PatternMatch.h b/mlir/include/mlir/IR/PatternMatch.h index ef53a0b82866fcd86bc683173529a73b8be33e44..070e6ed702f86ac35ff4dbb60d3a8a17f17c497d 100644 --- a/mlir/include/mlir/IR/PatternMatch.h +++ b/mlir/include/mlir/IR/PatternMatch.h @@ -736,6 +736,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 +758,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..b4ed0967e63f18b479fb5bc1e4a8af1d054b0784 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. @@ -265,6 +269,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/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/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/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.td b/mlir/include/mlir/Transforms/Passes.td index b8fdf7a580476eec1c38752763306885deaa5268..51b2a27da639d67e5b332aacbbacfbcf164d0b28 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">, ]; } 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/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/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/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/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/Dialect/Affine/Analysis/AffineAnalysis.cpp b/mlir/lib/Dialect/Affine/Analysis/AffineAnalysis.cpp index 1ba0bc8b6bfbe5e86ed992da7029783e8b597bc6..61244921bc38acf112db82af09540634016f5272 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" 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/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..6a593185ccedcec4be3234bc04ba76d99d74a759 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" @@ -46,6 +49,12 @@ void arith::ArithDialect::initialize() { >(); addInterfaces<ArithInlinerInterface>(); declarePromisedInterface<ArithDialect, ConvertToLLVMPatternInterface>(); + declarePromisedInterface<SelectOp, + bufferization::BufferDeallocationOpInterface>(); + 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..2f32d9a26e7752874c25fd668a62895fb3575b75 100644 --- a/mlir/lib/Dialect/Arith/IR/ArithOps.cpp +++ b/mlir/lib/Dialect/Arith/IR/ArithOps.cpp @@ -689,43 +689,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 +943,6 @@ OpFoldResult arith::MaxNumFOp::fold(FoldAdaptor adaptor) { [](const APFloat &a, const APFloat &b) { return llvm::maximum(a, b); }); } - //===----------------------------------------------------------------------===// // MaxSIOp //===----------------------------------------------------------------------===// @@ -2173,35 +2146,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 +2182,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..71e14a153cfda94cdda7f4304eaeb7f71f8b9b67 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(); } }; 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/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/ControlFlow/IR/ControlFlowOps.cpp b/mlir/lib/Dialect/ControlFlow/IR/ControlFlowOps.cpp index d242d75bd51fa7b1d2770a3cff342fe10865e9f9..c6b02b9703e75f86d0212153d17ce6c9e20b78f7 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" @@ -69,6 +71,10 @@ void ControlFlowDialect::initialize() { >(); addInterfaces<ControlFlowInlinerInterface>(); declarePromisedInterface<ControlFlowDialect, ConvertToLLVMPatternInterface>(); + declarePromisedInterfaces<bufferization::BufferizableOpInterface, BranchOp, + CondBranchOp>(); + declarePromisedInterface<CondBranchOp, + bufferization::BufferDeallocationOpInterface>(); } //===----------------------------------------------------------------------===// diff --git a/mlir/lib/Dialect/EmitC/IR/EmitC.cpp b/mlir/lib/Dialect/EmitC/IR/EmitC.cpp index 9426bbbe2370f06815e7fb26958059b0301dbdaf..ab5c418e844fbfc27000f2fe912c482f70ab9eea 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()) @@ -746,6 +776,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..ed2ecfe9d0fb51ada565c713b100d17ad9147d5b 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" @@ -43,6 +44,8 @@ void FuncDialect::initialize() { >(); declarePromisedInterface<FuncDialect, DialectInlinerInterface>(); declarePromisedInterface<FuncDialect, ConvertToLLVMPatternInterface>(); + 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..a02eca8b11790caf875fd65a062f0beb11a93262 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<TerminatorOp, + bufferization::BufferDeallocationOpInterface>(); } 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..fc3a4375694588e1a636a0faf082cbd1e1e9f3d3 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" 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/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/LLVMMemorySlot.cpp b/mlir/lib/Dialect/LLVMIR/IR/LLVMMemorySlot.cpp index bf24194d03ddb21e9cb63ecea51ba04930955cc3..f171bf7cc4bec3e8df3c7eb358bc3b14a9e9ddb4 100644 --- a/mlir/lib/Dialect/LLVMIR/IR/LLVMMemorySlot.cpp +++ b/mlir/lib/Dialect/LLVMIR/IR/LLVMMemorySlot.cpp @@ -13,10 +13,8 @@ #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" @@ -71,12 +69,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 +126,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 +150,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 +176,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 +298,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 +310,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 +322,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 +334,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 +346,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 +358,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 +370,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 +382,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 +418,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; @@ -337,13 +438,18 @@ static bool isFirstIndexZero(LLVM::GEPOp gep) { } 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)) return failure(); + // Dynamic indices can be out-of-bounds (even negative), so an access with + // dynamic indices can never be considered safe. + if (!getDynamicIndices().empty()) + return failure(); Type reachedType = getResultPtrElementType(); if (!reachedType) return failure(); @@ -353,32 +459,35 @@ LogicalResult LLVM::GEPOp::ensureOnlySafeAccesses( 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; + // Dynamic indices can be out-of-bounds (even negative), so an access with + // dynamic indices can never be properly rewired. + if (!getDynamicIndices().empty()) + return false; Type reachedType = getResultPtrElementType(); if (!reachedType || getIndices().size() < 2) return false; auto firstLevelIndex = dyn_cast<IntegerAttr>(getIndices()[1]); if (!firstLevelIndex) return false; - assert(slot.elementPtrs.contains(firstLevelIndex)); - if (!llvm::isa<LLVM::LLVMPointerType>(slot.elementPtrs.at(firstLevelIndex))) - return false; mustBeSafelyUsed.emplace_back<MemorySlot>({getResult(), reachedType}); + assert(slot.elementPtrs.contains(firstLevelIndex)); usedIndices.insert(firstLevelIndex); return true; } DeletionKind LLVM::GEPOp::rewire(const DestructurableMemorySlot &slot, DenseMap<Attribute, MemorySlot> &subslots, - RewriterBase &rewriter) { + RewriterBase &rewriter, + const DataLayout &dataLayout) { IntegerAttr firstLevelIndex = llvm::dyn_cast_if_present<IntegerAttr>(getIndices()[1]); const MemorySlot &newSlot = subslots.at(firstLevelIndex); @@ -447,7 +556,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 +621,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 +636,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 +646,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 +668,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 +689,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 +751,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 +762,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 +790,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 +803,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 +842,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 +879,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 +905,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 +919,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 +954,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 +968,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 +1005,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 +1019,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..9e8407451a0855e6288c895ea23ecf6048db7183 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); } 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..a6936fde43709de8235ad12c4990463c97c7fcea 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" @@ -123,6 +126,23 @@ void mlir::linalg::LinalgDialect::initialize() { declarePromisedInterface<GenericOp, mesh::ShardingInterface>(); declarePromisedInterfaces<mesh::ShardingInterface, #define GET_OP_LIST +#include "mlir/Dialect/Linalg/IR/LinalgStructuredOps.cpp.inc" + >(); + declarePromisedInterface<CopyOp, SubsetOpInterface>(); + declarePromisedInterface<CopyOp, SubsetInsertionOpInterface>(); + declarePromisedInterface<IndexOp, ValueBoundsOpInterface>(); + declarePromisedInterface<linalg::GenericOp, TilingInterface>(); + declarePromisedInterface<linalg::GenericOp, PartialReductionOpInterface>(); + 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/TransformOps/LinalgMatchOps.cpp b/mlir/lib/Dialect/Linalg/TransformOps/LinalgMatchOps.cpp index fb18886c16b16d561b5e5a83fa1e24a769bfcb19..ae2a34bcf3e59ac38bda01136f0950bebf00984f 100644 --- a/mlir/lib/Dialect/Linalg/TransformOps/LinalgMatchOps.cpp +++ b/mlir/lib/Dialect/Linalg/TransformOps/LinalgMatchOps.cpp @@ -13,6 +13,7 @@ #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/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/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..c74ab1e6448bec12bb72e184ab9c50c207ca39fd 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"); } @@ -3475,9 +3577,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 +3604,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/Transforms/ExpandPatterns.cpp b/mlir/lib/Dialect/Math/Transforms/ExpandPatterns.cpp index 989a3e5536ec66fc014d16adbd3a7c6541ed90c0..e1ab9c905447b794a5b8f538dba30f77168ac565 100644 --- a/mlir/lib/Dialect/Math/Transforms/ExpandPatterns.cpp +++ b/mlir/lib/Dialect/Math/Transforms/ExpandPatterns.cpp @@ -91,34 +91,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(); } 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..41082a85a485f26f18ab16d811da3c295aabc851 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> @@ -43,6 +48,13 @@ void mlir::memref::MemRefDialect::initialize() { >(); addInterfaces<MemRefInlinerInterface>(); declarePromisedInterface<MemRefDialect, ConvertToLLVMPatternInterface>(); + declarePromisedInterfaces<bufferization::AllocationOpInterface, AllocOp, + AllocaOp, ReallocOp>(); + declarePromisedInterfaces<RuntimeVerifiableOpInterface, CastOp, ExpandShapeOp, + LoadOp, ReinterpretCastOp, StoreOp, SubViewOp>(); + declarePromisedInterfaces<ValueBoundsOpInterface, AllocOp, AllocaOp, CastOp, + DimOp, GetGlobalOp, RankOp, SubViewOp>(); + declarePromisedInterface<MemRefType, DestructurableTypeInterface>(); } /// 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/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..ddb9676eb4f62899bf37795ce97668725c8aca2f 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<ForOp, ValueBoundsOpInterface>(); } /// Default callback for IfOp builders. Inserts a yield without arguments. diff --git a/mlir/lib/Dialect/SCF/TransformOps/SCFTransformOps.cpp b/mlir/lib/Dialect/SCF/TransformOps/SCFTransformOps.cpp index bc2fe5772af9d6d2712cdaed0cd0ae2543dd2f79..4d8d93f7aac72028d46bfed9db1f470af2b20849 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" 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/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/SPIRVCanonicalization.cpp b/mlir/lib/Dialect/SPIRV/IR/SPIRVCanonicalization.cpp index 4c62289a1e94580f5a2ea14a78c50a6e45ed9428..3f1a7826f8b63ed7c4c1408eda7880928abb2429 100644 --- a/mlir/lib/Dialect/SPIRV/IR/SPIRVCanonicalization.cpp +++ b/mlir/lib/Dialect/SPIRV/IR/SPIRVCanonicalization.cpp @@ -797,6 +797,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 +880,88 @@ OpFoldResult spirv::INotEqualOp::fold(spirv::INotEqualOp::FoldAdaptor adaptor) { }); } +//===----------------------------------------------------------------------===// +// 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/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/Shape/IR/Shape.cpp b/mlir/lib/Dialect/Shape/IR/Shape.cpp index d9ee39a4e8dd321b03336dae2a173af612febd7c..f5a3717f815de555b9efdb0a89cc26b33791bb77 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" @@ -143,6 +144,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 c19907a945d3bba4190a4c94d217aaa1d0758a73..6da51bb6b9cacfcc2b7bbb694d2d83a1d691e3b8 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" @@ -1741,15 +1742,6 @@ LogicalResult ConcatenateOp::verify() { return success(); } -LogicalResult InsertOp::verify() { - const auto stt = getSparseTensorType(getTensor()); - if (stt.getEncoding().getBatchLvlRank() > 0) - return emitOpError("batched sparse tensor insertion not implemented"); - if (stt.getLvlRank() != static_cast<Level>(getLvlCoords().size())) - return emitOpError("incorrect number of coordinates"); - return success(); -} - void PushBackOp::build(OpBuilder &builder, OperationState &result, Value curSize, Value inBuffer, Value value) { build(builder, result, curSize, inBuffer, value, Value()); @@ -1965,6 +1957,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 3f4ae1f67de15021646c20fc95bca70e899940e4..7734d1d258453c8dcff23135de87362f1ecf8e39 100644 --- a/mlir/lib/Dialect/SparseTensor/Transforms/BufferizableOpInterfaceImpl.cpp +++ b/mlir/lib/Dialect/SparseTensor/Transforms/BufferizableOpInterfaceImpl.cpp @@ -187,8 +187,8 @@ struct DisassembleOpInterface } }; -struct InsertOpInterface : public SparseBufferizableOpInterfaceExternalModel< - InsertOpInterface, sparse_tensor::InsertOp> { +struct ForeachOpInterface : public SparseBufferizableOpInterfaceExternalModel< + ForeachOpInterface, sparse_tensor::ForeachOp> { bool bufferizesToMemoryRead(Operation *op, OpOperand &opOperand, const AnalysisState &state) const { return true; @@ -196,15 +196,23 @@ struct InsertOpInterface : public SparseBufferizableOpInterfaceExternalModel< bool bufferizesToMemoryWrite(Operation *op, OpOperand &opOperand, const AnalysisState &state) const { - // InsertOp writes to memory. - return true; + return false; } AliasingValueList getAliasingValues(Operation *op, OpOperand &opOperand, const AnalysisState &state) const { - // InsertOp returns an alias of its operand. - assert(op->getNumResults() == 1); - return {{op->getOpResult(0), BufferRelation::Equivalent}}; + 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(); } }; @@ -324,11 +332,11 @@ void mlir::sparse_tensor::registerBufferizableOpInterfaceExternalModels( sparse_tensor::ConvertOp::attachInterface<ConvertOpInterface>(*ctx); sparse_tensor::LoadOp::attachInterface<LoadOpInterface>(*ctx); sparse_tensor::NewOp::attachInterface<NewOpInterface>(*ctx); - sparse_tensor::InsertOp::attachInterface<InsertOpInterface>(*ctx); sparse_tensor::NumberOfEntriesOp::attachInterface< 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 fbe2fc31ab8b15bb19fd9e66b56fb2463d80740a..14ea07f0b54b8299dae6ea4a87b82db63b2d61f6 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. @@ -640,14 +646,14 @@ struct TensorInsertDemapper using DemapInsRewriter::DemapInsRewriter; LogicalResult rewriteOp(tensor::InsertOp op, OpAdaptor adaptor, PatternRewriter &rewriter) const { - if (!hasAnySparseResult(op)) + if (!hasAnySparseResult(op) || !hasAnyNonIdentityOperandsOrResults(op)) return failure(); Location loc = op.getLoc(); auto stt = getSparseTensorType(op.getResult()); ValueRange lvlCrd = stt.translateCrds(rewriter, loc, op.getIndices(), CrdTransDirectionKind::dim2lvl); - auto insertOp = rewriter.create<sparse_tensor::InsertOp>( + auto insertOp = rewriter.create<tensor::InsertOp>( loc, op.getScalar(), adaptor.getDest(), lvlCrd); Value out = genRemap(rewriter, stt.getEncoding(), insertOp.getResult()); diff --git a/mlir/lib/Dialect/SparseTensor/Transforms/SparseTensorCodegen.cpp b/mlir/lib/Dialect/SparseTensor/Transforms/SparseTensorCodegen.cpp index 44c5d4dbe485bf3c3c042d1f05d0bd3dd0fd025f..5679f277e148660063d6b70a0be38892ec9de0b7 100644 --- a/mlir/lib/Dialect/SparseTensor/Transforms/SparseTensorCodegen.cpp +++ b/mlir/lib/Dialect/SparseTensor/Transforms/SparseTensorCodegen.cpp @@ -1014,24 +1014,29 @@ public: }; /// Sparse codegen rule for the insert operator. -class SparseInsertConverter : public OpConversionPattern<InsertOp> { +class SparseInsertConverter : public OpConversionPattern<tensor::InsertOp> { public: using OpConversionPattern::OpConversionPattern; LogicalResult - matchAndRewrite(InsertOp op, OpAdaptor adaptor, + matchAndRewrite(tensor::InsertOp op, OpAdaptor adaptor, ConversionPatternRewriter &rewriter) const override { + auto stt = getSparseTensorType(adaptor.getDest()); + if (!stt.hasEncoding()) + return failure(); + assert(stt.isIdentity() && "Run reinterpret-map before conversion."); + Location loc = op.getLoc(); - auto desc = getDescriptorFromTensorTuple(adaptor.getTensor()); + auto desc = getDescriptorFromTensorTuple(adaptor.getDest()); TypeRange flatSpTensorTps = desc.getFields().getTypes(); SmallVector<Value> params = llvm::to_vector(desc.getFields()); - params.append(adaptor.getLvlCoords().begin(), adaptor.getLvlCoords().end()); - params.push_back(adaptor.getValue()); - SparseInsertGenerator insertGen(op.getTensor().getType(), flatSpTensorTps, + params.append(adaptor.getIndices().begin(), adaptor.getIndices().end()); + params.push_back(adaptor.getScalar()); + SparseInsertGenerator insertGen(op.getDest().getType(), flatSpTensorTps, params, /*genCall=*/true); SmallVector<Value> ret = insertGen.genCallOrInline(rewriter, loc); // Replace operation with resulting memrefs. rewriter.replaceOp(op, - genTuple(rewriter, loc, op.getTensor().getType(), ret)); + genTuple(rewriter, loc, op.getDest().getType(), ret)); return success(); } }; @@ -1556,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 //===----------------------------------------------------------------------===// @@ -1567,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 010c3aa58b72c7ee930a8431066f44b2b92d250e..92c98b34af60270f3bc2b583dc2d8d4037601940 100644 --- a/mlir/lib/Dialect/SparseTensor/Transforms/SparseTensorConversion.cpp +++ b/mlir/lib/Dialect/SparseTensor/Transforms/SparseTensorConversion.cpp @@ -580,17 +580,24 @@ public: }; /// Sparse conversion rule for the insertion operator. -class SparseTensorInsertConverter : public OpConversionPattern<InsertOp> { +class SparseTensorInsertConverter + : public OpConversionPattern<tensor::InsertOp> { public: using OpConversionPattern::OpConversionPattern; LogicalResult - matchAndRewrite(InsertOp op, OpAdaptor adaptor, + matchAndRewrite(tensor::InsertOp op, OpAdaptor adaptor, ConversionPatternRewriter &rewriter) const override { // Note that the current regime only allows for strict lexicographic // coordinate order. All values are passed by reference through stack // allocated memrefs. Location loc = op->getLoc(); - const auto stt = getSparseTensorType(op.getTensor()); + const auto stt = getSparseTensorType(op.getDest()); + + // Dense tensor insertion. + if (!stt.hasEncoding()) + return failure(); + + assert(stt.isIdentity() && "Run reinterpret-map before conversion."); const auto elemTp = stt.getElementType(); const Level lvlRank = stt.getLvlRank(); Value lvlCoords, vref; @@ -608,12 +615,12 @@ public: lvlCoords = genAlloca(rewriter, loc, lvlRank, rewriter.getIndexType()); vref = genAllocaScalar(rewriter, loc, elemTp); } - storeAll(rewriter, loc, lvlCoords, adaptor.getLvlCoords()); - rewriter.create<memref::StoreOp>(loc, adaptor.getValue(), vref); + storeAll(rewriter, loc, lvlCoords, adaptor.getIndices()); + rewriter.create<memref::StoreOp>(loc, adaptor.getScalar(), vref); SmallString<12> name{"lexInsert", primaryTypeFunctionSuffix(elemTp)}; createFuncCall(rewriter, loc, name, {}, - {adaptor.getTensor(), lvlCoords, vref}, EmitCInterface::On); - rewriter.replaceOp(op, adaptor.getTensor()); + {adaptor.getDest(), lvlCoords, vref}, EmitCInterface::On); + rewriter.replaceOp(op, adaptor.getDest()); return success(); } }; @@ -833,6 +840,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 //===----------------------------------------------------------------------===// @@ -861,6 +881,7 @@ void mlir::populateSparseTensorConversionPatterns(TypeConverter &typeConverter, SparseTensorToValuesConverter, SparseNumberOfEntriesConverter, SparseTensorLoadConverter, SparseTensorInsertConverter, SparseTensorExpandConverter, SparseTensorCompressConverter, - SparseTensorAssembleConverter, SparseTensorDisassembleConverter>( - typeConverter, patterns.getContext()); + 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 a65bce78d095cf49e1ba9be6b5baf6683500c6f5..17f70d0796ccfc3c949f84af4283bc3ea7ea1502 100644 --- a/mlir/lib/Dialect/SparseTensor/Transforms/SparseTensorRewriting.cpp +++ b/mlir/lib/Dialect/SparseTensor/Transforms/SparseTensorRewriting.cpp @@ -817,7 +817,8 @@ public: reshapeCvs(builder, loc, expandReass, collapsedSizes, collapsedDcvs, dstSizes, dstDcvs); - auto t = builder.create<InsertOp>(loc, v, reduc.front(), dstDcvs); + auto t = + builder.create<tensor::InsertOp>(loc, v, reduc.front(), dstDcvs); builder.create<sparse_tensor::YieldOp>(loc, t); }); @@ -901,7 +902,8 @@ public: SmallVector<Value> dstDcvs; reshapeCvs(builder, loc, op.getReassociationIndices(), srcSizes, srcDcvs, dstSizes, dstDcvs); - auto t = builder.create<InsertOp>(loc, v, reduc.front(), dstDcvs); + auto t = + builder.create<tensor::InsertOp>(loc, v, reduc.front(), dstDcvs); builder.create<sparse_tensor::YieldOp>(loc, t); }); diff --git a/mlir/lib/Dialect/SparseTensor/Transforms/Sparsification.cpp b/mlir/lib/Dialect/SparseTensor/Transforms/Sparsification.cpp index 1fb70ed5035c03b95c2ec37029d09afd3eceee3c..cd046b670d9a8e362c148af7ab6b4107e8bcaf17 100644 --- a/mlir/lib/Dialect/SparseTensor/Transforms/Sparsification.cpp +++ b/mlir/lib/Dialect/SparseTensor/Transforms/Sparsification.cpp @@ -428,7 +428,7 @@ static void genInsertionStore(CodegenEnv &env, OpBuilder &builder, OpOperand *t, /*else=*/true); // True branch. builder.setInsertionPointToStart(ifValidLexInsert.thenBlock()); - Value res = builder.create<InsertOp>(loc, rhs, chain, ivs); + Value res = builder.create<tensor::InsertOp>(loc, rhs, chain, ivs); builder.create<scf::YieldOp>(loc, res); // False branch. builder.setInsertionPointToStart(ifValidLexInsert.elseBlock()); @@ -438,7 +438,8 @@ static void genInsertionStore(CodegenEnv &env, OpBuilder &builder, OpOperand *t, env.updateInsertionChain(ifValidLexInsert.getResult(0)); } else { // Generates regular insertion chain. - env.updateInsertionChain(builder.create<InsertOp>(loc, rhs, chain, ivs)); + env.updateInsertionChain( + builder.create<tensor::InsertOp>(loc, rhs, chain, ivs)); } return; } 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/Tensor/IR/TensorDialect.cpp b/mlir/lib/Dialect/Tensor/IR/TensorDialect.cpp index 62032ff301bece2f2e155e9ddae0eeda26bc2ce5..4b3156728cc979cb3258a722df7b4b1a4a019a7b 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<ExtractSliceOp, SubsetExtractionOpInterface>(); + declarePromisedInterfaces<TilingInterface, PadOp, PackOp, UnPackOp>(); + declarePromisedInterfaces<ValueBoundsOpInterface, CastOp, DimOp, EmptyOp, + ExtractSliceOp, PadOp, RankOp>(); } 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/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/TosaOps.cpp b/mlir/lib/Dialect/Tosa/IR/TosaOps.cpp index 62d07859e32f6ecff4b6827423889f5813b66563..f461e7e1a555b88beebfc4127b075e88f4c922fc 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, 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/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..f90ac089adaa4347e37d71a5a7c7c0a3bff71e9f 100644 --- a/mlir/lib/Dialect/Transform/IR/CMakeLists.txt +++ b/mlir/lib/Dialect/Transform/IR/CMakeLists.txt @@ -2,7 +2,6 @@ add_mlir_dialect_library(MLIRTransformDialect MatchInterfaces.cpp TransformAttrs.cpp TransformDialect.cpp - TransformInterfaces.cpp TransformOps.cpp TransformTypes.cpp Utils.cpp @@ -10,7 +9,6 @@ add_mlir_dialect_library(MLIRTransformDialect DEPENDS MLIRMatchInterfacesIncGen MLIRTransformDialectIncGen - MLIRTransformInterfacesIncGen LINK_LIBS PUBLIC MLIRCastInterfaces @@ -24,5 +22,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..8d2ed8f6d737148bf3917ea2055a02f608723580 100644 --- a/mlir/lib/Dialect/Transform/IR/TransformOps.cpp +++ b/mlir/lib/Dialect/Transform/IR/TransformOps.cpp @@ -14,8 +14,8 @@ #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/TransformInterfaces.h" #include "mlir/IR/BuiltinAttributes.h" #include "mlir/IR/Diagnostics.h" #include "mlir/IR/Dominance.h" 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..7b837bde0625cb9a6092b4401a4790ec1418cc86 --- /dev/null +++ b/mlir/lib/Dialect/Transform/Interfaces/CMakeLists.txt @@ -0,0 +1,15 @@ +add_mlir_library(MLIRTransformDialectInterfaces + TransformInterfaces.cpp + + DEPENDS + MLIRTransformInterfacesIncGen + + LINK_LIBS PUBLIC + MLIRCastInterfaces + MLIRIR + MLIRRewrite + MLIRSideEffectInterfaces + MLIRTransforms + MLIRTransformDialectUtils +) + 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/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..35296824246eb6bcb7bc13ffd50dbe2c9464418a 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<TransferReadOp, SubsetExtractionOpInterface>(); + declarePromisedInterface<TransferWriteOp, SubsetInsertionOpInterface>(); } /// Materialize a single constant operation from a given attribute value with @@ -6054,7 +6064,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/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/VectorTransforms.cpp b/mlir/lib/Dialect/Vector/Transforms/VectorTransforms.cpp index a2d4e216633181f2ad4962a5a3c9fe631a7638a0..6f6b6dcdad2006db128bb93b2fc1e0c797009e90 100644 --- a/mlir/lib/Dialect/Vector/Transforms/VectorTransforms.cpp +++ b/mlir/lib/Dialect/Vector/Transforms/VectorTransforms.cpp @@ -1255,42 +1255,6 @@ getTransferFoldableInnerUnitDims(MemRefType srcType, VectorType vectorType) { return result; } -/// Returns a MemRef type that drops inner `dimsToDrop` dimensions from -/// `srcType`. E.g., if `srcType` is memref<512x16x1x1xf32> and `dimsToDrop` is -/// two, it returns memref<512x16x16> type. -static MemRefType getMemRefTypeWithDroppingInnerDims(OpBuilder &builder, - MemRefType srcType, - size_t dimsToDrop) { - MemRefLayoutAttrInterface layout = srcType.getLayout(); - if (isa<AffineMapAttr>(layout) && layout.isIdentity()) { - return MemRefType::get(srcType.getShape().drop_back(dimsToDrop), - srcType.getElementType(), nullptr, - srcType.getMemorySpace()); - } - MemRefLayoutAttrInterface updatedLayout; - if (auto strided = dyn_cast<StridedLayoutAttr>(layout)) { - auto strides = llvm::to_vector(strided.getStrides().drop_back(dimsToDrop)); - updatedLayout = StridedLayoutAttr::get(strided.getContext(), - strided.getOffset(), strides); - return MemRefType::get(srcType.getShape().drop_back(dimsToDrop), - srcType.getElementType(), updatedLayout, - srcType.getMemorySpace()); - } - - // Non-strided layout case. - AffineMap map = srcType.getLayout().getAffineMap(); - int numSymbols = map.getNumSymbols(); - for (size_t i = 0; i < dimsToDrop; ++i) { - int dim = srcType.getRank() - i - 1; - map = map.replace(builder.getAffineDimExpr(dim), - builder.getAffineConstantExpr(0), map.getNumDims() - 1, - numSymbols); - } - return MemRefType::get(srcType.getShape().drop_back(dimsToDrop), - srcType.getElementType(), updatedLayout, - srcType.getMemorySpace()); -} - /// Drop inner most contiguous unit dimensions from transfer_read operand. class DropInnerMostUnitDimsTransferRead : public OpRewritePattern<vector::TransferReadOp> { @@ -1337,8 +1301,10 @@ class DropInnerMostUnitDimsTransferRead rewriter.getIndexAttr(0)); SmallVector<OpFoldResult> strides(srcType.getRank(), rewriter.getIndexAttr(1)); - MemRefType resultMemrefType = - getMemRefTypeWithDroppingInnerDims(rewriter, srcType, dimsToDrop); + auto resultMemrefType = + cast<MemRefType>(memref::SubViewOp::inferRankReducedResultType( + srcType.getShape().drop_back(dimsToDrop), srcType, offsets, sizes, + strides)); ArrayAttr inBoundsAttr = readOp.getInBounds() ? rewriter.getArrayAttr( @@ -1421,8 +1387,10 @@ class DropInnerMostUnitDimsTransferWrite rewriter.getIndexAttr(0)); SmallVector<OpFoldResult> strides(srcType.getRank(), rewriter.getIndexAttr(1)); - MemRefType resultMemrefType = - getMemRefTypeWithDroppingInnerDims(rewriter, srcType, dimsToDrop); + auto resultMemrefType = + cast<MemRefType>(memref::SubViewOp::inferRankReducedResultType( + srcType.getShape().drop_back(dimsToDrop), srcType, offsets, sizes, + strides)); ArrayAttr inBoundsAttr = writeOp.getInBounds() ? rewriter.getArrayAttr( diff --git a/mlir/lib/Dialect/Vector/Utils/VectorUtils.cpp b/mlir/lib/Dialect/Vector/Utils/VectorUtils.cpp index d613672608c3ad8095cf7137371ea0649bde5309..63ed0947cf6ce2676ebf4c790d9266f0e2412c1c 100644 --- a/mlir/lib/Dialect/Vector/Utils/VectorUtils.cpp +++ b/mlir/lib/Dialect/Vector/Utils/VectorUtils.cpp @@ -300,3 +300,20 @@ 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; +} 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/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/SparseTensorRuntime.cpp b/mlir/lib/ExecutionEngine/SparseTensorRuntime.cpp index 731abcbbf1f39e77f45370659bf37ad82bd562da..8835056099d234ba9cbe56eb4c738504aa768007 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); \ } \ 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/AsmPrinter.cpp b/mlir/lib/IR/AsmPrinter.cpp index 8d75349f8eed4544aad03f78de9b61cc6e50af40..456cf6a2c27783e8895da5d14af16e8c704ecdae 100644 --- a/mlir/lib/IR/AsmPrinter.cpp +++ b/mlir/lib/IR/AsmPrinter.cpp @@ -1895,9 +1895,6 @@ static OpPrintingFlags verifyOpAndAdjustFlags(Operation *op, printerFlags.shouldAssumeVerified()) return printerFlags; - LLVM_DEBUG(llvm::dbgs() << DEBUG_TYPE << ": Verifying operation: " - << op->getName() << "\n"); - // Ignore errors emitted by the verifier. We check the thread id to avoid // consuming other threads' errors. auto parentThreadId = llvm::get_threadid(); 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..06ec3f4e135e9f5fb2cdc86d2958d458f076b9d9 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> 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/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/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..95c7af2f07be46b5e61c4780d0b6546784c085ac 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) { @@ -1091,12 +1102,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 +1171,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 +1192,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 +1370,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 +1447,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 +1462,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() || 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/ModuleTranslation.cpp b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp index c00628a420a000a9ba3f96d200314912d081304d..f90495d407fdfed17b7e50b1291d72c1f7659b43 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; })); 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/InlinerPass.cpp b/mlir/lib/Transforms/InlinerPass.cpp index c058e8050cd199393d2bf70664fd706442a1aafd..9a7d5403a95dc53e6386439a924ac9cc225c2f6b 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. @@ -88,6 +90,42 @@ 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(); + + // We should not get external nodes here, but just return true + // for now to preserve the original behavior of the inliner pass. + if (!callerRegion || !calleeRegion) + return true; + + 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 +138,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())) 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/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/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/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/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/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..bdc6c91d92677541e567caab52d2806ad36660fa 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 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/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/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/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..3f4d17c6a43f97fd23fcb465898837a79b123147 100644 --- a/mlir/test/Dialect/LLVMIR/sroa.mlir +++ b/mlir/test/Dialect/LLVMIR/sroa.mlir @@ -197,3 +197,124 @@ 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 +} 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/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..6326d3a71874b44e01ddc08d6ca51d686f2ebd61 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]] // ----- 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/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/SPIRV/Transforms/canonicalize.mlir b/mlir/test/Dialect/SPIRV/Transforms/canonicalize.mlir index 1cb69891a70ed6e16faec2788b507c10b8ca3521..ed0bd070c43c2f9cb15acabf7339bf401f9cdd7e 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,182 @@ func.func @const_fold_vector_inotequal() -> 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/SparseTensor/codegen.mlir b/mlir/test/Dialect/SparseTensor/codegen.mlir index b63762485c961f585cc780bd3f0bcf729bdf394b..40bfa1e4e2a501404b36db04a3c903293795f671 100644 --- a/mlir/test/Dialect/SparseTensor/codegen.mlir +++ b/mlir/test/Dialect/SparseTensor/codegen.mlir @@ -643,7 +643,7 @@ func.func @sparse_compression_unordered(%tensor: tensor<8x8xf64, #UCSR>, // CHECK: %[[R:.*]]:4 = call @_insert_compressed_128_f64_0_0(%[[A1]], %[[A2]], %[[A3]], %[[A4]], %[[A5]], %[[A6]]) // CHECK: return %[[R]]#0, %[[R]]#1, %[[R]]#2, %[[R]]#3 func.func @sparse_insert(%arg0: tensor<128xf64, #SV>, %arg1: index, %arg2: f64) -> tensor<128xf64, #SV> { - %0 = sparse_tensor.insert %arg2 into %arg0[%arg1] : tensor<128xf64, #SV> + %0 = tensor.insert %arg2 into %arg0[%arg1] : tensor<128xf64, #SV> %1 = sparse_tensor.load %0 hasInserts : tensor<128xf64, #SV> return %1 : tensor<128xf64, #SV> } @@ -666,7 +666,7 @@ func.func @sparse_insert(%arg0: tensor<128xf64, #SV>, %arg1: index, %arg2: f64) // CHECK: %[[R:.*]]:4 = call @_insert_compressed_128_f64_64_32(%[[A1]], %[[A2]], %[[A3]], %[[A4]], %[[A5]], %[[A6]]) // CHECK: return %[[R]]#0, %[[R]]#1, %[[R]]#2, %[[R]]#3 func.func @sparse_insert_typed(%arg0: tensor<128xf64, #SparseVector>, %arg1: index, %arg2: f64) -> tensor<128xf64, #SparseVector> { - %0 = sparse_tensor.insert %arg2 into %arg0[%arg1] : tensor<128xf64, #SparseVector> + %0 = tensor.insert %arg2 into %arg0[%arg1] : tensor<128xf64, #SparseVector> %1 = sparse_tensor.load %0 hasInserts : tensor<128xf64, #SparseVector> return %1 : tensor<128xf64, #SparseVector> } @@ -690,7 +690,7 @@ func.func @sparse_insert_typed(%arg0: tensor<128xf64, #SparseVector>, %arg1: ind // CHECK: %[[R:.*]]:4 = call @_insert_compressed_nonunique_singleton_5_6_f64_0_0(%[[A0]], %[[A1]], %[[A2]], %[[A3]], %[[A4]], %[[A4]], %[[A5]]) // CHECK: return %[[R]]#0, %[[R]]#1, %[[R]]#2, %[[R]]#3 func.func @sparse_insert_coo(%arg0: tensor<5x6xf64, #Coo>, %arg1: index, %arg2: f64) -> tensor<5x6xf64, #Coo> { - %0 = sparse_tensor.insert %arg2 into %arg0[%arg1, %arg1] : tensor<5x6xf64, #Coo> + %0 = tensor.insert %arg2 into %arg0[%arg1, %arg1] : tensor<5x6xf64, #Coo> %1 = sparse_tensor.load %0 hasInserts : tensor<5x6xf64, #Coo> return %1 : tensor<5x6xf64, #Coo> } diff --git a/mlir/test/Dialect/SparseTensor/constant_index_map.mlir b/mlir/test/Dialect/SparseTensor/constant_index_map.mlir index eaef6a3158529204f53f1b19129682f06d6ede1e..f9559ce648c7834bff3456062a0afba5017d4755 100644 --- a/mlir/test/Dialect/SparseTensor/constant_index_map.mlir +++ b/mlir/test/Dialect/SparseTensor/constant_index_map.mlir @@ -20,7 +20,7 @@ // CHECK: %[[VAL_11:.*]] = memref.load %[[VAL_6]]{{\[}}%[[VAL_3]], %[[VAL_9]]] : memref<1x77xi1> // CHECK: %[[VAL_12:.*]] = memref.load %[[VAL_7]]{{\[}}%[[VAL_3]], %[[VAL_9]]] : memref<1x77xi1> // CHECK: %[[VAL_13:.*]] = arith.addi %[[VAL_11]], %[[VAL_12]] : i1 -// CHECK: %[[VAL_14:.*]] = sparse_tensor.insert %[[VAL_13]] into %[[VAL_10]]{{\[}}%[[VAL_9]]] : tensor<77xi1, #{{.*}}> +// CHECK: %[[VAL_14:.*]] = tensor.insert %[[VAL_13]] into %[[VAL_10]]{{\[}}%[[VAL_9]]] : tensor<77xi1, #{{.*}}> // CHECK: scf.yield %[[VAL_14]] : tensor<77xi1, #{{.*}}> // CHECK: } // CHECK: %[[VAL_15:.*]] = sparse_tensor.load %[[VAL_16:.*]] hasInserts : tensor<77xi1, #{{.*}}> diff --git a/mlir/test/Dialect/SparseTensor/conversion.mlir b/mlir/test/Dialect/SparseTensor/conversion.mlir index 465f21086266065ec8796fe2a5cfc5eb4534aba7..f23f6ac4f181e29dd470727102709bff06d58fe3 100644 --- a/mlir/test/Dialect/SparseTensor/conversion.mlir +++ b/mlir/test/Dialect/SparseTensor/conversion.mlir @@ -318,7 +318,7 @@ func.func @sparse_reconstruct_ins(%arg0: tensor<128xf32, #SparseVector>) -> tens func.func @sparse_insert(%arg0: tensor<128xf32, #SparseVector>, %arg1: index, %arg2: f32) -> tensor<128xf32, #SparseVector> { - %0 = sparse_tensor.insert %arg2 into %arg0[%arg1] : tensor<128xf32, #SparseVector> + %0 = tensor.insert %arg2 into %arg0[%arg1] : tensor<128xf32, #SparseVector> return %0 : tensor<128xf32, #SparseVector> } diff --git a/mlir/test/Dialect/SparseTensor/invalid.mlir b/mlir/test/Dialect/SparseTensor/invalid.mlir index eac97f702f58bd8e3e4d2b899c486ada0aa1c806..18851f29d8eaa36e541457d84fe99ce3021cbc8e 100644 --- a/mlir/test/Dialect/SparseTensor/invalid.mlir +++ b/mlir/test/Dialect/SparseTensor/invalid.mlir @@ -290,24 +290,6 @@ func.func @sparse_unannotated_load(%arg0: tensor<16x32xf64>) -> tensor<16x32xf64 // ----- -func.func @sparse_unannotated_insert(%arg0: tensor<128xf64>, %arg1: index, %arg2: f64) { - // expected-error@+1 {{'sparse_tensor.insert' 'tensor' must be sparse tensor of any type values, but got 'tensor<128xf64>'}} - sparse_tensor.insert %arg2 into %arg0[%arg1] : tensor<128xf64> - return -} - -// ----- - -#CSR = #sparse_tensor.encoding<{map = (d0, d1) -> (d0 : dense, d1 : compressed)}> - -func.func @sparse_wrong_arity_insert(%arg0: tensor<128x64xf64, #CSR>, %arg1: index, %arg2: f64) { - // expected-error@+1 {{'sparse_tensor.insert' op incorrect number of coordinates}} - sparse_tensor.insert %arg2 into %arg0[%arg1] : tensor<128x64xf64, #CSR> - return -} - -// ----- - func.func @sparse_push_back(%arg0: index, %arg1: memref<?xf64>, %arg2: f32) -> (memref<?xf64>, index) { // expected-error@+1 {{'sparse_tensor.push_back' op failed to verify that value type matches element type of inBuffer}} %0:2 = sparse_tensor.push_back %arg0, %arg1, %arg2 : index, memref<?xf64>, f32 @@ -886,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/roundtrip.mlir b/mlir/test/Dialect/SparseTensor/roundtrip.mlir index 41094fbad9218f5f31fd593c1791faa88c0f6bee..a47a3d5119f96d4c2bfd34e127e0a3ed659611b9 100644 --- a/mlir/test/Dialect/SparseTensor/roundtrip.mlir +++ b/mlir/test/Dialect/SparseTensor/roundtrip.mlir @@ -311,10 +311,10 @@ func.func @sparse_load_ins(%arg0: tensor<16x32xf64, #DenseMatrix>) -> tensor<16x // CHECK-SAME: %[[A:.*]]: tensor<128xf64, #sparse{{[0-9]*}}>, // CHECK-SAME: %[[B:.*]]: index, // CHECK-SAME: %[[C:.*]]: f64) -// CHECK: %[[T:.*]] = sparse_tensor.insert %[[C]] into %[[A]][%[[B]]] : tensor<128xf64, #{{.*}}> +// CHECK: %[[T:.*]] = tensor.insert %[[C]] into %[[A]][%[[B]]] : tensor<128xf64, #{{.*}}> // CHECK: return %[[T]] : tensor<128xf64, #{{.*}}> func.func @sparse_insert(%arg0: tensor<128xf64, #SparseVector>, %arg1: index, %arg2: f64) -> tensor<128xf64, #SparseVector> { - %0 = sparse_tensor.insert %arg2 into %arg0[%arg1] : tensor<128xf64, #SparseVector> + %0 = tensor.insert %arg2 into %arg0[%arg1] : tensor<128xf64, #SparseVector> return %0 : tensor<128xf64, #SparseVector> } @@ -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/SparseTensor/sparse_2d.mlir b/mlir/test/Dialect/SparseTensor/sparse_2d.mlir index 85ae0db916899eabdd2e86d1ac8c791dfe64b941..4afa0a8ceccd4b5f05890b99afb3175a0f6f6ca6 100644 --- a/mlir/test/Dialect/SparseTensor/sparse_2d.mlir +++ b/mlir/test/Dialect/SparseTensor/sparse_2d.mlir @@ -1090,20 +1090,20 @@ func.func @cmp_ss_ss(%arga: tensor<32x16xf32, #Tss>, %argb: tensor<32x16xf32, #T // CHECK: %[[VAL_41:.*]] = memref.load %[[VAL_8]]{{\[}}%[[VAL_30]]] : memref<?xf64> // CHECK: %[[VAL_42:.*]] = memref.load %[[VAL_11]]{{\[}}%[[VAL_31]]] : memref<?xf64> // CHECK: %[[VAL_43:.*]] = arith.subf %[[VAL_41]], %[[VAL_42]] : f64 -// CHECK: %[[VAL_44:.*]] = sparse_tensor.insert %[[VAL_43]] into %[[VAL_32]]{{\[}}%[[VAL_13]], %[[VAL_36]]] : tensor<2x3xf64, #sparse{{[0-9]*}}> +// CHECK: %[[VAL_44:.*]] = tensor.insert %[[VAL_43]] into %[[VAL_32]]{{\[}}%[[VAL_13]], %[[VAL_36]]] : tensor<2x3xf64, #sparse{{[0-9]*}}> // CHECK: scf.yield %[[VAL_44]] : tensor<2x3xf64, #sparse{{[0-9]*}}> // CHECK: } else { // CHECK: %[[VAL_45:.*]] = arith.cmpi eq, %[[VAL_33]], %[[VAL_36]] : index // CHECK: %[[VAL_46:.*]] = scf.if %[[VAL_45]] -> (tensor<2x3xf64, #sparse{{[0-9]*}}>) { // CHECK: %[[VAL_47:.*]] = memref.load %[[VAL_8]]{{\[}}%[[VAL_30]]] : memref<?xf64> -// CHECK: %[[VAL_48:.*]] = sparse_tensor.insert %[[VAL_47]] into %[[VAL_32]]{{\[}}%[[VAL_13]], %[[VAL_36]]] : tensor<2x3xf64, #sparse{{[0-9]*}}> +// CHECK: %[[VAL_48:.*]] = tensor.insert %[[VAL_47]] into %[[VAL_32]]{{\[}}%[[VAL_13]], %[[VAL_36]]] : tensor<2x3xf64, #sparse{{[0-9]*}}> // CHECK: scf.yield %[[VAL_48]] : tensor<2x3xf64, #sparse{{[0-9]*}}> // CHECK: } else { // CHECK: %[[VAL_49:.*]] = arith.cmpi eq, %[[VAL_34]], %[[VAL_36]] : index // CHECK: %[[VAL_50:.*]] = scf.if %[[VAL_49]] -> (tensor<2x3xf64, #sparse{{[0-9]*}}>) { // CHECK: %[[VAL_51:.*]] = memref.load %[[VAL_11]]{{\[}}%[[VAL_31]]] : memref<?xf64> // CHECK: %[[VAL_52:.*]] = arith.negf %[[VAL_51]] : f64 -// CHECK: %[[VAL_53:.*]] = sparse_tensor.insert %[[VAL_52]] into %[[VAL_32]]{{\[}}%[[VAL_13]], %[[VAL_36]]] : tensor<2x3xf64, #sparse{{[0-9]*}}> +// CHECK: %[[VAL_53:.*]] = tensor.insert %[[VAL_52]] into %[[VAL_32]]{{\[}}%[[VAL_13]], %[[VAL_36]]] : tensor<2x3xf64, #sparse{{[0-9]*}}> // CHECK: scf.yield %[[VAL_53]] : tensor<2x3xf64, #sparse{{[0-9]*}}> // CHECK: } else { // CHECK: scf.yield %[[VAL_32]] : tensor<2x3xf64, #sparse{{[0-9]*}}> @@ -1123,14 +1123,14 @@ func.func @cmp_ss_ss(%arga: tensor<32x16xf32, #Tss>, %argb: tensor<32x16xf32, #T // CHECK: %[[VAL_63:.*]] = scf.for %[[VAL_64:.*]] = %[[VAL_65:.*]]#0 to %[[VAL_18]] step %[[VAL_4]] iter_args(%[[VAL_66:.*]] = %[[VAL_65]]#2) // CHECK: %[[VAL_67:.*]] = memref.load %[[VAL_7]]{{\[}}%[[VAL_64]]] : memref<?xindex> // CHECK: %[[VAL_68:.*]] = memref.load %[[VAL_8]]{{\[}}%[[VAL_64]]] : memref<?xf64> -// CHECK: %[[VAL_69:.*]] = sparse_tensor.insert %[[VAL_68]] into %[[VAL_66]]{{\[}}%[[VAL_13]], %[[VAL_67]]] : tensor<2x3xf64, #sparse{{[0-9]*}}> +// CHECK: %[[VAL_69:.*]] = tensor.insert %[[VAL_68]] into %[[VAL_66]]{{\[}}%[[VAL_13]], %[[VAL_67]]] : tensor<2x3xf64, #sparse{{[0-9]*}}> // CHECK: scf.yield %[[VAL_69]] : tensor<2x3xf64, #sparse{{[0-9]*}}> // CHECK: } // CHECK: %[[VAL_70:.*]] = scf.for %[[VAL_71:.*]] = %[[VAL_72:.*]]#1 to %[[VAL_22]] step %[[VAL_4]] iter_args(%[[VAL_73:.*]] = %[[VAL_74:.*]]) // CHECK: %[[VAL_75:.*]] = memref.load %[[VAL_10]]{{\[}}%[[VAL_71]]] : memref<?xindex> // CHECK: %[[VAL_76:.*]] = memref.load %[[VAL_11]]{{\[}}%[[VAL_71]]] : memref<?xf64> // CHECK: %[[VAL_77:.*]] = arith.negf %[[VAL_76]] : f64 -// CHECK: %[[VAL_78:.*]] = sparse_tensor.insert %[[VAL_77]] into %[[VAL_73]]{{\[}}%[[VAL_13]], %[[VAL_75]]] : tensor<2x3xf64, #sparse{{[0-9]*}}> +// CHECK: %[[VAL_78:.*]] = tensor.insert %[[VAL_77]] into %[[VAL_73]]{{\[}}%[[VAL_13]], %[[VAL_75]]] : tensor<2x3xf64, #sparse{{[0-9]*}}> // CHECK: scf.yield %[[VAL_78]] : tensor<2x3xf64, #sparse{{[0-9]*}}> // CHECK: } // CHECK: scf.yield %[[VAL_79:.*]] : tensor<2x3xf64, #sparse{{[0-9]*}}> diff --git a/mlir/test/Dialect/SparseTensor/sparse_broadcast.mlir b/mlir/test/Dialect/SparseTensor/sparse_broadcast.mlir index 278450fabd74ec29fb97374d73df84e057209b25..a409329700ffd78c4ec16ca75fd31d75a01e9508 100644 --- a/mlir/test/Dialect/SparseTensor/sparse_broadcast.mlir +++ b/mlir/test/Dialect/SparseTensor/sparse_broadcast.mlir @@ -33,7 +33,7 @@ // CHECK: %[[L2:.*]] = scf.for %[[TMP_arg3:.*]] = %[[TMP_10]] to %[[TMP_12]] step %[[TMP_c1]] {{.*}} { // CHECK: %[[TMP_13:.*]] = memref.load %[[TMP_4]][%[[TMP_arg3]]] : memref<?xindex> // CHECK: %[[TMP_14:.*]] = memref.load %[[TMP_5]][%[[TMP_arg3]]] : memref<?xi32> -// CHECK: %[[Y:.*]] = sparse_tensor.insert %[[TMP_14]] into %{{.*}}[%[[TMP_9]], %[[TMP_arg2]], %[[TMP_13]]] +// CHECK: %[[Y:.*]] = tensor.insert %[[TMP_14]] into %{{.*}}[%[[TMP_9]], %[[TMP_arg2]], %[[TMP_13]]] // CHECK: scf.yield %[[Y]] // CHECK: } // CHECK: scf.yield %[[L2]] diff --git a/mlir/test/Dialect/SparseTensor/sparse_conv_2d_slice_based.mlir b/mlir/test/Dialect/SparseTensor/sparse_conv_2d_slice_based.mlir index 6076c1fbe76f21d0e452c3da02685df27c7334f0..bf3473ead204ebcd2ad68bf37bbdfd1fa974a51b 100644 --- a/mlir/test/Dialect/SparseTensor/sparse_conv_2d_slice_based.mlir +++ b/mlir/test/Dialect/SparseTensor/sparse_conv_2d_slice_based.mlir @@ -41,7 +41,7 @@ // CHECK: scf.yield // CHECK: } // CHECK: scf.if {{.*}} { -// CHECK: sparse_tensor.insert %{{.*}} into %{{.*}}{{\[}}%[[D0]], %[[D1]]] +// CHECK: tensor.insert %{{.*}} into %{{.*}}{{\[}}%[[D0]], %[[D1]]] // CHECK: scf.yield // CHECK: } else { // CHECK: scf.yield diff --git a/mlir/test/Dialect/SparseTensor/sparse_fp_ops.mlir b/mlir/test/Dialect/SparseTensor/sparse_fp_ops.mlir index 8c09523174bd76e7de19d72d828aff11bdf85c2e..07b2c3c22995d15987b9957aa987e37030eec271 100644 --- a/mlir/test/Dialect/SparseTensor/sparse_fp_ops.mlir +++ b/mlir/test/Dialect/SparseTensor/sparse_fp_ops.mlir @@ -371,7 +371,7 @@ func.func @divbyc(%arga: tensor<32xf64, #SV>, // CHECK: %[[VAL_17:.*]] = math.log1p %[[VAL_16]] : f64 // CHECK: %[[VAL_18:.*]] = math.sin %[[VAL_17]] : f64 // CHECK: %[[VAL_19:.*]] = math.tanh %[[VAL_18]] : f64 -// CHECK: %[[Y:.*]] = sparse_tensor.insert %[[VAL_19]] into %{{.*}}[%[[VAL_10]]] : tensor<32xf64, #sparse{{[0-9]*}}> +// CHECK: %[[Y:.*]] = tensor.insert %[[VAL_19]] into %{{.*}}[%[[VAL_10]]] : tensor<32xf64, #sparse{{[0-9]*}}> // CHECK: scf.yield %[[Y]] // CHECK: } // CHECK: %[[VAL_20:.*]] = sparse_tensor.load %[[T]] hasInserts : tensor<32xf64, #sparse{{[0-9]*}}> @@ -412,7 +412,7 @@ func.func @zero_preserving_math(%arga: tensor<32xf64, #SV>) -> tensor<32xf64, #S // CHECK: %[[VAL_11:.*]] = memref.load %[[VAL_6]]{{\[}}%[[VAL_10]]] : memref<?xindex> // CHECK: %[[VAL_12:.*]] = memref.load %[[VAL_7]]{{\[}}%[[VAL_10]]] : memref<?xcomplex<f64>> // CHECK: %[[VAL_13:.*]] = complex.div %[[VAL_12]], %[[VAL_3]] : complex<f64> -// CHECK: %[[Y:.*]] = sparse_tensor.insert %[[VAL_13]] into %{{.*}}[%[[VAL_11]]] : tensor<32xcomplex<f64>, #sparse{{[0-9]*}}> +// CHECK: %[[Y:.*]] = tensor.insert %[[VAL_13]] into %{{.*}}[%[[VAL_11]]] : tensor<32xcomplex<f64>, #sparse{{[0-9]*}}> // CHECK: scf.yield %[[Y]] // CHECK: } // CHECK: %[[VAL_14:.*]] = sparse_tensor.load %[[T]] hasInserts : tensor<32xcomplex<f64>, #sparse{{[0-9]*}}> diff --git a/mlir/test/Dialect/SparseTensor/sparse_index.mlir b/mlir/test/Dialect/SparseTensor/sparse_index.mlir index 3e8b485f63df9757560609821e43b800ff5f62b1..7fe662893f4b1808bbdf087f1bff8d0dad31b8f0 100644 --- a/mlir/test/Dialect/SparseTensor/sparse_index.mlir +++ b/mlir/test/Dialect/SparseTensor/sparse_index.mlir @@ -95,7 +95,7 @@ func.func @dense_index(%arga: tensor<?x?xi64, #DenseMatrix>) // CHECK: %[[VAL_22:.*]] = memref.load %[[VAL_10]]{{\[}}%[[VAL_18]]] : memref<?xi64> // CHECK: %[[VAL_23:.*]] = arith.muli %[[VAL_21]], %[[VAL_22]] : i64 // CHECK: %[[VAL_24:.*]] = arith.muli %[[VAL_20]], %[[VAL_23]] : i64 -// CHECK: %[[Y:.*]] = sparse_tensor.insert %[[VAL_24]] into %{{.*}}[%[[VAL_14]], %[[VAL_19]]] : tensor<?x?xi64, #sparse{{[0-9]*}}> +// CHECK: %[[Y:.*]] = tensor.insert %[[VAL_24]] into %{{.*}}[%[[VAL_14]], %[[VAL_19]]] : tensor<?x?xi64, #sparse{{[0-9]*}}> // CHECK: scf.yield %[[Y]] // CHECK: } // CHECK: scf.yield %[[L]] diff --git a/mlir/test/Dialect/SparseTensor/sparse_out.mlir b/mlir/test/Dialect/SparseTensor/sparse_out.mlir index b1795ff2e1a2268ab74a51ef299b356b4be5a03e..08b81b54a9e63ce5f984e801b7eebd0051bc391b 100644 --- a/mlir/test/Dialect/SparseTensor/sparse_out.mlir +++ b/mlir/test/Dialect/SparseTensor/sparse_out.mlir @@ -114,7 +114,7 @@ func.func @sparse_simply_dynamic2(%argx: tensor<32x16xf32, #DCSR>) -> tensor<32x // CHECK: %[[VAL_18:.*]] = memref.load %[[VAL_7]]{{\[}}%[[VAL_16]]] : memref<?xindex> // CHECK: %[[VAL_19:.*]] = memref.load %[[VAL_8]]{{\[}}%[[VAL_16]]] : memref<?xf32> // CHECK: %[[VAL_20:.*]] = arith.mulf %[[VAL_19]], %[[VAL_4]] : f32 -// CHECK: %[[VAL_21:.*]] = sparse_tensor.insert %[[VAL_20]] into %[[VAL_17]]{{\[}}%[[VAL_10]], %[[VAL_18]]] : tensor<10x20xf32, #sparse{{[0-9]*}}> +// CHECK: %[[VAL_21:.*]] = tensor.insert %[[VAL_20]] into %[[VAL_17]]{{\[}}%[[VAL_10]], %[[VAL_18]]] : tensor<10x20xf32, #sparse{{[0-9]*}}> // CHECK: scf.yield %[[VAL_21]] : tensor<10x20xf32, #sparse{{[0-9]*}}> // CHECK: } // CHECK: scf.yield %[[VAL_22:.*]] : tensor<10x20xf32, #sparse{{[0-9]*}}> @@ -248,7 +248,7 @@ func.func @sparse_truly_dynamic(%arga: tensor<10x20xf32, #CSR>) -> tensor<10x20x // CHECK: scf.yield %[[VAL_100]], %[[VAL_103]], %[[VAL_104:.*]]#0, %[[VAL_104]]#1, %[[VAL_104]]#2 : index, index, i32, i1, tensor<?x?xi32, #sparse{{[0-9]*}}> // CHECK: } // CHECK: %[[VAL_202:.*]] = scf.if %[[VAL_74]]#3 -> (tensor<?x?xi32, #sparse{{[0-9]*}}>) { -// CHECK: %[[VAL_105:.*]] = sparse_tensor.insert %[[VAL_74]]#2 into %[[VAL_74]]#4{{\[}}%[[VAL_39]], %[[VAL_63]]] : tensor<?x?xi32, #sparse{{[0-9]*}}> +// CHECK: %[[VAL_105:.*]] = tensor.insert %[[VAL_74]]#2 into %[[VAL_74]]#4{{\[}}%[[VAL_39]], %[[VAL_63]]] : tensor<?x?xi32, #sparse{{[0-9]*}}> // CHECK: scf.yield %[[VAL_105]] : tensor<?x?xi32, #sparse{{[0-9]*}}> // CHECK: } else { // CHECK: scf.yield %[[VAL_74]]#4 : tensor<?x?xi32, #sparse{{[0-9]*}}> diff --git a/mlir/test/Dialect/SparseTensor/sparse_reinterpret_map.mlir b/mlir/test/Dialect/SparseTensor/sparse_reinterpret_map.mlir index aa17261724dbc0bc2e308303e80278e8b8281bb2..97c668716eecc32b282d056d006efda29533b30e 100644 --- a/mlir/test/Dialect/SparseTensor/sparse_reinterpret_map.mlir +++ b/mlir/test/Dialect/SparseTensor/sparse_reinterpret_map.mlir @@ -63,7 +63,7 @@ func.func @mul(%arg0: tensor<32x32xf32>, // CHECK: %[[VAL_2:.*]] = sparse_tensor.reinterpret_map %[[VAL_0]] : tensor<2x4xf64, #[[$remap]]> to tensor<1x2x2x2xf64, #[[$demap]]> // CHECK: %[[VAL_4:.*]] = sparse_tensor.foreach in %[[VAL_2]] init(%[[VAL_1]]) // CHECK: ^bb0(%[[VAL_5:.*]]: index, %[[VAL_6:.*]]: index, %[[VAL_7:.*]]: index, %[[VAL_8:.*]]: index, %[[VAL_9:.*]]: f64, %[[VAL_10:.*]]: tensor<1x2x2x2xf64, #[[$demap]]> -// CHECK: %[[VAL_11:.*]] = sparse_tensor.insert %[[VAL_9]] into %[[VAL_10]]{{\[}}%[[VAL_5]], %[[VAL_6]], %[[VAL_7]], %[[VAL_8]]] : tensor<1x2x2x2xf64, #[[$demap]]> +// CHECK: %[[VAL_11:.*]] = tensor.insert %[[VAL_9]] into %[[VAL_10]]{{\[}}%[[VAL_5]], %[[VAL_6]], %[[VAL_7]], %[[VAL_8]]] : tensor<1x2x2x2xf64, #[[$demap]]> // CHECK: sparse_tensor.yield %[[VAL_11]] : tensor<1x2x2x2xf64, #sparse{{[0-9]*}}> // CHECK: } // CHECK: %[[VAL_12:.*]] = sparse_tensor.reinterpret_map %[[VAL_4]] : tensor<1x2x2x2xf64, #[[$demap]]> to tensor<2x4xf64, #[[$remap]]> diff --git a/mlir/test/Dialect/SparseTensor/sparse_reshape.mlir b/mlir/test/Dialect/SparseTensor/sparse_reshape.mlir index eea77c6e5a6cc6b990fb4cfc1e093b7442b73640..edb53fa024c26b6bcd19cf190d912372f5ecbbf5 100644 --- a/mlir/test/Dialect/SparseTensor/sparse_reshape.mlir +++ b/mlir/test/Dialect/SparseTensor/sparse_reshape.mlir @@ -31,7 +31,7 @@ // CHECK: %[[SV:.*]] = memref.load %[[V]]{{\[}}%[[I]]] : memref<?xf64> // CHECK: %[[DI0:.*]] = arith.divui %[[SI]], %[[C10]] : index // CHECK: %[[DI1:.*]] = arith.remui %[[SI]], %[[C10]] : index -// CHECK: %[[NT:.*]] = sparse_tensor.insert %[[SV]] into %[[R]]{{\[}}%[[DI0]], %[[DI1]]] +// CHECK: %[[NT:.*]] = tensor.insert %[[SV]] into %[[R]]{{\[}}%[[DI0]], %[[DI1]]] // CHECK: scf.yield %[[NT:.*]] // CHECK: } // CHECK: %[[NT1:.*]] = sparse_tensor.load %[[RET]] hasInserts @@ -75,7 +75,7 @@ func.func @sparse_expand(%arg0: tensor<100xf64, #SparseVector>) -> tensor<10x10x // CHECK: %[[SV:.*]] = memref.load %[[V]]{{\[}}%[[J]]] : memref<?xf64> // CHECK: %[[T:.*]] = arith.muli %[[SI0]], %[[C10]] : index // CHECK: %[[DI:.*]] = arith.addi %[[T]], %[[SI1]] : index -// CHECK: %[[R1:.*]] = sparse_tensor.insert %[[SV]] into %[[A1]]{{\[}}%[[DI]]] +// CHECK: %[[R1:.*]] = tensor.insert %[[SV]] into %[[A1]]{{\[}}%[[DI]]] // CHECK scf.yield %[[R1]] // CHECK } // CHECK scf.yield %[[RET_1]] @@ -120,7 +120,7 @@ func.func @sparse_collapse(%arg0: tensor<10x10xf64, #SparseMatrix>) -> tensor<10 // CHECK: %[[T3:.*]] = arith.remui %[[SI]], %[[T2]] : index // CHECK: %[[T4:.*]] = arith.divui %[[T2]], %[[C10]] : index // CHECK: %[[DI1:.*]] = arith.divui %[[T3]], %[[T4]] : index -// CHECK: %[[NT:.*]] = sparse_tensor.insert %[[SV]] into %[[R]]{{\[}}%[[DI0]], %[[DI1]]] +// CHECK: %[[NT:.*]] = tensor.insert %[[SV]] into %[[R]]{{\[}}%[[DI0]], %[[DI1]]] // CHECK: scf.yield %[[NT]] // CHECK: } // CHECK: %[[NT1:.*]] = sparse_tensor.load %[[RET]] hasInserts @@ -169,7 +169,7 @@ func.func @dynamic_sparse_expand(%arg0: tensor<?xf64, #SparseVector>) -> tensor< // CHECK: %[[T3:.*]] = arith.divui %[[T1]], %[[SD1]] : index // CHECK: %[[T4:.*]] = arith.muli %[[SI1]], %[[T3]] : index // CHECK: %[[DI:.*]] = arith.addi %[[T2]], %[[T4]] : index -// CHECK: %[[NT:.*]] = sparse_tensor.insert %[[SV]] into %[[R1]]{{\[}}%[[DI]]] +// CHECK: %[[NT:.*]] = tensor.insert %[[SV]] into %[[R1]]{{\[}}%[[DI]]] // CHECK scf.yield %[[NT]] // CHECK } // CHECK scf.yield %[[RET_1]] diff --git a/mlir/test/Dialect/SparseTensor/sparse_tensor_reshape.mlir b/mlir/test/Dialect/SparseTensor/sparse_tensor_reshape.mlir index 47d24ebf24fc6afaf0bbe2677328d51f973e0c5c..89826ebfe14d1a19576374711241c2a364e2f5e0 100644 --- a/mlir/test/Dialect/SparseTensor/sparse_tensor_reshape.mlir +++ b/mlir/test/Dialect/SparseTensor/sparse_tensor_reshape.mlir @@ -29,7 +29,7 @@ // CHECK: %[[DI:.*]] = arith.addi %[[T]], %[[SI1]] : index // CHECK: %[[D:.*]] = arith.divui %[[DI]], %[[C10]] : index // CHECK: %[[R:.*]] = arith.remui %[[DI]], %[[C10]] : index -// CHECK: %[[R1:.*]] = sparse_tensor.insert %[[SV]] into %[[A1]]{{\[}}%[[D]], %[[R]]] +// CHECK: %[[R1:.*]] = tensor.insert %[[SV]] into %[[A1]]{{\[}}%[[D]], %[[R]]] // CHECK: scf.yield %[[R1]] // CHECK: } // CHECK: scf.yield %[[RET_1]] diff --git a/mlir/test/Dialect/SparseTensor/sparse_transpose.mlir b/mlir/test/Dialect/SparseTensor/sparse_transpose.mlir index 80a989d789df21e3a5c71279b5218ea71c8ff56d..5038e977688dc90a43ad6cf13fcb19dbe41e8b46 100644 --- a/mlir/test/Dialect/SparseTensor/sparse_transpose.mlir +++ b/mlir/test/Dialect/SparseTensor/sparse_transpose.mlir @@ -37,7 +37,7 @@ // CHECK: %[[VAL_19:.*]] = scf.for %[[VAL_20:.*]] = %[[VAL_16]] to %[[VAL_18]] step %[[VAL_2]] iter_args(%[[VAL_21:.*]] = %[[VAL_14]]) -> (tensor<4x3xf64, #sparse{{[0-9]*}}>) { // CHECK: %[[VAL_22:.*]] = memref.load %[[VAL_8]]{{\[}}%[[VAL_20]]] : memref<?xindex> // CHECK: %[[VAL_23:.*]] = memref.load %[[VAL_9]]{{\[}}%[[VAL_20]]] : memref<?xf64> -// CHECK: %[[VAL_24:.*]] = sparse_tensor.insert %[[VAL_23]] into %[[VAL_21]]{{\[}}%[[VAL_15]], %[[VAL_22]]] : tensor<4x3xf64, #sparse{{[0-9]*}}> +// CHECK: %[[VAL_24:.*]] = tensor.insert %[[VAL_23]] into %[[VAL_21]]{{\[}}%[[VAL_15]], %[[VAL_22]]] : tensor<4x3xf64, #sparse{{[0-9]*}}> // CHECK: scf.yield %[[VAL_24]] : tensor<4x3xf64, #sparse{{[0-9]*}}> // CHECK: } // CHECK: scf.yield %[[VAL_25:.*]] : tensor<4x3xf64, #sparse{{[0-9]*}}> diff --git a/mlir/test/Dialect/Tensor/canonicalize.mlir b/mlir/test/Dialect/Tensor/canonicalize.mlir index e5374f031be5530949be0d876f6dd575c22e7b28..9ab54fe9c133db36a1ac10b9d21a35910ed3320f 100644 --- a/mlir/test/Dialect/Tensor/canonicalize.mlir +++ b/mlir/test/Dialect/Tensor/canonicalize.mlir @@ -2367,3 +2367,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/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-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/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/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/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..4ba51c5953d13caa4f60280bee8db746306bf64a 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 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-collapse-inner-most-dims.mlir b/mlir/test/Dialect/Vector/vector-transfer-collapse-inner-most-dims.mlir index 3984f17f9e8cdb73b4360db909c99e6395c579cd..477755b66c020c72aad61254b6a3a5ed17b7847b 100644 --- a/mlir/test/Dialect/Vector/vector-transfer-collapse-inner-most-dims.mlir +++ b/mlir/test/Dialect/Vector/vector-transfer-collapse-inner-most-dims.mlir @@ -16,22 +16,27 @@ func.func @contiguous_inner_most_view(%in: memref<1x1x8x1xf32, strided<[3072, 8, // ----- -func.func @contiguous_outer_dyn_inner_most_view(%in: memref<?x1x8x1xf32, strided<[3072, 8, 1, 1], offset: ?>>) -> vector<1x8x1xf32>{ +func.func @contiguous_outer_dyn_inner_most_view(%a: index, %b: index, %memref: memref<?x?x8x1xf32>) -> vector<8x1xf32> { %c0 = arith.constant 0 : index - %cst = arith.constant 0.0 : f32 - %0 = vector.transfer_read %in[%c0, %c0, %c0, %c0], %cst {in_bounds = [true, true, true]} : memref<?x1x8x1xf32, strided<[3072, 8, 1, 1], offset: ?>>, vector<1x8x1xf32> - return %0 : vector<1x8x1xf32> + %pad = arith.constant 0.0 : f32 + %v = vector.transfer_read %memref[%a, %b, %c0, %c0], %pad {in_bounds = [true, true]} : memref<?x?x8x1xf32>, vector<8x1xf32> + return %v : vector<8x1xf32> } -// CHECK: func @contiguous_outer_dyn_inner_most_view( +// CHECK: func.func @contiguous_outer_dyn_inner_most_view( +// CHECK-SAME: %[[IDX0:[a-zA-Z0-9]+]] +// CHECK-SAME: %[[IDX1:[a-zA-Z0-9]+]] // CHECK-SAME: %[[SRC:[a-zA-Z0-9]+]] -// CHECK-DAG: %[[C0:.+]] = arith.constant 0 : index -// CHECK-DAG: %[[D0:.+]] = memref.dim %[[SRC]], %[[C0]] -// CHECK: %[[SRC_0:.+]] = memref.subview %[[SRC]][0, 0, 0, 0] [%[[D0]], 1, 8, 1] [1, 1, 1, 1] -// CHECK-SAME: memref<?x1x8x1xf32, strided<[3072, 8, 1, 1], offset: ?>> to memref<?x1x8xf32, strided<[3072, 8, 1], offset: ?>> -// CHECK: %[[VEC:.+]] = vector.transfer_read %[[SRC_0]] -// CHECK-SAME: memref<?x1x8xf32, strided<[3072, 8, 1], offset: ?>>, vector<1x8xf32> -// CHECK: %[[RESULT:.+]] = vector.shape_cast %[[VEC]] -// CHECK: return %[[RESULT]] +// CHECK-DAG: %[[C0:.+]] = arith.constant 0 : index +// CHECK-DAG: %[[C1:.+]] = arith.constant 1 : index +// CHECK-DAG: %[[PAD:.+]] = arith.constant 0.000000e+00 : f32 +// CHECK: %[[D0:.+]] = memref.dim %[[SRC]], %[[C0]] +// CHECK: %[[D1:.+]] = memref.dim %[[SRC]], %[[C1]] +// CHECK: %[[VIEW:.+]] = memref.subview %[[SRC]][0, 0, 0, 0] [%[[D0]], %[[D1]], 8, 1] [1, 1, 1, 1] +// CHECK-SAME: memref<?x?x8x1xf32> to memref<?x?x8xf32, strided<[?, 8, 1], offset: ?>> +// CHECK: %[[VEC:.+]] = vector.transfer_read %[[VIEW]] +// CHECK-SAME: memref<?x?x8xf32, strided<[?, 8, 1], offset: ?>>, vector<8xf32> +// CHECK: %[[RESULT:.+]] = vector.shape_cast %[[VEC]] +// CHECK: return %[[RESULT]] // ----- @@ -43,7 +48,7 @@ func.func @contiguous_inner_most_dim(%A: memref<16x1xf32>, %i:index, %j:index) - } // CHECK: func @contiguous_inner_most_dim(%[[SRC:.+]]: memref<16x1xf32>, %[[I:.+]]: index, %[[J:.+]]: index) -> vector<8x1xf32> // CHECK: %[[SRC_0:.+]] = memref.subview %[[SRC]] -// CHECK-SAME: memref<16x1xf32> to memref<16xf32> +// CHECK-SAME: memref<16x1xf32> to memref<16xf32, strided<[1]>> // CHECK: %[[V:.+]] = vector.transfer_read %[[SRC_0]] // CHECK: %[[RESULT]] = vector.shape_cast %[[V]] : vector<8xf32> to vector<8x1xf32> // CHECK: return %[[RESULT]] @@ -111,7 +116,7 @@ func.func @drop_two_inner_most_dim_for_transfer_write(%arg0: memref<1x512x16x1x1 // CHECK-SAME: %[[IDX:[a-zA-Z0-9]+]] // CHECK-DAG: %[[C0:.+]] = arith.constant 0 : index // CHECK: %[[SUBVIEW:.+]] = memref.subview %[[DEST]] -// CHECK-SAME: memref<1x512x16x1x1xf32> to memref<1x512x16xf32> +// CHECK-SAME: memref<1x512x16x1x1xf32> to memref<1x512x16xf32, strided<[8192, 16, 1]>> // CHECK: %[[CAST:.+]] = vector.shape_cast %[[VEC]] : vector<1x16x16x1x1xf32> to vector<1x16x16xf32> // CHECK: vector.transfer_write %[[CAST]], %[[SUBVIEW]] // CHECK-SAME: [%[[C0]], %[[IDX]], %[[C0]]] 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/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/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_1d.mlir b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_insert_1d.mlir index 61c68507ea5198fd69826061e2a3a541a315d938..12e0d2267a265b64eb9189c40a3adaf70386a4e5 100644 --- a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_insert_1d.mlir +++ b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_insert_1d.mlir @@ -54,10 +54,10 @@ module { // Build the sparse vector from straightline code. %0 = tensor.empty() : tensor<1024xf32, #SparseVector> - %1 = sparse_tensor.insert %f1 into %0[%c0] : tensor<1024xf32, #SparseVector> - %2 = sparse_tensor.insert %f2 into %1[%c1] : tensor<1024xf32, #SparseVector> - %3 = sparse_tensor.insert %f3 into %2[%c3] : tensor<1024xf32, #SparseVector> - %4 = sparse_tensor.insert %f4 into %3[%c1023] : tensor<1024xf32, #SparseVector> + %1 = tensor.insert %f1 into %0[%c0] : tensor<1024xf32, #SparseVector> + %2 = tensor.insert %f2 into %1[%c1] : tensor<1024xf32, #SparseVector> + %3 = tensor.insert %f3 into %2[%c3] : tensor<1024xf32, #SparseVector> + %4 = tensor.insert %f4 into %3[%c1023] : tensor<1024xf32, #SparseVector> %5 = sparse_tensor.load %4 hasInserts : tensor<1024xf32, #SparseVector> // @@ -76,7 +76,7 @@ module { %6 = tensor.empty() : tensor<1024xf32, #SparseVector> %7 = scf.for %i = %c0 to %c8 step %c1 iter_args(%vin = %6) -> tensor<1024xf32, #SparseVector> { %ii = arith.muli %i, %c3 : index - %vout = sparse_tensor.insert %f1 into %vin[%ii] : tensor<1024xf32, #SparseVector> + %vout = tensor.insert %f1 into %vin[%ii] : tensor<1024xf32, #SparseVector> scf.yield %vout : tensor<1024xf32, #SparseVector> } %8 = sparse_tensor.load %7 hasInserts : tensor<1024xf32, #SparseVector> diff --git a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_insert_2d.mlir b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_insert_2d.mlir index d51b67792337d165ac8df10a5372aae1ccc0916c..8831091506533f8055fcc18d35cfc83cf9628a44 100644 --- a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_insert_2d.mlir +++ b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_insert_2d.mlir @@ -72,10 +72,10 @@ module { // CHECK-NEXT: ---- // %densea = tensor.empty() : tensor<4x3xf64, #Dense> - %dense1 = sparse_tensor.insert %f1 into %densea[%c0, %c0] : tensor<4x3xf64, #Dense> - %dense2 = sparse_tensor.insert %f2 into %dense1[%c2, %c2] : tensor<4x3xf64, #Dense> - %dense3 = sparse_tensor.insert %f3 into %dense2[%c3, %c0] : tensor<4x3xf64, #Dense> - %dense4 = sparse_tensor.insert %f4 into %dense3[%c3, %c2] : tensor<4x3xf64, #Dense> + %dense1 = tensor.insert %f1 into %densea[%c0, %c0] : tensor<4x3xf64, #Dense> + %dense2 = tensor.insert %f2 into %dense1[%c2, %c2] : tensor<4x3xf64, #Dense> + %dense3 = tensor.insert %f3 into %dense2[%c3, %c0] : tensor<4x3xf64, #Dense> + %dense4 = tensor.insert %f4 into %dense3[%c3, %c2] : tensor<4x3xf64, #Dense> %densem = sparse_tensor.load %dense4 hasInserts : tensor<4x3xf64, #Dense> sparse_tensor.print %densem : tensor<4x3xf64, #Dense> @@ -93,10 +93,10 @@ module { // CHECK-NEXT: ---- // %cooa = tensor.empty() : tensor<4x3xf64, #SortedCOO> - %coo1 = sparse_tensor.insert %f1 into %cooa[%c0, %c0] : tensor<4x3xf64, #SortedCOO> - %coo2 = sparse_tensor.insert %f2 into %coo1[%c2, %c2] : tensor<4x3xf64, #SortedCOO> - %coo3 = sparse_tensor.insert %f3 into %coo2[%c3, %c0] : tensor<4x3xf64, #SortedCOO> - %coo4 = sparse_tensor.insert %f4 into %coo3[%c3, %c2] : tensor<4x3xf64, #SortedCOO> + %coo1 = tensor.insert %f1 into %cooa[%c0, %c0] : tensor<4x3xf64, #SortedCOO> + %coo2 = tensor.insert %f2 into %coo1[%c2, %c2] : tensor<4x3xf64, #SortedCOO> + %coo3 = tensor.insert %f3 into %coo2[%c3, %c0] : tensor<4x3xf64, #SortedCOO> + %coo4 = tensor.insert %f4 into %coo3[%c3, %c2] : tensor<4x3xf64, #SortedCOO> %coom = sparse_tensor.load %coo4 hasInserts : tensor<4x3xf64, #SortedCOO> sparse_tensor.print %coom : tensor<4x3xf64, #SortedCOO> @@ -113,10 +113,10 @@ module { // CHECK-NEXT: ---- // %csra = tensor.empty() : tensor<4x3xf64, #CSR> - %csr1 = sparse_tensor.insert %f1 into %csra[%c0, %c0] : tensor<4x3xf64, #CSR> - %csr2 = sparse_tensor.insert %f2 into %csr1[%c2, %c2] : tensor<4x3xf64, #CSR> - %csr3 = sparse_tensor.insert %f3 into %csr2[%c3, %c0] : tensor<4x3xf64, #CSR> - %csr4 = sparse_tensor.insert %f4 into %csr3[%c3, %c2] : tensor<4x3xf64, #CSR> + %csr1 = tensor.insert %f1 into %csra[%c0, %c0] : tensor<4x3xf64, #CSR> + %csr2 = tensor.insert %f2 into %csr1[%c2, %c2] : tensor<4x3xf64, #CSR> + %csr3 = tensor.insert %f3 into %csr2[%c3, %c0] : tensor<4x3xf64, #CSR> + %csr4 = tensor.insert %f4 into %csr3[%c3, %c2] : tensor<4x3xf64, #CSR> %csrm = sparse_tensor.load %csr4 hasInserts : tensor<4x3xf64, #CSR> sparse_tensor.print %csrm : tensor<4x3xf64, #CSR> @@ -135,10 +135,10 @@ module { // CHECK-NEXT: ---- // %dcsra = tensor.empty() : tensor<4x3xf64, #DCSR> - %dcsr1 = sparse_tensor.insert %f1 into %dcsra[%c0, %c0] : tensor<4x3xf64, #DCSR> - %dcsr2 = sparse_tensor.insert %f2 into %dcsr1[%c2, %c2] : tensor<4x3xf64, #DCSR> - %dcsr3 = sparse_tensor.insert %f3 into %dcsr2[%c3, %c0] : tensor<4x3xf64, #DCSR> - %dcsr4 = sparse_tensor.insert %f4 into %dcsr3[%c3, %c2] : tensor<4x3xf64, #DCSR> + %dcsr1 = tensor.insert %f1 into %dcsra[%c0, %c0] : tensor<4x3xf64, #DCSR> + %dcsr2 = tensor.insert %f2 into %dcsr1[%c2, %c2] : tensor<4x3xf64, #DCSR> + %dcsr3 = tensor.insert %f3 into %dcsr2[%c3, %c0] : tensor<4x3xf64, #DCSR> + %dcsr4 = tensor.insert %f4 into %dcsr3[%c3, %c2] : tensor<4x3xf64, #DCSR> %dcsrm = sparse_tensor.load %dcsr4 hasInserts : tensor<4x3xf64, #DCSR> sparse_tensor.print %dcsrm : tensor<4x3xf64, #DCSR> @@ -155,10 +155,10 @@ module { // CHECK-NEXT: ---- // %rowa = tensor.empty() : tensor<4x3xf64, #Row> - %row1 = sparse_tensor.insert %f1 into %rowa[%c0, %c0] : tensor<4x3xf64, #Row> - %row2 = sparse_tensor.insert %f2 into %row1[%c2, %c2] : tensor<4x3xf64, #Row> - %row3 = sparse_tensor.insert %f3 into %row2[%c3, %c0] : tensor<4x3xf64, #Row> - %row4 = sparse_tensor.insert %f4 into %row3[%c3, %c2] : tensor<4x3xf64, #Row> + %row1 = tensor.insert %f1 into %rowa[%c0, %c0] : tensor<4x3xf64, #Row> + %row2 = tensor.insert %f2 into %row1[%c2, %c2] : tensor<4x3xf64, #Row> + %row3 = tensor.insert %f3 into %row2[%c3, %c0] : tensor<4x3xf64, #Row> + %row4 = tensor.insert %f4 into %row3[%c3, %c2] : tensor<4x3xf64, #Row> %rowm = sparse_tensor.load %row4 hasInserts : tensor<4x3xf64, #Row> sparse_tensor.print %rowm : tensor<4x3xf64, #Row> 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 1917fd987c5d7d3fa2265f4a0f4e2e15c795b54e..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 @@ -71,11 +71,11 @@ module { // CHECK-NEXT: values : ( 1.1, 2.2, 3.3, 4.4, 5.5 // CHECK-NEXT: ---- %tensora = tensor.empty() : tensor<5x4x3xf64, #TensorCSR> - %tensor1 = sparse_tensor.insert %f1 into %tensora[%c3, %c0, %c1] : tensor<5x4x3xf64, #TensorCSR> - %tensor2 = sparse_tensor.insert %f2 into %tensor1[%c3, %c0, %c2] : tensor<5x4x3xf64, #TensorCSR> - %tensor3 = sparse_tensor.insert %f3 into %tensor2[%c3, %c3, %c1] : tensor<5x4x3xf64, #TensorCSR> - %tensor4 = sparse_tensor.insert %f4 into %tensor3[%c4, %c2, %c2] : tensor<5x4x3xf64, #TensorCSR> - %tensor5 = sparse_tensor.insert %f5 into %tensor4[%c4, %c3, %c2] : tensor<5x4x3xf64, #TensorCSR> + %tensor1 = tensor.insert %f1 into %tensora[%c3, %c0, %c1] : tensor<5x4x3xf64, #TensorCSR> + %tensor2 = tensor.insert %f2 into %tensor1[%c3, %c0, %c2] : tensor<5x4x3xf64, #TensorCSR> + %tensor3 = tensor.insert %f3 into %tensor2[%c3, %c3, %c1] : tensor<5x4x3xf64, #TensorCSR> + %tensor4 = tensor.insert %f4 into %tensor3[%c4, %c2, %c2] : tensor<5x4x3xf64, #TensorCSR> + %tensor5 = tensor.insert %f5 into %tensor4[%c4, %c3, %c2] : tensor<5x4x3xf64, #TensorCSR> %tensorm = sparse_tensor.load %tensor5 hasInserts : tensor<5x4x3xf64, #TensorCSR> sparse_tensor.print %tensorm : tensor<5x4x3xf64, #TensorCSR> @@ -90,11 +90,11 @@ module { // CHECK-NEXT: values : ( 0, 1.1, 2.2, 0, 3.3, 0, 0, 0, 4.4, 0, 0, 5.5 // CHECK-NEXT: ---- %rowa = tensor.empty() : tensor<5x4x3xf64, #TensorRow> - %row1 = sparse_tensor.insert %f1 into %rowa[%c3, %c0, %c1] : tensor<5x4x3xf64, #TensorRow> - %row2 = sparse_tensor.insert %f2 into %row1[%c3, %c0, %c2] : tensor<5x4x3xf64, #TensorRow> - %row3 = sparse_tensor.insert %f3 into %row2[%c3, %c3, %c1] : tensor<5x4x3xf64, #TensorRow> - %row4 = sparse_tensor.insert %f4 into %row3[%c4, %c2, %c2] : tensor<5x4x3xf64, #TensorRow> - %row5 = sparse_tensor.insert %f5 into %row4[%c4, %c3, %c2] : tensor<5x4x3xf64, #TensorRow> + %row1 = tensor.insert %f1 into %rowa[%c3, %c0, %c1] : tensor<5x4x3xf64, #TensorRow> + %row2 = tensor.insert %f2 into %row1[%c3, %c0, %c2] : tensor<5x4x3xf64, #TensorRow> + %row3 = tensor.insert %f3 into %row2[%c3, %c3, %c1] : tensor<5x4x3xf64, #TensorRow> + %row4 = tensor.insert %f4 into %row3[%c4, %c2, %c2] : tensor<5x4x3xf64, #TensorRow> + %row5 = tensor.insert %f5 into %row4[%c4, %c3, %c2] : tensor<5x4x3xf64, #TensorRow> %rowm = sparse_tensor.load %row5 hasInserts : tensor<5x4x3xf64, #TensorRow> sparse_tensor.print %rowm : tensor<5x4x3xf64, #TensorRow> @@ -109,11 +109,11 @@ module { // CHECK-NEXT: values : ( 1.1, 2.2, 3.3, 4.4, 5.5 // CHECK-NEXT: ---- %ccoo = tensor.empty() : tensor<5x4x3xf64, #CCoo> - %ccoo1 = sparse_tensor.insert %f1 into %ccoo[%c3, %c0, %c1] : tensor<5x4x3xf64, #CCoo> - %ccoo2 = sparse_tensor.insert %f2 into %ccoo1[%c3, %c0, %c2] : tensor<5x4x3xf64, #CCoo> - %ccoo3 = sparse_tensor.insert %f3 into %ccoo2[%c3, %c3, %c1] : tensor<5x4x3xf64, #CCoo> - %ccoo4 = sparse_tensor.insert %f4 into %ccoo3[%c4, %c2, %c2] : tensor<5x4x3xf64, #CCoo> - %ccoo5 = sparse_tensor.insert %f5 into %ccoo4[%c4, %c3, %c2] : tensor<5x4x3xf64, #CCoo> + %ccoo1 = tensor.insert %f1 into %ccoo[%c3, %c0, %c1] : tensor<5x4x3xf64, #CCoo> + %ccoo2 = tensor.insert %f2 into %ccoo1[%c3, %c0, %c2] : tensor<5x4x3xf64, #CCoo> + %ccoo3 = tensor.insert %f3 into %ccoo2[%c3, %c3, %c1] : tensor<5x4x3xf64, #CCoo> + %ccoo4 = tensor.insert %f4 into %ccoo3[%c4, %c2, %c2] : tensor<5x4x3xf64, #CCoo> + %ccoo5 = tensor.insert %f5 into %ccoo4[%c4, %c3, %c2] : tensor<5x4x3xf64, #CCoo> %ccoom = sparse_tensor.load %ccoo5 hasInserts : tensor<5x4x3xf64, #CCoo> sparse_tensor.print %ccoom : tensor<5x4x3xf64, #CCoo> @@ -126,11 +126,11 @@ module { // CHECK-NEXT: values : ( 1.1, 2.2, 3.3, 4.4, 5.5 // CHECK-NEXT: ---- %dcoo = tensor.empty() : tensor<5x4x3xf64, #DCoo> - %dcoo1 = sparse_tensor.insert %f1 into %dcoo[%c3, %c0, %c1] : tensor<5x4x3xf64, #DCoo> - %dcoo2 = sparse_tensor.insert %f2 into %dcoo1[%c3, %c0, %c2] : tensor<5x4x3xf64, #DCoo> - %dcoo3 = sparse_tensor.insert %f3 into %dcoo2[%c3, %c3, %c1] : tensor<5x4x3xf64, #DCoo> - %dcoo4 = sparse_tensor.insert %f4 into %dcoo3[%c4, %c2, %c2] : tensor<5x4x3xf64, #DCoo> - %dcoo5 = sparse_tensor.insert %f5 into %dcoo4[%c4, %c3, %c2] : tensor<5x4x3xf64, #DCoo> + %dcoo1 = tensor.insert %f1 into %dcoo[%c3, %c0, %c1] : tensor<5x4x3xf64, #DCoo> + %dcoo2 = tensor.insert %f2 into %dcoo1[%c3, %c0, %c2] : tensor<5x4x3xf64, #DCoo> + %dcoo3 = tensor.insert %f3 into %dcoo2[%c3, %c3, %c1] : tensor<5x4x3xf64, #DCoo> + %dcoo4 = tensor.insert %f4 into %dcoo3[%c4, %c2, %c2] : tensor<5x4x3xf64, #DCoo> + %dcoo5 = tensor.insert %f5 into %dcoo4[%c4, %c3, %c2] : tensor<5x4x3xf64, #DCoo> %dcoom = sparse_tensor.load %dcoo5 hasInserts : tensor<5x4x3xf64, #DCoo> sparse_tensor.print %dcoom : tensor<5x4x3xf64, #DCoo> 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/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/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/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/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 d35acb0475e6f8e2d82612ba94091b4b2ace7d8f..ce6b56d48437a0c6338ef886557e256b8c934d35 100644 --- a/mlir/test/Target/LLVMIR/rocdl.mlir +++ b/mlir/test/Target/LLVMIR/rocdl.mlir @@ -88,6 +88,20 @@ llvm.func @rocdl.bpermute(%src : i32) -> i32 { llvm.return %0 : i32 } +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/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/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/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..ddc38b99356402781f357f6bdb53d77834cbe6b7 100644 --- a/mlir/test/lib/Dialect/Transform/TestTransformDialectExtension.h +++ b/mlir/test/lib/Dialect/Transform/TestTransformDialectExtension.h @@ -17,8 +17,8 @@ #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/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..75134b25882f0260ec8bf1ab41515bcaf95ecb66 100644 --- a/mlir/test/lib/Dialect/Transform/TestTransformDialectExtension.td +++ b/mlir/test/lib/Dialect/Transform/TestTransformDialectExtension.td @@ -19,7 +19,7 @@ include "mlir/IR/AttrTypeBase.td" include "mlir/IR/OpBase.td" include "mlir/Dialect/Transform/IR/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/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/mlir-cpu-runner/test-expand-math-approx.mlir b/mlir/test/mlir-cpu-runner/test-expand-math-approx.mlir index 541a201c94c58666104e3c36210d1e68f36f5d77..e2229a392bbf76a461039cb880aac5fb845a9e2c 100644 --- a/mlir/test/mlir-cpu-runner/test-expand-math-approx.mlir +++ b/mlir/test/mlir-cpu-runner/test-expand-math-approx.mlir @@ -683,6 +683,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 +708,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-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/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/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/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..b382137b70ee2a804aa10a9aa8c366218ccb84c6 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. diff --git a/openmp/libomptarget/DeviceRTL/src/Mapping.cpp b/openmp/libomptarget/DeviceRTL/src/Mapping.cpp index 31dd8054dec33efc3cbe3cb34a575f4ff1675f1a..b2028a8fb4f50695fe92508e4ba7193202e05a81 100644 --- a/openmp/libomptarget/DeviceRTL/src/Mapping.cpp +++ b/openmp/libomptarget/DeviceRTL/src/Mapping.cpp @@ -172,10 +172,7 @@ uint32_t getThreadIdInBlock(int32_t Dim) { UNREACHABLE("Dim outside range!"); } -uint32_t getThreadIdInWarp() { - return impl::getThreadIdInBlock(mapping::DIM_X) & - (mapping::getWarpSize() - 1); -} +uint32_t getThreadIdInWarp() { return __nvvm_read_ptx_sreg_laneid(); } uint32_t getBlockIdInKernel(int32_t Dim) { switch (Dim) { 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/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/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..b7be7b645ba33e8bd98d96adc8c9bc727100e6d3 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. @@ -1393,7 +1393,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/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..f39f913d85eec20c883d3f3001614f67c62689b8 100644 --- a/openmp/libomptarget/plugins-nextgen/common/src/PluginInterface.cpp +++ b/openmp/libomptarget/plugins-nextgen/common/src/PluginInterface.cpp @@ -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); @@ -1560,7 +1565,7 @@ Expected<bool> GenericPluginTy::checkELFImage(StringRef Image) const { return isELFCompatible(Image); } -const bool llvm::omp::target::plugin::libomptargetSupportsRPC() { +bool llvm::omp::target::plugin::libomptargetSupportsRPC() { #ifdef LIBOMPTARGET_RPC_SUPPORT return true; #else 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..b862bc74909257f871561b279a9eb30c3e6ac7a7 100644 --- a/openmp/libomptarget/plugins-nextgen/cuda/src/rtl.cpp +++ b/openmp/libomptarget/plugins-nextgen/cuda/src/rtl.cpp @@ -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(); 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 100% rename from openmp/libomptarget/plugins-nextgen/generic-elf-64bit/dynamic_ffi/ffi.cpp rename to openmp/libomptarget/plugins-nextgen/host/dynamic_ffi/ffi.cpp 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 97% rename from openmp/libomptarget/plugins-nextgen/generic-elf-64bit/src/rtl.cpp rename to openmp/libomptarget/plugins-nextgen/host/src/rtl.cpp index 38fc275804faf123e594db82e491086ee6e3cfd2..1ef18814a26ac8a1afd4e5bd7c005ba8597cdcde 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 { @@ -395,7 +400,7 @@ struct GenELF64PluginTy final : public GenericPluginTy { Error deinitImpl() override { return Plugin::success(); } /// 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,7 +411,7 @@ 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(); } }; 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/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..b7f547f1ec3d5cca999c0a2f7d879268af7bd024 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; diff --git a/openmp/libomptarget/src/omptarget.cpp b/openmp/libomptarget/src/omptarget.cpp index 3b3e17f0f311e8cd64a6facd17189ea86b921b3a..5bbf3a455c72ad4ba70d22cb2b6a52261b3a69ef 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> @@ -1752,7 +1753,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/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/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 48d7124e56c57c650ce5ac126bf6032b9ab87847..18ccf10fe17d0f6e4bf231bd75b387dd5a7235a2 100644 --- a/openmp/runtime/src/kmp.h +++ b/openmp/runtime/src/kmp.h @@ -819,13 +819,14 @@ 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; public: kmp_affinity_raii_t(const kmp_affin_mask_t *new_mask = nullptr) - : restored(false) { + : mask(nullptr), restored(false) { if (KMP_AFFINITY_CAPABLE()) { KMP_CPU_ALLOC(mask); KMP_ASSERT(mask != NULL); @@ -835,7 +836,7 @@ public: } } void restore() { - if (!restored && KMP_AFFINITY_CAPABLE()) { + if (mask && KMP_AFFINITY_CAPABLE() && !restored) { __kmp_set_system_affinity(mask, /*abort_on_error=*/true); KMP_CPU_FREE(mask); } @@ -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(). @@ -1392,8 +1394,6 @@ typedef struct kmp_cpuinfo { int stepping; // CPUID(1).EAX[3:0] ( Stepping ) kmp_cpuinfo_flags_t flags; int apic_id; - int physical_id; - int logical_id; kmp_uint64 frequency; // Nominal CPU frequency in Hz. char name[3 * sizeof(kmp_cpuid_t)]; // CPUID(0x80000002,0x80000003,0x80000004) } kmp_cpuinfo_t; @@ -1404,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) { @@ -3922,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 b79b57eafd6a81f432335d0897501422eaea66cd..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 @@ -1777,6 +1780,8 @@ static bool __kmp_affinity_create_hwloc_map(kmp_i18n_id_t *const msg_id) { __kmp_nThreadsPerCore = __kmp_hwloc_get_nobjs_under_obj(o, HWLOC_OBJ_PU); else __kmp_nThreadsPerCore = 1; // no CORE found + if (__kmp_nThreadsPerCore == 0) + __kmp_nThreadsPerCore = 1; __kmp_ncores = __kmp_xproc / __kmp_nThreadsPerCore; if (nCoresPerPkg == 0) nCoresPerPkg = 1; // to prevent possible division by 0 @@ -2905,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); @@ -2969,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. @@ -2998,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 @@ -3245,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 @@ -4440,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); @@ -4836,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; @@ -5010,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) { @@ -5123,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()) { @@ -5131,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 @@ -5154,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( @@ -5174,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() { @@ -5556,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 // @@ -5591,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_os.h b/openmp/runtime/src/kmp_os.h index 63da9e5fa15d1cc408efc024abe4485fd76a88db..a628070c882ad7e7e931da65c3cc284b831002da 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 diff --git a/openmp/runtime/src/kmp_sched.cpp b/openmp/runtime/src/kmp_sched.cpp index 53182bef58732e2522a53f7f188bdf391b16f290..4d764e441f28355de0ec3485e52add33714e2506 100644 --- a/openmp/runtime/src/kmp_sched.cpp +++ b/openmp/runtime/src/kmp_sched.cpp @@ -52,6 +52,7 @@ char const *traits_t<long>::spec = "ld"; } else if (i > 0) { \ t = (u - l) / i + 1; \ } else { \ + KMP_DEBUG_ASSERT(i != 0); \ t = (l - u) / (-i) + 1; \ } \ KMP_COUNT_VALUE(stat, t); \ @@ -284,6 +285,7 @@ static void __kmp_for_static_init(ident_t *loc, kmp_int32 global_tid, // upper-lower can exceed the limit of signed type trip_count = (UT)(*pupper - *plower) / incr + 1; } else { + KMP_DEBUG_ASSERT(incr != 0); trip_count = (UT)(*plower - *pupper) / (-incr) + 1; } @@ -318,6 +320,7 @@ static void __kmp_for_static_init(ident_t *loc, kmp_int32 global_tid, if (plastiter != NULL) *plastiter = (tid == trip_count - 1); } else { + KMP_DEBUG_ASSERT(nth != 0); if (__kmp_static == kmp_sch_static_balanced) { UT small_chunk = trip_count / nth; UT extras = trip_count % nth; @@ -358,6 +361,7 @@ static void __kmp_for_static_init(ident_t *loc, kmp_int32 global_tid, case kmp_sch_static_chunked: { ST span; UT nchunks; + KMP_DEBUG_ASSERT(chunk != 0); if (chunk < 1) chunk = 1; else if ((UT)chunk > trip_count) @@ -383,6 +387,7 @@ static void __kmp_for_static_init(ident_t *loc, kmp_int32 global_tid, } case kmp_sch_static_balanced_chunked: { T old_upper = *pupper; + KMP_DEBUG_ASSERT(nth != 0); // round up to make sure the chunk is enough to cover all iterations UT span = (trip_count + nth - 1) / nth; @@ -398,8 +403,10 @@ static void __kmp_for_static_init(ident_t *loc, kmp_int32 global_tid, } else if (*pupper < old_upper) *pupper = old_upper; - if (plastiter != NULL) + if (plastiter != NULL) { + KMP_DEBUG_ASSERT(chunk != 0); *plastiter = (tid == ((trip_count - 1) / (UT)chunk)); + } break; } default: @@ -417,6 +424,7 @@ static void __kmp_for_static_init(ident_t *loc, kmp_int32 global_tid, // Calculate chunk in case it was not specified; it is specified for // kmp_sch_static_chunked if (schedtype == kmp_sch_static) { + KMP_DEBUG_ASSERT(nth != 0); cur_chunk = trip_count / nth + ((trip_count % nth) ? 1 : 0); } // 0 - "static" schedule @@ -547,6 +555,7 @@ static void __kmp_dist_for_static_init(ident_t *loc, kmp_int32 gtid, // upper-lower can exceed the limit of signed type trip_count = (UT)(*pupper - *plower) / incr + 1; } else { + KMP_DEBUG_ASSERT(incr != 0); trip_count = (UT)(*plower - *pupper) / (-incr) + 1; } @@ -568,6 +577,7 @@ static void __kmp_dist_for_static_init(ident_t *loc, kmp_int32 gtid, *plastiter = (tid == 0 && team_id == trip_count - 1); } else { // Get the team's chunk first (each team gets at most one chunk) + KMP_DEBUG_ASSERT(nteams != 0); if (__kmp_static == kmp_sch_static_balanced) { UT chunkD = trip_count / nteams; UT extras = trip_count % nteams; @@ -619,6 +629,7 @@ static void __kmp_dist_for_static_init(ident_t *loc, kmp_int32 gtid, // upper-lower can exceed the limit of signed type trip_count = (UT)(*pupperDist - *plower) / incr + 1; } else { + KMP_DEBUG_ASSERT(incr != 0); trip_count = (UT)(*plower - *pupperDist) / (-incr) + 1; } KMP_DEBUG_ASSERT(trip_count); @@ -637,6 +648,7 @@ static void __kmp_dist_for_static_init(ident_t *loc, kmp_int32 gtid, if (*plastiter != 0 && !(tid == trip_count - 1)) *plastiter = 0; } else { + KMP_DEBUG_ASSERT(nth != 0); if (__kmp_static == kmp_sch_static_balanced) { UT chunkL = trip_count / nth; UT extras = trip_count % nth; @@ -684,9 +696,11 @@ static void __kmp_dist_for_static_init(ident_t *loc, kmp_int32 gtid, *pstride = span * nth; *plower = *plower + (span * tid); *pupper = *plower + span - incr; - if (plastiter != NULL) + if (plastiter != NULL) { + KMP_DEBUG_ASSERT(chunk != 0); if (*plastiter != 0 && !(tid == ((trip_count - 1) / (UT)chunk) % nth)) *plastiter = 0; + } break; } default: @@ -809,6 +823,7 @@ static void __kmp_team_static_init(ident_t *loc, kmp_int32 gtid, // upper-lower can exceed the limit of signed type trip_count = (UT)(upper - lower) / incr + 1; } else { + KMP_DEBUG_ASSERT(incr != 0); trip_count = (UT)(lower - upper) / (-incr) + 1; } if (chunk < 1) @@ -817,8 +832,10 @@ static void __kmp_team_static_init(ident_t *loc, kmp_int32 gtid, *p_st = span * nteams; *p_lb = lower + (span * team_id); *p_ub = *p_lb + span - incr; - if (p_last != NULL) + if (p_last != NULL) { + KMP_DEBUG_ASSERT(chunk != 0); *p_last = (team_id == ((trip_count - 1) / (UT)chunk) % nteams); + } // Correct upper bound if needed if (incr > 0) { if (*p_ub < *p_lb) // overflow? diff --git a/openmp/runtime/src/kmp_utility.cpp b/openmp/runtime/src/kmp_utility.cpp index f901eaca92f4d1cc5f464dea562a27e05fc97beb..bfa450c9ced26a28231a4163686eabcafb502cb1 100644 --- a/openmp/runtime/src/kmp_utility.cpp +++ b/openmp/runtime/src/kmp_utility.cpp @@ -28,68 +28,6 @@ static const char *unknown = "unknown"; static int trace_level = 5; #endif -/* LOG_ID_BITS = ( 1 + floor( log_2( max( log_per_phy - 1, 1 )))) - * APIC_ID = (PHY_ID << LOG_ID_BITS) | LOG_ID - * PHY_ID = APIC_ID >> LOG_ID_BITS - */ -int __kmp_get_physical_id(int log_per_phy, int apic_id) { - int index_lsb, index_msb, temp; - - if (log_per_phy > 1) { - index_lsb = 0; - index_msb = 31; - - temp = log_per_phy; - while ((temp & 1) == 0) { - temp >>= 1; - index_lsb++; - } - - temp = log_per_phy; - while ((temp & 0x80000000) == 0) { - temp <<= 1; - index_msb--; - } - - /* If >1 bits were set in log_per_phy, choose next higher power of 2 */ - if (index_lsb != index_msb) - index_msb++; - - return ((int)(apic_id >> index_msb)); - } - - return apic_id; -} - -/* - * LOG_ID_BITS = ( 1 + floor( log_2( max( log_per_phy - 1, 1 )))) - * APIC_ID = (PHY_ID << LOG_ID_BITS) | LOG_ID - * LOG_ID = APIC_ID & (( 1 << LOG_ID_BITS ) - 1 ) - */ -int __kmp_get_logical_id(int log_per_phy, int apic_id) { - unsigned current_bit; - int bits_seen; - - if (log_per_phy <= 1) - return (0); - - bits_seen = 0; - - for (current_bit = 1; log_per_phy != 0; current_bit <<= 1) { - if (log_per_phy & current_bit) { - log_per_phy &= ~current_bit; - bits_seen++; - } - } - - /* If exactly 1 bit was set in log_per_phy, choose next lower power of 2 */ - if (bits_seen == 1) { - current_bit >>= 1; - } - - return ((int)((current_bit - 1) & apic_id)); -} - static kmp_uint64 __kmp_parse_frequency( // R: Frequency in Hz. char const *frequency // I: Float number and unit: MHz, GHz, or TGz. ) { @@ -122,7 +60,6 @@ static kmp_uint64 __kmp_parse_frequency( // R: Frequency in Hz. void __kmp_query_cpuid(kmp_cpuinfo_t *p) { struct kmp_cpuid buf; int max_arg; - int log_per_phy; #ifdef KMP_DEBUG int cflush_size; #endif @@ -227,11 +164,8 @@ void __kmp_query_cpuid(kmp_cpuinfo_t *p) { if ((buf.edx >> 28) & 1) { /* Bits 23-16: Logical Processors per Physical Processor (1 for P4) */ - log_per_phy = data[2]; p->apic_id = data[3]; /* Bits 31-24: Processor Initial APIC ID (X) */ - KA_TRACE(trace_level, (" HT(%d TPUs)", log_per_phy)); - p->physical_id = __kmp_get_physical_id(log_per_phy, p->apic_id); - p->logical_id = __kmp_get_logical_id(log_per_phy, p->apic_id); + KA_TRACE(trace_level, (" HT(%d TPUs)", data[2])); } #ifdef KMP_DEBUG if ((buf.edx >> 29) & 1) { diff --git a/openmp/runtime/src/z_Linux_util.cpp b/openmp/runtime/src/z_Linux_util.cpp index 3f831d6e2a8f9d846cca1959f2a0746ab1bc9647..29db9d008a49b3f34a71259d787db6edddd9b758 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(); @@ -2325,6 +2351,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; @@ -2610,6 +2637,43 @@ finish: // Clean up and exit. KMP_ARCH_PPC64 || KMP_ARCH_RISCV64 || KMP_ARCH_LOONGARCH64 || \ KMP_ARCH_ARM || KMP_ARCH_VE || KMP_ARCH_S390X || KMP_ARCH_PPC_XCOFF) +// 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 int __kmp_invoke_microtask(microtask_t pkfn, int gtid, int tid, int argc, @@ -2629,66 +2693,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/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/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/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..c01986815afe117c2d25c2f9f8786581c773be24 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,6 +2053,7 @@ cc_library( ":frontend", ":support", "//llvm:Core", + "//llvm:Demangle", "//llvm:Support", "//llvm:TextAPI", ], @@ -2114,7 +2100,6 @@ cc_library( name = "frontend_tool", srcs = glob([ "lib/FrontendTool/*.cpp", - "lib/FrontendTool/*.h", ]), hdrs = glob(["include/clang/FrontendTool/*.h"]), includes = ["include"], @@ -2318,7 +2303,6 @@ cc_binary( testonly = 1, srcs = glob([ "tools/clang-import-test/*.cpp", - "tools/clang-import-test/*.h", ]), stamp = 0, deps = [ @@ -2348,7 +2332,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 +2388,7 @@ cc_binary( stamp = 0, deps = [ ":basic", + ":diagnostic_defs_gen", ":frontend", ":lex", ":sema", @@ -2665,7 +2649,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..0d531a3dc12a7c8b2ac70f9243fce4748ea66546 100644 --- a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel +++ b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel @@ -62,7 +62,47 @@ 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"], +) + +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 +191,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", ], ) @@ -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", @@ -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", ], ) @@ -595,6 +656,7 @@ 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", @@ -669,6 +731,7 @@ libc_support_library( ":__support_macros_properties_architectures", ":__support_macros_sanitizer", ":errno", + ":llvm_libc_macros_math_macros", ], ) @@ -691,6 +754,7 @@ libc_support_library( ":__support_macros_attributes", ":__support_macros_properties_types", ":__support_math_extras", + ":__support_sign", ":__support_uint128", ], ) @@ -726,7 +790,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 +805,7 @@ libc_support_library( ":__support_fputil_normal_float", ":__support_macros_optimization", ":__support_uint128", + ":llvm_libc_macros_math_macros", ], ) @@ -751,6 +819,7 @@ libc_support_library( ":__support_fputil_fp_bits", ":__support_fputil_rounding_mode", ":__support_macros_attributes", + ":llvm_libc_macros_math_macros", ], ) @@ -979,33 +1048,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 +1214,7 @@ libc_support_library( "__support_cpp_type_traits", ":__support_common", ":errno", + ":llvm_libc_macros_math_macros", ], ) @@ -1233,13 +1276,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", ], ) @@ -3229,6 +3268,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/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..65173f986585c4c42cf05e85609624891f7cee9a 100644 --- a/utils/bazel/llvm-project-overlay/llvm/BUILD.bazel +++ b/utils/bazel/llvm-project-overlay/llvm/BUILD.bazel @@ -66,7 +66,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 +84,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 +102,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 +120,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( @@ -168,7 +180,6 @@ cc_library( name = "Demangle", srcs = glob([ "lib/Demangle/*.cpp", - "lib/Demangle/*.h", ]), hdrs = glob([ "include/llvm/Demangle/*.h", @@ -203,7 +214,6 @@ cc_library( "include/llvm/Option/*.h", ]) + select({ "@platforms//os:windows": glob([ - "lib/Support/Windows/*.h", "lib/Support/Windows/*.inc", ]), "//conditions:default": glob([ @@ -315,7 +325,6 @@ cc_library( name = "LineEditor", srcs = glob([ "lib/LineEditor/*.cpp", - "lib/LineEditor/*.h", ]), hdrs = glob(["include/llvm/LineEditor/*.h"]), copts = llvm_copts, @@ -329,7 +338,6 @@ cc_library( name = "Option", srcs = glob([ "lib/Option/*.cpp", - "lib/Option/*.h", ]), hdrs = glob(["include/llvm/Option/*.h"]), copts = llvm_copts, @@ -376,8 +384,6 @@ cc_library( name = "BinaryFormat", srcs = glob([ "lib/BinaryFormat/*.cpp", - "lib/BinaryFormat/*.def", - "lib/BinaryFormat/*.h", ]), hdrs = glob([ "include/llvm/BinaryFormat/*.h", @@ -409,7 +415,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 +425,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 +441,6 @@ cc_library( name = "DebugInfoCodeView", srcs = glob([ "lib/DebugInfo/CodeView/*.cpp", - "lib/DebugInfo/CodeView/*.h", ]), hdrs = glob([ "include/llvm/DebugInfo/CodeView/*.h", @@ -480,9 +483,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 +524,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 +543,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 +560,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 +576,6 @@ cc_library( name = "Symbolize", srcs = glob([ "lib/DebugInfo/Symbolize/*.cpp", - "lib/DebugInfo/Symbolize/*.h", ]), hdrs = glob([ "include/llvm/DebugInfo/Symbolize/*.h", @@ -603,14 +598,14 @@ 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,7 +621,7 @@ cc_binary( cc_library( name = "TableGenGlobalISel", srcs = [ - "utils/TableGen/GlobalISel/CodeExpander.cpp", + "utils/TableGen/Common/GlobalISel/CodeExpander.cpp", ], hdrs = glob([ # We have to include these headers here as well as in the `hdrs` below @@ -634,8 +629,8 @@ cc_library( # 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"], @@ -658,10 +653,13 @@ 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 @@ -669,9 +667,10 @@ cc_binary( "include/llvm/MC/*.h", "include/llvm/TargetParser/SubtargetFeature.h", ], - exclude = ["utils/TableGen/GlobalISel/CodeExpander.cpp"], + exclude = ["utils/TableGen/Common/GlobalISel/CodeExpander.cpp"], ), copts = llvm_copts, + includes = ["utils/TableGen"], stamp = 0, deps = [ ":CodeGenTypes", @@ -821,7 +820,6 @@ cc_library( name = "BitstreamReader", srcs = glob([ "lib/Bitstream/Reader/*.cpp", - "lib/Bitstream/Reader/*.h", ]), hdrs = [ "include/llvm/Bitstream/BitCodeEnums.h", @@ -836,9 +834,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 +951,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,9 +996,7 @@ 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 = [ ":Object", @@ -1067,7 +1059,6 @@ cc_library( name = "ObjectYAML", srcs = glob([ "lib/ObjectYAML/*.cpp", - "lib/ObjectYAML/*.h", ]), hdrs = glob(["include/llvm/ObjectYAML/*.h"]), copts = llvm_copts, @@ -1085,7 +1076,6 @@ cc_library( name = "ProfileData", srcs = glob([ "lib/ProfileData/*.cpp", - "lib/ProfileData/*.h", ]), hdrs = glob([ "include/llvm/ProfileData/*.h", @@ -1109,7 +1099,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 +1115,6 @@ cc_library( srcs = glob( [ "lib/Analysis/*.cpp", - "lib/Analysis/*.h", - "lib/Analysis/*.def", ], ), hdrs = glob( @@ -1185,7 +1172,6 @@ cc_library( name = "Target", srcs = glob([ "lib/Target/*.cpp", - "lib/Target/*.h", ]), hdrs = glob([ "include/llvm/Target/*.h", @@ -1221,14 +1207,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 +1235,6 @@ cc_library( name = "DWP", srcs = glob([ "lib/DWP/*.cpp", - "lib/DWP/*.h", ]), hdrs = glob(["include/llvm/DWP/*.h"]), copts = llvm_copts, @@ -1269,7 +1251,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 +1371,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 +1412,6 @@ cc_library( cc_library( name = "FrontendDebug", - srcs = glob([ - "lib/Frontend/Debug/*.cpp", - ]), hdrs = glob([ "include/llvm/Frontend/Debug/*.h", ]), @@ -1530,8 +1507,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 +1566,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 +1580,6 @@ cc_library( name = "AsmParser", srcs = glob([ "lib/AsmParser/*.cpp", - "lib/AsmParser/*.h", ]), hdrs = glob(["include/llvm/AsmParser/*.h"]), copts = llvm_copts, @@ -1623,7 +1595,6 @@ cc_library( name = "IRPrinter", srcs = glob([ "lib/IRPrinter/*.cpp", - "lib/IRPrinter/*.h", ]), hdrs = glob([ "include/llvm/IRPrinter/*.h", @@ -1640,7 +1611,6 @@ cc_library( name = "IRReader", srcs = glob([ "lib/IRReader/*.cpp", - "lib/IRReader/*.h", ]), hdrs = glob([ "include/llvm/IRReader/*.h", @@ -1683,7 +1653,6 @@ cc_library( name = "IPO", srcs = glob([ "lib/Transforms/IPO/*.cpp", - "lib/Transforms/IPO/*.h", ]), hdrs = glob([ "include/llvm/Transforms/IPO/*.h", @@ -1721,7 +1690,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 +1704,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 +1793,6 @@ cc_library( copts = llvm_copts, textual_hdrs = glob([ "include/llvm/CodeGen/**/*.def", - "include/llvm/CodeGen/**/*.inc", ]), deps = [ ":AggressiveInstCombine", @@ -2305,10 +2271,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 +2301,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 +2367,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 +2411,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 +2448,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 +2462,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 +2487,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 +2552,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 +2576,6 @@ cc_library( ":InstCombine", ":Instrumentation", ":MC", - ":MLPolicies", ":ObjCARC", ":Scalar", ":Support", @@ -2617,7 +2592,6 @@ cc_library( name = "LTO", srcs = glob([ "lib/LTO/*.cpp", - "lib/LTO/*.h", ]), hdrs = glob([ "include/llvm/LTO/*.h", @@ -2657,7 +2631,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 +2744,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 +2870,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 +2890,6 @@ cc_library( name = "DWARFLinkerBase", srcs = glob([ "lib/DWARFLinker/*.cpp", - "lib/DWARFLinker/*.h", ]), hdrs = glob(["include/llvm/DWARFLinker/*.h"]), copts = llvm_copts, @@ -3011,7 +2980,6 @@ cc_library( name = "InterfaceStub", srcs = glob([ "lib/InterfaceStub/*.cpp", - "lib/InterfaceStub/*.h", ]), hdrs = glob([ "include/llvm/InterfaceStub/*.h", @@ -3062,7 +3030,6 @@ cc_library( name = "MCA", srcs = glob([ "lib/MCA/**/*.cpp", - "lib/MCA/**/*.h", ]), hdrs = glob([ "include/llvm/MCA/**/*.h", @@ -3089,7 +3056,6 @@ cc_library( name = "XRay", srcs = glob([ "lib/XRay/*.cpp", - "lib/XRay/*.h", ]), hdrs = glob(["include/llvm/XRay/*.h"]), copts = llvm_copts, @@ -3146,21 +3112,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 = [ @@ -3334,7 +3303,6 @@ cc_binary( name = "llvm-ar", srcs = glob([ "tools/llvm-ar/*.cpp", - "tools/llvm-ar/*.h", ]) + ["llvm-ar-driver.cpp"], copts = llvm_copts, stamp = 0, @@ -3372,7 +3340,6 @@ cc_binary( name = "llvm-as", srcs = glob([ "tools/llvm-as/*.cpp", - "tools/llvm-as/*.h", ]), copts = llvm_copts, stamp = 0, @@ -3389,7 +3356,6 @@ cc_binary( name = "llvm-bcanalyzer", srcs = glob([ "tools/llvm-bcanalyzer/*.cpp", - "tools/llvm-bcanalyzer/*.h", ]), copts = llvm_copts, stamp = 0, @@ -3476,7 +3442,6 @@ cc_binary( name = "llvm-cvtres", srcs = glob([ "tools/llvm-cvtres/*.cpp", - "tools/llvm-cvtres/*.h", ]), copts = llvm_copts, stamp = 0, @@ -3510,7 +3475,6 @@ cc_binary( name = "llvm-cxxmap", srcs = glob([ "tools/llvm-cxxmap/*.cpp", - "tools/llvm-cxxmap/*.h", ]), copts = llvm_copts, stamp = 0, @@ -3545,7 +3509,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 +3541,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 +3557,6 @@ cc_binary( name = "llvm-dis", srcs = glob([ "tools/llvm-dis/*.cpp", - "tools/llvm-dis/*.h", ]), copts = llvm_copts, stamp = 0, @@ -3690,7 +3651,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 +3690,6 @@ cc_binary( name = "llvm-extract", srcs = glob([ "tools/llvm-extract/*.cpp", - "tools/llvm-extract/*.h", ]), copts = llvm_copts, stamp = 0, @@ -3772,7 +3731,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 +3882,6 @@ cc_binary( name = "llvm-link", srcs = glob([ "tools/llvm-link/*.cpp", - "tools/llvm-link/*.h", ]), copts = llvm_copts, stamp = 0, @@ -3989,7 +3946,6 @@ cc_binary( name = "llvm-lto", srcs = glob([ "tools/llvm-lto/*.cpp", - "tools/llvm-lto/*.h", ]), copts = llvm_copts, stamp = 0, @@ -4012,7 +3968,6 @@ cc_binary( name = "llvm-lto2", srcs = glob([ "tools/llvm-lto2/*.cpp", - "tools/llvm-lto2/*.h", ]), copts = llvm_copts, stamp = 0, @@ -4158,7 +4113,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, @@ -4195,7 +4149,6 @@ cc_binary( name = "llvm-nm", srcs = glob([ "tools/llvm-nm/*.cpp", - "tools/llvm-nm/*.h", ]) + ["llvm-nm-driver.cpp"], copts = llvm_copts, stamp = 0, @@ -4279,7 +4232,6 @@ cc_binary( name = "llvm-stress", srcs = glob([ "tools/llvm-stress/*.cpp", - "tools/llvm-stress/*.h", ]), copts = llvm_copts, stamp = 0, @@ -4456,7 +4408,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 +4591,6 @@ cc_binary( name = "llvm-rtdyld", srcs = glob([ "tools/llvm-rtdyld/*.cpp", - "tools/llvm-rtdyld/*.h", ]), copts = llvm_copts, stamp = 0, @@ -4682,7 +4632,6 @@ cc_binary( name = "llvm-size", srcs = glob([ "tools/llvm-size/*.cpp", - "tools/llvm-size/*.h", ]) + ["llvm-size-driver.cpp"], copts = llvm_copts, stamp = 0, @@ -4698,7 +4647,6 @@ cc_binary( name = "llvm-split", srcs = glob([ "tools/llvm-split/*.cpp", - "tools/llvm-split/*.h", ]), copts = llvm_copts, stamp = 0, @@ -4728,7 +4676,6 @@ cc_binary( name = "llvm-strings", srcs = glob([ "tools/llvm-strings/*.cpp", - "tools/llvm-strings/*.h", ]), copts = llvm_copts, stamp = 0, @@ -4765,7 +4712,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 +4737,6 @@ cc_binary( name = "llvm-undname", srcs = glob([ "tools/llvm-undname/*.cpp", - "tools/llvm-undname/*.h", ]), copts = llvm_copts, stamp = 0, @@ -4805,7 +4750,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 +4832,6 @@ cc_binary( name = "sancov", srcs = glob([ "tools/sancov/*.cpp", - "tools/sancov/*.h", ]) + ["sancov-driver.cpp"], copts = llvm_copts, stamp = 0, @@ -4911,7 +4854,6 @@ cc_binary( name = "sanstats", srcs = glob([ "tools/sanstats/*.cpp", - "tools/sanstats/*.h", ]), copts = llvm_copts, stamp = 0, @@ -4926,7 +4868,6 @@ cc_binary( name = "split-file", srcs = glob([ "utils/split-file/*.cpp", - "utils/split-file/*.h", ]), copts = llvm_copts, stamp = 0, @@ -5022,7 +4963,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 +4991,6 @@ cc_binary( testonly = True, srcs = glob([ "utils/FileCheck/*.cpp", - "utils/FileCheck/*.h", ]), copts = llvm_copts, stamp = 0, @@ -5097,7 +5036,6 @@ cc_binary( testonly = True, srcs = glob([ "utils/count/*.c", - "utils/count/*.h", ]), stamp = 0, deps = [":Support"], @@ -5108,7 +5046,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 +5112,6 @@ cc_binary( testonly = True, srcs = glob([ "tools/llvm-diff/*.cpp", - "tools/llvm-diff/*.h", ]), copts = llvm_copts, stamp = 0, @@ -5193,7 +5129,6 @@ cc_binary( testonly = True, srcs = glob([ "tools/llvm-isel-fuzzer/*.cpp", - "tools/llvm-isel-fuzzer/*.h", ]), copts = llvm_copts, stamp = 0, @@ -5239,7 +5174,6 @@ cc_binary( testonly = True, srcs = glob([ "utils/not/*.cpp", - "utils/not/*.h", ]), copts = llvm_copts, stamp = 0, @@ -5319,7 +5253,6 @@ cc_binary( testonly = True, srcs = glob([ "tools/llvm-tli-checker/*.cpp", - "tools/llvm-tli-checker/*.h", ]), copts = llvm_copts, stamp = 0, @@ -5366,7 +5299,6 @@ cc_binary( name = "verify-uselistorder", srcs = glob([ "tools/verify-uselistorder/*.cpp", - "tools/verify-uselistorder/*.h", ]), copts = llvm_copts, stamp = 0, @@ -5386,7 +5318,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/unittests/BUILD.bazel b/utils/bazel/llvm-project-overlay/llvm/unittests/BUILD.bazel index 99b924626c2afc06b328859768fef269161b919e..c8863af43c400d4d81c1037905b956f4d7408efb 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", diff --git a/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel b/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel index 28a69c7ffea1f4d7d27836736ba1700f9af2a7ab..88b46bdb326ca300fdcca98fcf9b473a2200aaed 100644 --- a/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel +++ b/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel @@ -325,21 +325,19 @@ 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/IR/PDLPatternMatch.h.inc", + "include/mlir/Interfaces/CallInterfaces.h", + "include/mlir/Interfaces/DataLayoutInterfaces.h", + "include/mlir/Interfaces/SideEffectInterfaces.h", "lib/Bytecode/BytecodeOpInterface.cpp", ], 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 = [ @@ -760,6 +758,7 @@ mlir_c_api_cc_library( includes = ["include"], deps = [ ":TransformDialect", + ":TransformDialectInterfaces", ":TransformDialectTransforms", ], ) @@ -1464,6 +1463,7 @@ cc_library( ":FuncDialect", ":IR", ":TransformDialect", + ":TransformDialectInterfaces", ":Transforms", ":VectorDialect", ], @@ -1572,6 +1572,7 @@ cc_library( ":FuncDialect", ":IR", ":TransformDialect", + ":TransformDialectInterfaces", ":VectorDialect", ], ) @@ -1627,7 +1628,6 @@ cc_library( srcs = glob( [ "lib/Dialect/AMDGPU/Transforms/*.cpp", - "lib/Dialect/AMDGPU/Transforms/*.h", ], ), hdrs = glob(["include/mlir/Dialect/AMDGPU/Transforms/*.h"]), @@ -1643,6 +1643,7 @@ cc_library( ":IR", ":MemRefDialect", ":Pass", + ":SideEffectInterfaces", ":Support", ":TransformUtils", ":Transforms", @@ -1765,7 +1766,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 +1773,6 @@ cc_library( ":EmitCDialect", ":FuncDialect", ":IR", - ":MathDialect", - ":SCFDialect", ":Support", ":TranslateLib", "//llvm:Support", @@ -1938,17 +1936,14 @@ cc_library( includes = ["include"], deps = [ ":ArithDialect", - ":ArmNeonIncGen", ":ArmNeonDialect", + ":DialectUtils", ":FuncDialect", ":IR", ":LLVMDialect", - ":SideEffectInterfaces", ":Support", - ":VectorDialect", ":Transforms", - "//llvm:Core", - "//llvm:Support", + ":VectorDialect", ], ) @@ -1969,7 +1964,6 @@ cc_library( name = "ArmNeon2dToIntr", srcs = glob([ "lib/Conversion/ArmNeon2dToIntr/*.cpp", - "lib/Conversion/ArmNeon2dToIntr/*.h", ]), hdrs = glob([ "include/mlir/Conversion/ArmNeon2dToIntr/*.h", @@ -2841,7 +2835,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 +2847,7 @@ cc_library( ":ArithDialect", ":ArithUtils", ":BufferizationDialect", + ":BufferizationInterfaces", ":BufferizationTransforms", ":DestinationStyleOpInterface", ":DialectUtils", @@ -2926,6 +2920,7 @@ cc_library( ":SCFUtils", ":SideEffectInterfaces", ":TransformDialect", + ":TransformDialectInterfaces", ":VectorDialect", "//llvm:Support", ], @@ -3127,9 +3122,11 @@ cc_library( includes = ["include"], deps = [ ":ArithDialect", + ":BufferizationInterfaces", ":DialectUtils", ":IR", ":InferTypeOpInterface", + ":SideEffectInterfaces", ":SparseTensorAttrDefsIncGen", ":SparseTensorEnums", ":SparseTensorInterfacesIncGen", @@ -3156,6 +3153,7 @@ cc_library( ":SparseTensorTransformOpsIncGen", ":Support", ":TransformDialect", + ":TransformDialectInterfaces", "//llvm:Support", ], ) @@ -3185,7 +3183,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 +3196,7 @@ cc_library( ":ArithDialect", ":ArithUtils", ":BufferizationDialect", + ":BufferizationInterfaces", ":BufferizationTransforms", ":ComplexDialect", ":DialectUtils", @@ -3582,6 +3580,7 @@ cc_library( ":SCFTransforms", ":Support", ":TransformDialect", + ":TransformDialectInterfaces", ":VectorDialect", "//llvm:Support", ], @@ -3671,6 +3670,8 @@ td_library( deps = [ ":BuiltinDialectTdFiles", ":OpBaseTdFiles", + ":ShapedOpInterfacesTdFiles", + ":ViewLikeInterfaceTdFiles", ], ) @@ -3754,7 +3755,11 @@ cc_library( hdrs = ["include/mlir/Dialect/XeGPU/IR/XeGPU.h"], includes = ["include"], deps = [ + ":DialectUtils", ":IR", + ":ShapedOpInterfaces", + ":SideEffectInterfaces", + ":ViewLikeInterface", ":XeGPUIncGen", "//llvm:Core", "//llvm:Support", @@ -3817,7 +3822,6 @@ cc_library( name = "Dialect", srcs = glob([ "lib/Dialect/*.cpp", - "lib/Dialect/*.h", ]), hdrs = glob([ "include/mlir/Dialect/*.h", @@ -3859,7 +3863,6 @@ cc_library( name = "DialectUtils", srcs = glob([ "lib/Dialect/Utils/*.cpp", - "lib/Dialect/Utils/*.h", ]), hdrs = glob([ "include/mlir/Dialect/Utils/*.h", @@ -3878,7 +3881,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", @@ -3888,9 +3890,11 @@ cc_library( ":AffineMemoryOpInterfacesIncGen", ":AffineOpsIncGen", ":ArithDialect", + ":BufferizationInterfaces", ":ControlFlowInterfaces", ":DialectUtils", ":IR", + ":InliningUtils", ":LoopLikeInterface", ":MemRefDialect", ":ShapedOpInterfaces", @@ -3998,7 +4002,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,6 +4009,7 @@ cc_library( ":AffineDialect", ":Analysis", ":ArithDialect", + ":CallOpInterfaces", ":DialectUtils", ":FuncDialect", ":IR", @@ -4021,7 +4025,6 @@ cc_library( srcs = glob( [ "lib/Dialect/Affine/Utils/*.cpp", - "lib/Dialect/Affine/Utils/*.h", ], ), hdrs = [ @@ -4068,7 +4071,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,6 +4091,7 @@ cc_library( ":Pass", ":SCFDialect", ":SCFUtils", + ":SideEffectInterfaces", ":Support", ":TensorDialect", ":Transforms", @@ -4170,11 +4173,11 @@ cc_library( ":MathToLLVM", ":MathToLibm", ":MathToSPIRV", + ":MemRefToEmitC", ":MemRefToLLVM", ":MemRefToSPIRV", ":NVGPUToNVVM", ":NVVMToLLVM", - ":OpenACCToLLVM", ":OpenACCToSCF", ":OpenMPToLLVM", ":PDLToPDLInterp", @@ -4207,7 +4210,6 @@ cc_library( name = "AsyncToLLVM", srcs = glob([ "lib/Conversion/AsyncToLLVM/*.cpp", - "lib/Conversion/AsyncToLLVM/*.h", ]), hdrs = glob(["include/mlir/Conversion/AsyncToLLVM/*.h"]), includes = ["include"], @@ -4233,7 +4235,6 @@ cc_library( name = "AffineToStandard", srcs = glob([ "lib/Conversion/AffineToStandard/*.cpp", - "lib/Conversion/AffineToStandard/*.h", ]), hdrs = glob(["include/mlir/Conversion/AffineToStandard/*.h"]), includes = ["include"], @@ -4254,32 +4255,11 @@ cc_library( ], ) -# 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,6 +4271,7 @@ cc_library( deps = [ ":ArithDialect", ":ArithUtils", + ":BufferizationInterfaces", ":ControlFlowDialect", ":ControlFlowInterfaces", ":DestinationStyleOpInterface", @@ -4298,6 +4279,7 @@ cc_library( ":FunctionInterfaces", ":IR", ":InferTypeOpInterface", + ":InliningUtils", ":LoopLikeInterface", ":MemRefDialect", ":ParallelCombiningOpInterface", @@ -4368,6 +4350,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"], @@ -4538,6 +4532,7 @@ cc_library( includes = ["include"], deps = [ ":ArithDialect", + ":BufferizationInterfaces", ":CastInterfaces", ":ControlFlowInterfaces", ":Dialect", @@ -4545,6 +4540,7 @@ cc_library( ":FunctionInterfaces", ":IR", ":InferTypeOpInterface", + ":InliningUtils", ":MLIRShapeCanonicalizationIncGen", ":ShapeOpsIncGen", ":SideEffectInterfaces", @@ -4572,7 +4568,6 @@ cc_library( name = "ShapeToStandard", srcs = glob([ "lib/Conversion/ShapeToStandard/*.cpp", - "lib/Conversion/ShapeToStandard/*.h", ]), hdrs = ["include/mlir/Conversion/ShapeToStandard/ShapeToStandard.h"], includes = ["include"], @@ -4612,7 +4607,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 +4617,7 @@ cc_library( deps = [ ":ArithDialect", ":BufferizationDialect", + ":BufferizationInterfaces", ":BufferizationTransforms", ":FuncDialect", ":IR", @@ -4694,7 +4689,6 @@ cc_library( srcs = glob( [ "lib/Dialect/ControlFlow/IR/*.cpp", - "lib/Dialect/ControlFlow/IR/*.h", ], ), hdrs = glob([ @@ -4703,11 +4697,13 @@ cc_library( includes = ["include"], deps = [ ":ArithDialect", + ":BufferizationInterfaces", ":CommonFolders", ":ControlFlowInterfaces", ":ControlFlowOpsIncGen", ":ConvertToLLVMInterface", ":IR", + ":InliningUtils", ":SideEffectInterfaces", ":Support", "//llvm:Support", @@ -4725,6 +4721,7 @@ cc_library( includes = ["include"], deps = [ ":BufferizationDialect", + ":BufferizationInterfaces", ":BufferizationTransforms", ":ControlFlowDialect", ":IR", @@ -4737,17 +4734,15 @@ 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", ":CallOpInterfaces", ":CastInterfaces", ":CommonFolders", @@ -4758,6 +4753,7 @@ cc_library( ":FunctionInterfaces", ":IR", ":InferTypeOpInterface", + ":InliningUtils", ":SideEffectInterfaces", ":Support", "//llvm:Support", @@ -4774,6 +4770,7 @@ cc_library( ":FuncDialect", ":IR", ":InferTypeOpInterface", + ":InliningUtils", ":MeshShardingInterface", ], ) @@ -4826,6 +4823,7 @@ cc_library( ":LLVMCommonConversion", ":LLVMDialect", ":TransformDialect", + ":TransformDialectInterfaces", ":TransformUtils", ], ) @@ -4890,7 +4888,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"], @@ -4924,16 +4921,19 @@ cc_library( ":AffineDialect", ":ArithDialect", ":ArithUtils", + ":BufferizationInterfaces", ":ControlFlowInterfaces", ":DataLayoutInterfaces", ":DestinationStyleOpInterface", ":DialectUtils", ":IR", ":InferTypeOpInterface", + ":InliningUtils", ":MaskableOpInterface", ":MaskingOpInterface", ":MemRefDialect", ":SideEffectInterfaces", + ":SubsetOpInterface", ":Support", ":TensorDialect", ":ValueBoundsOpInterface", @@ -4964,6 +4964,7 @@ cc_library( ":LLVMDialect", ":SideEffectInterfaces", ":TransformDialect", + ":TransformDialectInterfaces", ":TransformUtils", ":VectorDialect", ":VectorEnumsIncGen", @@ -5023,7 +5024,6 @@ cc_library( srcs = glob( [ "lib/Dialect/Vector/Transforms/*.cpp", - "lib/Dialect/Vector/Transforms/*.h", ], ), hdrs = glob([ @@ -5036,6 +5036,7 @@ cc_library( ":ArithTransforms", ":ArithUtils", ":BufferizationDialect", + ":BufferizationInterfaces", ":BufferizationTransforms", ":DialectUtils", ":FuncDialect", @@ -5089,7 +5090,6 @@ cc_library( name = "Support", srcs = glob([ "lib/Support/*.cpp", - "lib/Support/*.h", ]), hdrs = glob(["include/mlir/Support/*.h"]), includes = ["include"], @@ -5103,11 +5103,8 @@ 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", @@ -5149,8 +5146,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( @@ -5224,8 +5219,6 @@ cc_library( name = "BytecodeReader", srcs = glob([ "lib/Bytecode/Reader/*.cpp", - "lib/Bytecode/Reader/*.h", - "lib/Bytecode/*.h", ]), hdrs = glob([ "include/mlir/Bytecode/*.h", @@ -5245,7 +5238,6 @@ cc_library( srcs = glob([ "lib/Bytecode/Writer/*.cpp", "lib/Bytecode/Writer/*.h", - "lib/Bytecode/*.h", ]), hdrs = glob([ "include/mlir/Bytecode/*.h", @@ -5263,7 +5255,6 @@ cc_library( name = "Parser", srcs = glob([ "lib/Parser/*.cpp", - "lib/Parser/*.h", ]), hdrs = glob([ "include/mlir/Parser/*.h", @@ -5289,6 +5280,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", @@ -5338,7 +5337,6 @@ cc_library( "include/mlir/Dialect/LLVMIR/*X86Vector*.h", ], ) + [ - "include/mlir/Transforms/InliningUtils.h", "include/mlir/Transforms/Mem2Reg.h", ], includes = ["include"], @@ -5349,6 +5347,7 @@ cc_library( ":FunctionInterfaces", ":IR", ":InferTypeOpInterface", + ":InliningUtils", ":LLVMDialectInterfaceIncGen", ":LLVMIntrinsicOpsIncGen", ":LLVMOpsIncGen", @@ -5386,7 +5385,6 @@ 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"], @@ -5539,13 +5537,13 @@ 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", ":ControlFlowInterfaces", ":DLTIDialect", ":FunctionInterfaces", @@ -5555,6 +5553,7 @@ cc_library( ":IR", ":InferIntRangeInterface", ":InferTypeOpInterface", + ":InliningUtils", ":LLVMDialect", ":MemRefDialect", ":SCFDialect", @@ -5631,7 +5630,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 +5641,7 @@ cc_library( ":AsmParser", ":AsyncDialect", ":BufferizationDialect", + ":BufferizationInterfaces", ":ControlFlowDialect", ":DLTIDialect", ":DialectUtils", @@ -5742,6 +5741,7 @@ cc_library( ":SideEffectInterfaces", ":Support", ":TransformDialect", + ":TransformDialectInterfaces", ":TransformUtils", ":VectorDialect", ":VectorTransforms", @@ -5819,7 +5819,6 @@ cc_library( name = "GPUToNVVMTransforms", srcs = glob([ "lib/Conversion/GPUToNVVM/*.cpp", - "lib/Conversion/GPUToNVVM/*.h", ]), hdrs = glob([ "include/mlir/Conversion/GPUToNVVM/*.h", @@ -5855,7 +5854,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", @@ -5880,7 +5878,6 @@ cc_library( name = "NVGPUToNVVM", srcs = glob([ "lib/Conversion/NVGPUToNVVM/*.cpp", - "lib/Conversion/NVGPUToNVVM/*.h", ]), hdrs = glob([ "include/mlir/Conversion/NVGPUToNVVM/*.h", @@ -5908,7 +5905,6 @@ cc_library( name = "VectorToSPIRV", srcs = glob([ "lib/Conversion/VectorToSPIRV/*.cpp", - "lib/Conversion/VectorToSPIRV/*.h", ]), hdrs = glob([ "include/mlir/Conversion/VectorToSPIRV/*.h", @@ -6037,7 +6033,6 @@ cc_library( name = "GPUToSPIRV", srcs = glob([ "lib/Conversion/GPUToSPIRV/*.cpp", - "lib/Conversion/GPUToSPIRV/*.h", ]), hdrs = glob([ "include/mlir/Conversion/GPUToSPIRV/*.h", @@ -6607,7 +6602,6 @@ cc_library( name = "PDLDialect", srcs = glob([ "lib/Dialect/PDL/IR/*.cpp", - "lib/Dialect/PDL/IR/*.h", ]), hdrs = glob([ "include/mlir/Dialect/PDL/IR/*.h", @@ -6682,7 +6676,6 @@ cc_library( name = "PDLInterpDialect", srcs = glob([ "lib/Dialect/PDLInterp/IR/*.cpp", - "lib/Dialect/PDLInterp/IR/*.h", ]), hdrs = glob([ "include/mlir/Dialect/PDLInterp/IR/*.h", @@ -6889,18 +6882,20 @@ 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 = [ + ":CallOpInterfaces", ":CommonFolders", ":ControlFlowInterfaces", ":FunctionInterfaces", ":GPUDialect", ":IR", ":InferTypeOpInterface", + ":InliningUtils", ":Parser", ":SPIRVAttrUtilsGen", ":SPIRVAttributesIncGen", @@ -6978,7 +6973,6 @@ cc_library( srcs = glob( [ "lib/Dialect/SPIRV/Transforms/*.cpp", - "lib/Dialect/SPIRV/Transforms/*.h", ], exclude = ["lib/Dialect/SPIRV/Transforms/SPIRVConversion.cpp"], ), @@ -7017,7 +7011,6 @@ cc_library( name = "MathToSPIRV", srcs = glob([ "lib/Conversion/MathToSPIRV/*.cpp", - "lib/Conversion/MathToSPIRV/*.h", ]), hdrs = glob([ "include/mlir/Conversion/MathToSPIRV/*.h", @@ -7044,7 +7037,6 @@ cc_library( name = "FuncToEmitC", srcs = glob([ "lib/Conversion/FuncToEmitC/*.cpp", - "lib/Conversion/FuncToEmitC/*.h", ]), hdrs = glob([ "include/mlir/Conversion/FuncToEmitC/*.h", @@ -7070,7 +7062,6 @@ cc_library( name = "FuncToSPIRV", srcs = glob([ "lib/Conversion/FuncToSPIRV/*.cpp", - "lib/Conversion/FuncToSPIRV/*.h", ]), hdrs = glob([ "include/mlir/Conversion/FuncToSPIRV/*.h", @@ -7102,7 +7093,6 @@ cc_library( name = "TensorToLinalg", srcs = glob([ "lib/Conversion/TensorToLinalg/*.cpp", - "lib/Conversion/TensorToLinalg/*.h", ]), hdrs = glob([ "include/mlir/Conversion/TensorToLinalg/*.h", @@ -7131,7 +7121,6 @@ cc_library( name = "TensorToSPIRV", srcs = glob([ "lib/Conversion/TensorToSPIRV/*.cpp", - "lib/Conversion/TensorToSPIRV/*.h", ]), hdrs = glob([ "include/mlir/Conversion/TensorToSPIRV/*.h", @@ -7305,7 +7294,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 +7307,7 @@ cc_library( ":AffineDialect", ":ArithDialect", ":ArithUtils", + ":BufferizationInterfaces", ":CastInterfaces", ":ComplexDialect", ":ControlFlowInterfaces", @@ -7326,13 +7315,16 @@ cc_library( ":DialectUtils", ":IR", ":InferTypeOpInterface", + ":InliningUtils", ":LoopLikeInterface", ":ParallelCombiningOpInterface", ":ShapedOpInterfaces", ":SideEffectInterfaces", + ":SubsetOpInterface", ":Support", ":TensorOpsIncGen", ":TilingInterface", + ":TransformDialectInterfaces", ":ValueBoundsOpInterface", ":ViewLikeInterface", "//llvm:Support", @@ -7414,7 +7406,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 +7417,7 @@ cc_library( ":ArithDialect", ":ArithUtils", ":BufferizationDialect", + ":BufferizationInterfaces", ":BufferizationTransforms", ":DialectUtils", ":FuncDialect", @@ -7490,6 +7482,7 @@ cc_library( ":TensorTransforms", ":TensorUtils", ":TransformDialect", + ":TransformDialectInterfaces", ":TransformUtils", ], ) @@ -7516,22 +7509,27 @@ cc_library( cc_library( name = "TransformUtils", - srcs = glob([ - "lib/Transforms/Utils/*.cpp", - "lib/Transforms/Utils/*.h", - ]), + srcs = glob( + include = [ + "lib/Transforms/Utils/*.cpp", + ], + exclude = ["lib/Transforms/Utils/InliningUtils.cpp"], + ), hdrs = glob( - [ - "include/mlir/Transforms/*.h", + include = ["include/mlir/Transforms/*.h"], + exclude = [ + "include/mlir/Transforms/InliningUtils.h", + "include/mlir/Transforms/Passes.h", ], - exclude = ["include/mlir/Transforms/Passes.h"], ), includes = ["include"], deps = [ ":Analysis", + ":CallOpInterfaces", ":ControlFlowInterfaces", ":FunctionInterfaces", ":IR", + ":InliningUtils", ":LoopLikeInterface", ":MemorySlotInterfaces", ":Pass", @@ -7852,20 +7850,22 @@ cc_library( name = "Transforms", srcs = glob([ "lib/Transforms/*.cpp", - "lib/Transforms/*.h", ]), hdrs = glob(["include/mlir/Transforms/*.h"]), includes = ["include"], deps = [ ":Analysis", + ":CallOpInterfaces", ":ControlFlowInterfaces", ":FunctionInterfaces", ":IR", + ":InliningUtils", ":LoopLikeInterface", ":MemorySlotInterfaces", ":Pass", ":Rewrite", ":RuntimeVerifiableOpInterface", + ":SideEffectInterfaces", ":Support", ":TransformUtils", ":TransformsPassIncGen", @@ -7937,7 +7937,6 @@ cc_library( name = "SCFToSPIRV", srcs = glob([ "lib/Conversion/SCFToSPIRV/*.cpp", - "lib/Conversion/SCFToSPIRV/*.h", ]), hdrs = glob([ "include/mlir/Conversion/SCFToSPIRV/*.h", @@ -8017,6 +8016,7 @@ cc_library( hdrs = glob(["include/mlir/Conversion/LLVMCommon/*.h"]), includes = ["include"], deps = [ + ":DataLayoutInterfaces", ":IR", ":LLVMDialect", ":Support", @@ -8182,6 +8182,31 @@ cc_library( ], ) +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", + ":MemRefDialect", + ":IR", + ":Pass", + ":Support", + ":TransformUtils", + ":Transforms", + "//llvm:Support", + ], +) + cc_library( name = "MemRefToLLVM", srcs = glob(["lib/Conversion/MemRefToLLVM/*.cpp"]), @@ -8210,7 +8235,6 @@ cc_library( name = "MemRefToSPIRV", srcs = glob([ "lib/Conversion/MemRefToSPIRV/*.cpp", - "lib/Conversion/MemRefToSPIRV/*.h", ]), hdrs = glob([ "include/mlir/Conversion/MemRefToSPIRV/*.h", @@ -8270,7 +8294,6 @@ cc_library( name = "ArithToArmSME", srcs = glob([ "lib/Conversion/ArithToArmSME/*.cpp", - "lib/Conversion/ArithToArmSME/*.h", ]), hdrs = glob([ "include/mlir/Conversion/ArithToArmSME/*.h", @@ -8291,7 +8314,6 @@ cc_library( name = "ArithToEmitC", srcs = glob([ "lib/Conversion/ArithToEmitC/*.cpp", - "lib/Conversion/ArithToEmitC/*.h", ]), hdrs = glob([ "include/mlir/Conversion/ArithToEmitC/*.h", @@ -8582,9 +8604,7 @@ cc_library( srcs = glob( [ "lib/Analysis/*.cpp", - "lib/Analysis/*.h", "lib/Analysis/*/*.cpp", - "lib/Analysis/*/*.h", ], ), hdrs = glob( @@ -8890,7 +8910,6 @@ cc_library( ":IR", ":LLVMDialect", ":OpenACCDialect", - ":OpenACCToLLVM", ":OpenMPCommon", ":Support", ":ToLLVMIRTranslation", @@ -8988,6 +9007,7 @@ cc_library( includes = ["include"], deps = [ ":DLTIDialect", + ":DataLayoutInterfaces", ":IR", ":LLVMConversionIncGen", ":LLVMDialect", @@ -9255,7 +9275,6 @@ cc_library( ":SCFToGPU", ":SCFTransformOps", ":SCFTransforms", - ":SDBM", ":SPIRVDialect", ":SPIRVPassIncGen", ":SPIRVTarget", @@ -9366,7 +9385,6 @@ cc_binary( "//mlir/test:TestTosaDialect", "//mlir/test:TestTransformDialect", "//mlir/test:TestTransforms", - "//mlir/test:TestTypeDialect", "//mlir/test:TestVector", "//mlir/test:TestVectorToSPIRV", ], @@ -9984,7 +10002,6 @@ cc_library( srcs = glob( [ "lib/Dialect/OpenACC/IR/*.cpp", - "lib/Dialect/OpenACC/IR/*.h", ], ), hdrs = glob( @@ -10038,7 +10055,6 @@ cc_library( srcs = glob( [ "lib/Dialect/OpenACC/Transforms/*.cpp", - "lib/Dialect/OpenACC/Transforms/*.h", ], ), hdrs = glob(["include/mlir/Dialect/OpenACC/Transforms/*.h"]), @@ -10202,7 +10218,6 @@ cc_library( srcs = glob( [ "lib/Dialect/OpenMP/IR/*.cpp", - "lib/Dialect/OpenMP/IR/*.h", ], ), hdrs = glob( @@ -10238,7 +10253,6 @@ cc_library( name = "OpenACCToSCF", srcs = glob([ "lib/Conversion/OpenACCToSCF/*.cpp", - "lib/Conversion/OpenACCToSCF/*.h", ]), hdrs = glob([ "include/mlir/Conversion/OpenACCToSCF/*.h", @@ -10258,35 +10272,10 @@ cc_library( ], ) -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", - ], -) - cc_library( name = "OpenMPToLLVM", srcs = glob([ "lib/Conversion/OpenMPToLLVM/*.cpp", - "lib/Conversion/OpenMPToLLVM/*.h", ]), hdrs = glob([ "include/mlir/Conversion/OpenMPToLLVM/*.h", @@ -10496,7 +10485,6 @@ cc_library( name = "IndexToLLVM", srcs = glob([ "lib/Conversion/IndexToLLVM/*.cpp", - "lib/Conversion/IndexToLLVM/*.h", ]), hdrs = glob([ "include/mlir/Conversion/IndexToLLVM/*.h", @@ -10522,7 +10510,6 @@ cc_library( name = "IndexToSPIRV", srcs = glob([ "lib/Conversion/IndexToSPIRV/*.cpp", - "lib/Conversion/IndexToSPIRV/*.h", ]), hdrs = glob([ "include/mlir/Conversion/IndexToSPIRV/*.h", @@ -10841,6 +10828,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 = [ @@ -10913,7 +10930,6 @@ cc_library( name = "LinalgToStandard", srcs = glob([ "lib/Conversion/LinalgToStandard/*.cpp", - "lib/Conversion/LinalgToStandard/*.h", ]), hdrs = glob([ "include/mlir/Conversion/LinalgToStandard/*.h", @@ -10948,6 +10964,7 @@ cc_library( ":ArithUtils", ":AsmParser", ":BufferizationDialect", + ":BufferizationInterfaces", ":ComplexDialect", ":ControlFlowInterfaces", ":CopyOpInterface", @@ -10957,6 +10974,7 @@ cc_library( ":FunctionInterfaces", ":IR", ":InferTypeOpInterface", + ":InliningUtils", ":LinalgEnumsIncGen", ":LinalgInterfacesIncGen", ":LinalgNamedStructuredOpsYamlIncGen", @@ -10964,11 +10982,12 @@ cc_library( ":LinalgStructuredOpsIncGen", ":MathDialect", ":MemRefDialect", + ":MeshShardingInterface", ":Parser", ":SCFDialect", - ":MeshShardingInterface", ":SideEffectInterfaces", ":SparseTensorDialect", + ":SubsetOpInterface", ":Support", ":TensorDialect", ":TilingInterface", @@ -11013,6 +11032,7 @@ cc_library( ":TensorUtils", ":TilingInterface", ":TransformDialect", + ":TransformDialectInterfaces", ":TransformDialectUtils", ":TransformUtils", ":VectorDialect", @@ -11055,7 +11075,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 +11103,6 @@ cc_library( name = "LinalgTransforms", srcs = glob([ "lib/Dialect/Linalg/Transforms/*.cpp", - "lib/Dialect/Linalg/Transforms/*.h", ]), hdrs = [ "include/mlir/Dialect/Linalg/Passes.h", @@ -11102,6 +11120,7 @@ cc_library( ":ArithTransforms", ":ArithUtils", ":BufferizationDialect", + ":BufferizationInterfaces", ":BufferizationTransforms", ":ComplexDialect", ":ControlFlowDialect", @@ -11121,12 +11140,12 @@ cc_library( ":MemRefDialect", ":MemRefTransforms", ":MeshDialect", + ":MeshShardingInterface", ":MeshTransforms", ":Pass", ":SCFDialect", ":SCFTransforms", ":SCFUtils", - ":MeshShardingInterface", ":SparseTensorDialect", ":SubsetOpInterface", ":Support", @@ -11435,7 +11454,6 @@ cc_library( name = "VectorToLLVM", srcs = glob([ "lib/Conversion/VectorToLLVM/*.cpp", - "lib/Conversion/VectorToLLVM/*.h", ]), hdrs = glob([ "include/mlir/Conversion/VectorToLLVM/*.h", @@ -11477,7 +11495,6 @@ cc_library( name = "VectorToArmSME", srcs = glob([ "lib/Conversion/VectorToArmSME/*.cpp", - "lib/Conversion/VectorToArmSME/*.h", ]), hdrs = glob([ "include/mlir/Conversion/VectorToArmSME/*.h", @@ -11498,7 +11515,6 @@ cc_library( name = "VectorToGPU", srcs = glob([ "lib/Conversion/VectorToGPU/*.cpp", - "lib/Conversion/VectorToGPU/*.h", ]), hdrs = glob([ "include/mlir/Conversion/VectorToGPU/*.h", @@ -11535,7 +11551,6 @@ cc_library( name = "VectorToSCF", srcs = glob([ "lib/Conversion/VectorToSCF/*.cpp", - "lib/Conversion/VectorToSCF/*.h", ]), hdrs = glob([ "include/mlir/Conversion/VectorToSCF/*.h", @@ -11685,7 +11700,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", ]), @@ -11703,6 +11717,7 @@ cc_library( ":FuncDialect", ":IR", ":InferTypeOpInterface", + ":InliningUtils", ":LoopLikeInterface", ":MeshDialect", ":MeshShardingInterface", @@ -11724,7 +11739,6 @@ cc_library( name = "TosaToArith", srcs = glob([ "lib/Conversion/TosaToArith/*.cpp", - "lib/Conversion/TosaToArith/*.h", ]), hdrs = glob([ "include/mlir/Conversion/TosaToArith/*.h", @@ -11748,7 +11762,6 @@ cc_library( name = "TosaToLinalg", srcs = glob([ "lib/Conversion/TosaToLinalg/*.cpp", - "lib/Conversion/TosaToLinalg/*.h", ]), hdrs = glob([ "include/mlir/Conversion/TosaToLinalg/*.h", @@ -11781,7 +11794,6 @@ cc_library( name = "TosaToMLProgram", srcs = glob([ "lib/Conversion/TosaToMLProgram/*.cpp", - "lib/Conversion/TosaToMLProgram/*.h", ]), hdrs = glob([ "include/mlir/Conversion/TosaToMLProgram/*.h", @@ -11805,7 +11817,6 @@ cc_library( name = "TosaToSCF", srcs = glob([ "lib/Conversion/TosaToSCF/*.cpp", - "lib/Conversion/TosaToSCF/*.h", ]), hdrs = glob([ "include/mlir/Conversion/TosaToSCF/*.h", @@ -11830,7 +11841,6 @@ cc_library( name = "TosaToTensor", srcs = glob([ "lib/Conversion/TosaToTensor/*.cpp", - "lib/Conversion/TosaToTensor/*.h", ]), hdrs = glob([ "include/mlir/Conversion/TosaToTensor/*.h", @@ -11853,6 +11863,15 @@ cc_library( ], ) +td_library( + name = "TransformInterfacesTdFiles", + srcs = glob(["include/mlir/Dialect/Transform/Interfaces/*.td"]), + deps = [ + ":OpBaseTdFiles", + ":SideEffectInterfacesTdFiles", + ], +) + td_library( name = "TransformDialectTdFiles", srcs = glob(["include/mlir/Dialect/Transform/IR/*.td"]), @@ -11862,6 +11881,7 @@ td_library( ":InferTypeOpInterfaceTdFiles", ":OpBaseTdFiles", ":SideEffectInterfacesTdFiles", + ":TransformInterfacesTdFiles", ], ) @@ -11917,29 +11937,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 +12022,23 @@ 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", + ":TransformDialectUtils", + ":Transforms", + "//llvm:Support", + ], +) + cc_library( name = "TransformDialect", srcs = glob(["lib/Dialect/Transform/IR/*.cpp"]), @@ -12023,7 +12060,7 @@ cc_library( ":Support", ":TransformDialectEnumsIncGen", ":TransformDialectIncGen", - ":TransformDialectInterfacesIncGen", + ":TransformDialectInterfaces", ":TransformDialectMatchInterfacesIncGen", ":TransformDialectUtils", ":TransformOpsIncGen", @@ -12075,6 +12112,7 @@ cc_library( ":SideEffectInterfaces", ":Support", ":TransformDialect", + ":TransformDialectInterfaces", ":TransformPDLExtensionOpsIncGen", "//llvm:Support", ], @@ -12118,6 +12156,7 @@ cc_library( ":Support", ":TransformDebugExtensionOpsIncGen", ":TransformDialect", + ":TransformDialectInterfaces", "//llvm:Support", ], ) @@ -12162,6 +12201,7 @@ cc_library( ":SideEffectInterfaces", ":Support", ":TransformDialect", + ":TransformDialectInterfaces", ":TransformLoopExtensionOpsIncGen", ":Transforms", "//llvm:Support", @@ -12206,6 +12246,7 @@ cc_library( ":SideEffectInterfaces", ":Support", ":TransformDialect", + ":TransformDialectInterfaces", ":TransformDialectTransformsIncGen", "//llvm:Support", ], @@ -12304,7 +12345,6 @@ cc_library( srcs = glob( [ "lib/Dialect/Complex/IR/*.cpp", - "lib/Dialect/Complex/IR/*.h", ], ), hdrs = ["include/mlir/Dialect/Complex/IR/Complex.h"], @@ -12317,6 +12357,7 @@ cc_library( ":ConvertToLLVMInterface", ":IR", ":InferTypeOpInterface", + ":InliningUtils", ":SideEffectInterfaces", "//llvm:Support", ], @@ -12326,7 +12367,6 @@ cc_library( name = "ComplexToLLVM", srcs = glob([ "lib/Conversion/ComplexToLLVM/*.cpp", - "lib/Conversion/ComplexToLLVM/*.h", ]), hdrs = glob([ "include/mlir/Conversion/ComplexToLLVM/*.h", @@ -12354,7 +12394,6 @@ cc_library( name = "ComplexToLibm", srcs = glob([ "lib/Conversion/ComplexToLibm/*.cpp", - "lib/Conversion/ComplexToLibm/*.h", ]), hdrs = glob([ "include/mlir/Conversion/ComplexToLibm/*.h", @@ -12378,7 +12417,6 @@ cc_library( name = "ComplexToSPIRV", srcs = glob([ "lib/Conversion/ComplexToSPIRV/*.cpp", - "lib/Conversion/ComplexToSPIRV/*.h", ]), hdrs = glob([ "include/mlir/Conversion/ComplexToSPIRV/*.h", @@ -12403,7 +12441,6 @@ cc_library( name = "ComplexToStandard", srcs = glob([ "lib/Conversion/ComplexToStandard/*.cpp", - "lib/Conversion/ComplexToStandard/*.h", ]), hdrs = glob([ "include/mlir/Conversion/ComplexToStandard/*.h", @@ -12562,13 +12599,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 +12615,23 @@ cc_library( ":ArithCanonicalizationIncGen", ":ArithOpsIncGen", ":ArithOpsInterfacesIncGen", + ":BufferizationInterfaces", + ":CallOpInterfaces", ":CastInterfaces", ":CommonFolders", + ":ControlFlowInterfaces", ":ConvertToLLVMInterface", + ":DestinationStyleOpInterface", ":IR", ":InferIntRangeCommon", ":InferIntRangeInterface", ":InferTypeOpInterface", + ":InliningUtils", + ":Pass", + ":SideEffectInterfaces", ":Support", ":UBDialect", + ":ValueBoundsOpInterfaceIncGen", ":VectorInterfaces", "//llvm:Support", ], @@ -12610,7 +12657,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,6 +12668,7 @@ cc_library( ":ArithPassIncGen", ":ArithUtils", ":BufferizationDialect", + ":BufferizationInterfaces", ":BufferizationTransforms", ":FuncDialect", ":FuncTransforms", @@ -12731,7 +12778,6 @@ cc_library( srcs = glob( [ "lib/Dialect/Math/IR/*.cpp", - "lib/Dialect/Math/IR/*.h", ], ), hdrs = [ @@ -12744,6 +12790,7 @@ cc_library( ":ConvertToLLVMInterface", ":IR", ":InferTypeOpInterface", + ":InliningUtils", ":MathBaseIncGen", ":MathOpsIncGen", ":SideEffectInterfaces", @@ -12757,7 +12804,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"], @@ -12781,7 +12827,6 @@ cc_library( name = "MathToLibm", srcs = glob([ "lib/Conversion/MathToLibm/*.cpp", - "lib/Conversion/MathToLibm/*.h", ]), hdrs = glob([ "include/mlir/Conversion/MathToLibm/*.h", @@ -12872,7 +12917,6 @@ cc_library( srcs = glob( [ "lib/Dialect/MemRef/IR/*.cpp", - "lib/Dialect/MemRef/IR/*.h", ], ), hdrs = [ @@ -12882,8 +12926,11 @@ cc_library( ], includes = ["include"], deps = [ + ":AllocationOpInterface", ":ArithDialect", ":ArithUtils", + ":BufferizationInterfaces", + ":CallOpInterfaces", ":CastInterfaces", ":ComplexDialect", ":ControlFlowInterfaces", @@ -12892,10 +12939,13 @@ cc_library( ":DialectUtils", ":IR", ":InferTypeOpInterface", + ":InliningUtils", ":MemRefBaseIncGen", ":MemRefOpsIncGen", ":MemorySlotInterfaces", + ":RuntimeVerifiableOpInterface", ":ShapedOpInterfaces", + ":SideEffectInterfaces", ":Support", ":ValueBoundsOpInterface", ":ViewLikeInterface", @@ -12944,7 +12994,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 +13007,8 @@ cc_library( ":ArithTransforms", ":ArithUtils", ":BufferizationDialect", + ":BufferizationInterfaces", + ":BufferizationTransforms", ":ControlFlowDialect", ":DialectUtils", ":FuncDialect", @@ -13030,6 +13081,7 @@ cc_library( ":NVGPUDialect", ":SCFDialect", ":TransformDialect", + ":TransformDialectInterfaces", ":TransformUtils", ":VectorDialect", ":VectorTransforms", @@ -13142,14 +13194,18 @@ cc_library( hdrs = glob(["include/mlir/Dialect/MLProgram/IR/*.h"]), includes = ["include"], deps = [ + ":CallOpInterfaces", ":ControlFlowInterfaces", ":FunctionInterfaces", ":IR", + ":InliningUtils", ":MLProgramAttributesIncGen", ":MLProgramOpsIncGen", ":MLProgramTypesIncGen", ":Pass", + ":SideEffectInterfaces", ":Support", + ":Transforms", "//llvm:Support", ], ) @@ -13165,6 +13221,7 @@ cc_library( includes = ["include"], deps = [ ":BufferizationDialect", + ":BufferizationInterfaces", ":FuncDialect", ":IR", ":MLProgramDialect", @@ -13344,6 +13401,7 @@ td_library( includes = ["include"], deps = [ ":AllocationOpInterfaceTdFiles", + ":BufferViewFlowOpInterfaceTdFiles", ":BufferizableOpInterfaceTdFiles", ":CopyOpInterfaceTdFiles", ":DestinationStyleOpInterfaceTdFiles", @@ -13448,6 +13506,7 @@ cc_library( deps = [ ":BufferizationDialect", ":BufferizationEnumsIncGen", + ":BufferizationInterfaces", ":BufferizationTransformOpsIncGen", ":BufferizationTransforms", ":FunctionInterfaces", @@ -13458,6 +13517,7 @@ cc_library( ":SideEffectInterfaces", ":TensorDialect", ":TransformDialect", + ":TransformDialectInterfaces", "//llvm:Support", ], ) @@ -13481,18 +13541,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", @@ -13504,10 +13585,12 @@ cc_library( ":Analysis", ":ArithDialect", ":BufferDeallocationOpInterfaceIncGen", + ":BufferViewFlowOpInterfaceIncGen", ":BufferizableOpInterfaceIncGen", ":BufferizationBaseIncGen", - ":BufferizationEnumsIncGen", + ":BufferizationInterfaces", ":BufferizationOpsIncGen", + ":CallOpInterfaces", ":ControlFlowInterfaces", ":CopyOpInterface", ":DestinationStyleOpInterface", @@ -13515,6 +13598,7 @@ cc_library( ":FunctionInterfaces", ":IR", ":InferTypeOpInterface", + ":InliningUtils", ":MemRefDialect", ":SparseTensorDialect", ":SubsetOpInterface", @@ -13545,7 +13629,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 +13638,13 @@ cc_library( ":Analysis", ":ArithDialect", ":BufferizationDialect", - ":BufferizationEnumsIncGen", + ":BufferizationInterfaces", ":BufferizationPassIncGen", + ":CallOpInterfaces", ":ControlFlowDialect", ":ControlFlowInterfaces", ":FuncDialect", + ":FunctionInterfaces", ":IR", ":LoopLikeInterface", ":MemRefDialect", @@ -13607,6 +13692,7 @@ cc_library( includes = ["include"], deps = [ ":BufferizationDialect", + ":BufferizationInterfaces", ":BufferizationToMemRef", ":BufferizationTransforms", ":FuncDialect", @@ -13736,7 +13822,6 @@ cc_library( srcs = glob( [ "lib/Tools/PDLL/ODS/*.cpp", - "lib/Tools/PDLL/ODS/*.h", ], ), hdrs = glob(["include/mlir/Tools/PDLL/ODS/*.h"]), @@ -13770,7 +13855,6 @@ cc_library( srcs = glob( [ "lib/Tools/PDLL/CodeGen/*.cpp", - "lib/Tools/PDLL/CodeGen/*.h", ], ), hdrs = glob(["include/mlir/Tools/PDLL/CodeGen/*.h"]), @@ -13912,7 +13996,6 @@ 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"], @@ -13920,6 +14003,7 @@ cc_library( deps = [ ":ConvertToLLVMInterface", ":IR", + ":InliningUtils", ":SideEffectInterfaces", ":UBOpsIncGen", ":UBOpsInterfacesIncGen", @@ -13931,7 +14015,6 @@ cc_library( name = "UBToLLVM", srcs = glob([ "lib/Conversion/UBToLLVM/*.cpp", - "lib/Conversion/UBToLLVM/*.h", ]), hdrs = glob([ "include/mlir/Conversion/UBToLLVM/*.h", @@ -13952,7 +14035,6 @@ cc_library( name = "UBToSPIRV", srcs = glob([ "lib/Conversion/UBToSPIRV/*.cpp", - "lib/Conversion/UBToSPIRV/*.h", ]), hdrs = glob([ "include/mlir/Conversion/UBToSPIRV/*.h", 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..2c49d52f1ed0aef0e7906ca384816a3684b47f6c 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,6 +102,7 @@ cc_binary( "//mlir:Analysis", "//mlir:ArithDialect", "//mlir:BytecodeReader", + "//mlir:CallOpInterfaces", "//mlir:CastInterfaces", "//mlir:FuncDialect", "//mlir:FuncExtensions", 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..cd7f7f018166134f8586272b12e677b4fc178350 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", 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..c03672eb4136eddcc94eb72193291ff27f33ffd2 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", 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..57b29eb46e084085e92d98d04d07d0812173d1b1 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", ], ) @@ -361,6 +363,7 @@ cc_library( "//mlir:Pass", "//mlir:TransformDebugExtension", "//mlir:TransformDialect", + "//mlir:TransformDialectInterfaces", "//mlir:TransformDialectTransforms", "//mlir:TransformPDLExtension", ], @@ -385,6 +388,7 @@ cc_library( ":TestTypeDefsIncGen", "//llvm:Support", "//mlir:ArithDialect", + "//mlir:CallOpInterfaces", "//mlir:ControlFlowInterfaces", "//mlir:CopyOpInterface", "//mlir:DLTIDialect", @@ -399,6 +403,7 @@ cc_library( "//mlir:IR", "//mlir:InferIntRangeInterface", "//mlir:InferTypeOpInterface", + "//mlir:InliningUtils", "//mlir:LLVMDialect", "//mlir:LinalgDialect", "//mlir:LoopLikeInterface", @@ -407,7 +412,6 @@ cc_library( "//mlir:SideEffectInterfaces", "//mlir:Support", "//mlir:TensorDialect", - "//mlir:TransformUtils", "//mlir:Transforms", "//mlir:ViewLikeInterface", ], @@ -505,6 +509,7 @@ cc_library( "//mlir:TensorTilingInterfaceImpl", "//mlir:TilingInterface", "//mlir:TransformDialect", + "//mlir:TransformDialectInterfaces", "//mlir:Transforms", ], ) @@ -532,7 +537,7 @@ cc_library( "//mlir:PDLInterpDialect", "//mlir:Pass", "//mlir:Support", - "//mlir:TransformUtils", + "//mlir:Transforms", ], ) @@ -569,8 +574,9 @@ cc_library( "//mlir:Pass", "//mlir:SCFDialect", "//mlir:SPIRVDialect", + "//mlir:SideEffectInterfaces", "//mlir:Support", - "//mlir:TransformUtils", + "//mlir:Transforms", ], ) @@ -600,7 +606,7 @@ cc_library( "//mlir:Pass", "//mlir:SCFDialect", "//mlir:SCFTransforms", - "//mlir:TransformUtils", + "//mlir:Transforms", ], ) @@ -695,7 +701,6 @@ cc_library( "//mlir:SCFToControlFlow", "//mlir:SPIRVDialect", "//mlir:ToLLVMIRTranslation", - "//mlir:TransformUtils", "//mlir:Transforms", "//mlir:VectorDialect", "//mlir:VectorToLLVM", @@ -728,7 +733,6 @@ cc_library( "//mlir:SCFTransforms", "//mlir:TensorDialect", "//mlir:TensorTransforms", - "//mlir:TransformUtils", "//mlir:Transforms", "//mlir:VectorDialect", "//mlir:VectorToSCF", @@ -770,7 +774,7 @@ cc_library( "//mlir:MathTransforms", "//mlir:Pass", "//mlir:SCFDialect", - "//mlir:TransformUtils", + "//mlir:Transforms", "//mlir:VectorDialect", "//mlir:X86VectorDialect", ], @@ -786,7 +790,7 @@ cc_library( "//mlir:IR", "//mlir:MathDialect", "//mlir:Pass", - "//mlir:TransformUtils", + "//mlir:Transforms", "//mlir:VCIXDialect", "//mlir:VectorDialect", ], @@ -814,7 +818,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", @@ -850,7 +853,7 @@ cc_library( "//mlir:Pass", "//mlir:SCFDialect", "//mlir:Support", - "//mlir:TransformUtils", + "//mlir:Transforms", ], ) @@ -869,7 +872,7 @@ cc_library( "//mlir:SCFDialect", "//mlir:SCFTransforms", "//mlir:SCFUtils", - "//mlir:TransformUtils", + "//mlir:Transforms", ], ) @@ -994,7 +997,7 @@ cc_library( "//mlir:FuncTransforms", "//mlir:IR", "//mlir:Pass", - "//mlir:TransformUtils", + "//mlir:Transforms", ], ) @@ -1010,6 +1013,7 @@ cc_library( "//mlir:TensorDialect", "//mlir:TensorTransforms", "//mlir:TransformDialect", + "//mlir:TransformDialectInterfaces", "//mlir:Transforms", ], ) @@ -1033,7 +1037,7 @@ cc_library( "//mlir:SCFDialect", "//mlir:Support", "//mlir:TensorDialect", - "//mlir:TransformUtils", + "//mlir:Transforms", "//mlir:VectorDialect", "//mlir:VectorToSCF", "//mlir:VectorTransforms", @@ -1041,18 +1045,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([ @@ -1119,6 +1111,6 @@ cc_library( "//mlir:Parser", "//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",