[llvm-branch-commits] [clang] [flang] [libc] [llvm] [mlir] Users/tstellar/merge doxygen (PR #213838)
Tom Stellard via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Mon Aug 3 22:10:21 PDT 2026
Valentin Clement =?utf-8?b?KOODkOODrOODsw=?=,Ayokunle Amodu
<ayokunle321 at gmail.com>,Tom Stellard <tstellar at redhat.com>,Michael Jones
<michaelrj at google.com>,Tom Stellard <tstellar at redhat.com>,Tom Stellard
<tstellar at redhat.com>,Tom Stellard <tstellar at redhat.com>,Tom Stellard
<tstellar at redhat.com>
Message-ID: <llvm.org/llvm/llvm-project/pull/213838 at github.com>
In-Reply-To:
https://github.com/tstellar created https://github.com/llvm/llvm-project/pull/213838
None
>From c3a73d8cfa2610da3d6f6379545f617f8970bd05 Mon Sep 17 00:00:00 2001
From: Tom Stellard <tstellar at redhat.com>
Date: Tue, 28 Jul 2026 22:48:55 -0700
Subject: [PATCH 01/43] workflows/release-documentation: Rework workflow to
make it testable
Removed the environment declaration from the validation job and split
out the www-releases update into a separate job. This makes it safe
and possible to add a pull_request trigger so we can at least test
building the documentation when someone submits a pull request.
---
.github/workflows/release-documentation.yml | 48 +++++++++++++++------
1 file changed, 34 insertions(+), 14 deletions(-)
diff --git a/.github/workflows/release-documentation.yml b/.github/workflows/release-documentation.yml
index d0b6a9994edb5..5347d4136bc26 100644
--- a/.github/workflows/release-documentation.yml
+++ b/.github/workflows/release-documentation.yml
@@ -38,6 +38,24 @@ on:
LLVM_TOKEN_GENERATOR_PRIVATE_KEY:
description: "Private key for our GitHub App we use for generating access tokens."
required: true
+ # Run on pull_requests for testing purposes.
+ pull_request:
+ paths:
+ - '.github/workflows/release-documentation.yml'
+ - 'llvm/utils/release/build-docs.sh'
+ types:
+ - opened
+ - synchronize
+ - reopened
+ # When a PR is closed, we still start this workflow, but then skip
+ # all the jobs, which makes it effectively a no-op. The reason to
+ # do this is that it allows us to take advantage of concurrency groups
+ # to cancel in progress CI jobs whenever the PR is closed.
+ - closed
+
+concurrency:
+ group: ${{ github.workflow }}-${{ inputs.release-version || github.event.pull_request.number }}
+ cancel-in-progress: True
jobs:
# This job checks permissions and validates inputs to prevent potential
@@ -47,9 +65,6 @@ jobs:
release-man-pages-validate-input:
name: Release Man Pages Validate Input
runs-on: ubuntu-24.04
- environment:
- name: release
- deployment: false
permissions:
contents: read
steps:
@@ -59,13 +74,6 @@ jobs:
sparse-checkout: |
.github/workflows/
- - name: Check Permissions
- uses: ./.github/workflows/require-team-membership
- with:
- team-slug: llvm-release-managers
- LLVM_TOKEN_GENERATOR_CLIENT_ID: ${{ secrets.LLVM_TOKEN_GENERATOR_CLIENT_ID }}
- LLVM_TOKEN_GENERATOR_PRIVATE_KEY: ${{ secrets.LLVM_TOKEN_GENERATOR_PRIVATE_KEY }}
-
- name: Validate Input
uses: ./.github/workflows/validate-release-version
with:
@@ -84,8 +92,6 @@ jobs:
man-page-tarball-name: ${{ steps.vars.outputs.man-page-tarball-name }}
man-page-upload: ${{ steps.vars.outputs.man-page-upload }}
man-page-attestation-name: ${{ steps.vars.outputs.man-page-attestation-name }}
- env:
- upload: ${{ inputs.upload && !contains(inputs.release-version, 'rc') }}
steps:
- name: Collect Variables
id: vars
@@ -155,8 +161,23 @@ jobs:
name: release-notes
path: docs-build/html-export/
+
+ upload-release-notes:
+ name: "Upload Release Notes"
+ runs-on: ubuntu-24.04
+ environment:
+ deployment: false
+ name: release
+ needs:
+ - release-documentation
+ if: >-
+ github.event_name != 'pull_request' &&
+ inputs.upload &&
+ !contains(inputs.release-version, 'rc')
+ permissions:
+ contents: read
+ steps:
- name: Clone www-releases
- if: env.upload
uses: actions/checkout at df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
with:
repository: ${{ github.repository_owner }}/www-releases
@@ -166,7 +187,6 @@ jobs:
persist-credentials: false
- name: Upload Release Notes
- if: env.upload
env:
PUSH_TOKEN: ${{ secrets.LLVMBOT_WWW_RELEASES_PUSH }}
GH_TOKEN: ${{ secrets.WWW_RELEASES_TOKEN }}
>From 32f690d630f6d95fec6e60f49ee1e14ed66aa5f9 Mon Sep 17 00:00:00 2001
From: Tom Stellard <tstellar at redhat.com>
Date: Wed, 29 Jul 2026 11:18:49 -0700
Subject: [PATCH 02/43] More fixes
---
.github/workflows/release-documentation.yml | 48 +++++++--------------
1 file changed, 15 insertions(+), 33 deletions(-)
diff --git a/.github/workflows/release-documentation.yml b/.github/workflows/release-documentation.yml
index 5347d4136bc26..3c080dce679c9 100644
--- a/.github/workflows/release-documentation.yml
+++ b/.github/workflows/release-documentation.yml
@@ -58,41 +58,25 @@ concurrency:
cancel-in-progress: True
jobs:
- # This job checks permissions and validates inputs to prevent potential
- # malicious actions. Since the release-documentation job has contents: write
- # permissions we need to be extra careful about who can run the job and what
- # inputs can be provided.
- release-man-pages-validate-input:
- name: Release Man Pages Validate Input
- runs-on: ubuntu-24.04
- permissions:
- contents: read
- steps:
- - uses: actions/checkout at df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- with:
- persist-credentials: false
- sparse-checkout: |
- .github/workflows/
-
- - name: Validate Input
- uses: ./.github/workflows/validate-release-version
- with:
- release-version: ${{ inputs.release-version }}
-
release-documentation:
name: Build and Upload Release Documentation and Man Pages
runs-on: ubuntu-24.04
- needs:
- - release-man-pages-validate-input
+ permissions:
+ contents: read
outputs:
man-page-digest: ${{ steps.man-page-digest.outputs.man-page-digest }}
man-page-artifact-id: ${{ steps.man-page-artifact-upload.outputs.artifact-id }}
man-page-release-version: ${{ steps.vars.outputs.man-page-release-version }}
- man-page-tarball-name: ${{ steps.vars.outputs.man-page-tarball-name }}
man-page-upload: ${{ steps.vars.outputs.man-page-upload }}
man-page-attestation-name: ${{ steps.vars.outputs.man-page-attestation-name }}
steps:
+ - name: Validate Input
+ if: inputs.release-version
+ uses: ./.github/workflows/validate-release-version
+ with:
+ release-version: ${{ inputs.release-version }}
+
- name: Collect Variables
id: vars
env:
@@ -102,7 +86,6 @@ jobs:
run: |
{
echo "man-page-release-version=$INPUTS_RELEASE_VERSION"
- echo "man-page-tarball-name=llvm_man_pages-$INPUTS_RELEASE_VERSION.tar.xz"
echo "man-page-ref=llvmorg-$INPUTS_RELEASE_VERSION"
echo "man-page-upload=$UPLOAD_MAN_PAGES"
echo "man-page-attestation-name=$RUNNER_OS-$RUNNER_ARCH-release-man-page-attestation"
@@ -113,11 +96,6 @@ jobs:
with:
persist-credentials: false
- - name: Validate Input
- uses: ./.github/workflows/validate-release-version
- with:
- release-version: ${{ inputs.release-version }}
-
- name: Setup Python env
uses: actions/setup-python at ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
with:
@@ -135,17 +113,21 @@ jobs:
pip3 install --require-hashes --user -r ./llvm/docs/requirements.txt
- name: Build Documentation
+ id: build
env:
GITHUB_TOKEN: ${{ github.token }}
INPUTS_RELEASE_VERSION: ${{ inputs.release-version }}
run: |
- ./llvm/utils/release/build-docs.sh -release "$INPUTS_RELEASE_VERSION" -no-doxygen
+ ./llvm/utils/release/build-docs.sh \
+ $(test -n "$INPUTS_RELEASE_VERSION" && echo -release $INPUTS_RELEASE_VERSION || echo -srcdir llvm) -no-doxygen
+ echo "man-page-tarball-name=$(find . -iname 'llvm_man_pages-*')" >> "$GITHUB_OUTPUT"
+
- name: Generate sha256 digest for man page tarball
id: man-page-digest
shell: bash
env:
- TARBALL_NAME: ${{ steps.vars.outputs.man-page-tarball-name }}
+ TARBALL_NAME: ${{ steps.build.outputs.man-page-tarball-name }}
run: |
echo "man-page-digest=$(cat "$TARBALL_NAME" | sha256sum | cut -d ' ' -f 1)" >> $GITHUB_OUTPUT
@@ -153,7 +135,7 @@ jobs:
uses: actions/upload-artifact at 043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
path: |
- ${{ steps.vars.outputs.man-page-tarball-name }}
+ ${{ steps.build.outputs.man-page-tarball-name }}
- name: Create Release Notes Artifact
uses: actions/upload-artifact at 043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
>From cb399024cbe90862b9184d0b05412185fcea0630 Mon Sep 17 00:00:00 2001
From: Tom Stellard <tstellar at redhat.com>
Date: Wed, 29 Jul 2026 14:07:40 -0700
Subject: [PATCH 03/43] Cleanups
---
.github/workflows/release-documentation.yml | 24 +++------------------
1 file changed, 3 insertions(+), 21 deletions(-)
diff --git a/.github/workflows/release-documentation.yml b/.github/workflows/release-documentation.yml
index 3c080dce679c9..b1bc2f586f935 100644
--- a/.github/workflows/release-documentation.yml
+++ b/.github/workflows/release-documentation.yml
@@ -66,10 +66,6 @@ jobs:
outputs:
man-page-digest: ${{ steps.man-page-digest.outputs.man-page-digest }}
man-page-artifact-id: ${{ steps.man-page-artifact-upload.outputs.artifact-id }}
-
- man-page-release-version: ${{ steps.vars.outputs.man-page-release-version }}
- man-page-upload: ${{ steps.vars.outputs.man-page-upload }}
- man-page-attestation-name: ${{ steps.vars.outputs.man-page-attestation-name }}
steps:
- name: Validate Input
if: inputs.release-version
@@ -77,20 +73,6 @@ jobs:
with:
release-version: ${{ inputs.release-version }}
- - name: Collect Variables
- id: vars
- env:
- INPUTS_RELEASE_VERSION: ${{ inputs.release-version }}
- UPLOAD_MAN_PAGES: ${{ inputs.upload }}
- shell: bash
- run: |
- {
- echo "man-page-release-version=$INPUTS_RELEASE_VERSION"
- echo "man-page-ref=llvmorg-$INPUTS_RELEASE_VERSION"
- echo "man-page-upload=$UPLOAD_MAN_PAGES"
- echo "man-page-attestation-name=$RUNNER_OS-$RUNNER_ARCH-release-man-page-attestation"
- } >> "$GITHUB_OUTPUT"
-
- name: Checkout LLVM
uses: actions/checkout at df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
with:
@@ -205,10 +187,10 @@ jobs:
id: man-page-artifact-upload
uses: $/.github/workflows/upload-release-artifact
with:
- release-version: ${{ needs.release-documentation.outputs.man-page-release-version }}
+ release-version: ${{ inputs.release-version }}
artifact-id: ${{ needs.release-documentation.outputs.man-page-artifact-id }}
- attestation-name: ${{ needs.release-documentation.outputs.man-page-attestation-name }}
+ attestation-name: ${{ runner.os }}-${{ runner.arch }}-release-man-page-attestation
digest: ${{ needs.release-documentation.outputs.man-page-digest }}
- upload: ${{ needs.release-documentation.outputs.man-page-upload }}
+ upload: ${{ inputs.upload }}
LLVM_TOKEN_GENERATOR_CLIENT_ID: ${{ secrets.LLVM_TOKEN_GENERATOR_CLIENT_ID }}
LLVM_TOKEN_GENERATOR_PRIVATE_KEY: ${{ secrets.LLVM_TOKEN_GENERATOR_PRIVATE_KEY }}
>From 3903d540a1f4c13cdf7b5efecda907624e02e983 Mon Sep 17 00:00:00 2001
From: Tom Stellard <tstellar at redhat.com>
Date: Wed, 29 Jul 2026 14:20:58 -0700
Subject: [PATCH 04/43] Fix build of libcxx docs
---
llvm/utils/release/build-docs.sh | 14 +++-----------
1 file changed, 3 insertions(+), 11 deletions(-)
diff --git a/llvm/utils/release/build-docs.sh b/llvm/utils/release/build-docs.sh
index 648c829a62618..12f437e1d3ca7 100755
--- a/llvm/utils/release/build-docs.sh
+++ b/llvm/utils/release/build-docs.sh
@@ -149,22 +149,14 @@ export CXX=clang++
cmake -G Ninja $srcdir -B $builddir \
-DLLVM_ENABLE_PROJECTS="clang;clang-tools-extra;lld;polly;flang${extra_man_page_projects}" \
+ -DLLVM_ENABLE_RUNTIMES="libcxx;libcxxabi;libunwind;${extra_man_page_runtimes}" \
-DCMAKE_BUILD_TYPE=Release \
-DLLVM_BUILD_DOCS=ON \
$sphinx_flag \
$doxygen_flag \
$man_page_flag
-ninja -C $builddir $sphinx_targets $doxygen_targets $man_page_targets
-
-cmake -G Ninja $srcdir/../runtimes -B $builddir/runtimes-doc \
- -DLLVM_ENABLE_RUNTIMES="libcxx;libcxxabi;libunwind;${extra_man_page_runtimes}" \
- -DLLVM_ENABLE_SPHINX=ON \
- -DLLVM_BUILD_DOCS=ON \
- -DSPHINX_WARNINGS_AS_ERRORS=OFF
-
-ninja -C $builddir/runtimes-doc \
- docs-libcxx-html
+ninja -C $builddir $sphinx_targets $doxygen_targets $man_page_targets docs-libcxx-html
if [ "${no_man_page}" != "yes" ]; then
output="llvm_man_pages-${release}"
@@ -196,5 +188,5 @@ done
# Keep the documentation for the runtimes under /projects/ to avoid breaking existing links.
for d in libcxx/docs/; do
mkdir -p $html_dir/projects/$d
- mv $builddir/runtimes-doc/$d/html/* $html_dir/projects/$d/
+ mv $builddir/$d/html/* $html_dir/projects/$d/
done
>From 0a2c1abbe06944d9910ea2f42be01defcfe6532d Mon Sep 17 00:00:00 2001
From: Tom Stellard <tstellar at redhat.com>
Date: Wed, 29 Jul 2026 14:27:50 -0700
Subject: [PATCH 05/43] Fix typo
---
llvm/utils/release/build-docs.sh | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/llvm/utils/release/build-docs.sh b/llvm/utils/release/build-docs.sh
index 12f437e1d3ca7..04f17b629c669 100755
--- a/llvm/utils/release/build-docs.sh
+++ b/llvm/utils/release/build-docs.sh
@@ -128,7 +128,7 @@ if [ "${no_man_pages}" != "yes" ]; then
install_prefix=${builddir}/install
man_page_flag=" -DLLVM_ENABLE_SPHINX=ON -DSPHINX_WARNINGS_AS_ERRORS=OFF -DSPHINX_OUTPUT_MAN:BOOL=ON -DCMAKE_INSTALL_PREFIX=${install_prefix}"
extra_man_page_projects=";lldb;mlir;bolt"
- extra_man_page_runtimes=";compiler-rt;openmp;"
+ extra_man_page_runtimes=";compiler-rt;openmp"
else
echo "Man pages: disabled"
fi
>From 75bfe65962f1ea843dd1fa08c12e6e053e755e02 Mon Sep 17 00:00:00 2001
From: Tom Stellard <tstellar at redhat.com>
Date: Wed, 29 Jul 2026 14:38:23 -0700
Subject: [PATCH 06/43] XXX: Debug
---
llvm/utils/release/build-docs.sh | 1 +
1 file changed, 1 insertion(+)
diff --git a/llvm/utils/release/build-docs.sh b/llvm/utils/release/build-docs.sh
index 04f17b629c669..0f630b2e600d5 100755
--- a/llvm/utils/release/build-docs.sh
+++ b/llvm/utils/release/build-docs.sh
@@ -147,6 +147,7 @@ fi
export CC=clang
export CXX=clang++
+set -ex
cmake -G Ninja $srcdir -B $builddir \
-DLLVM_ENABLE_PROJECTS="clang;clang-tools-extra;lld;polly;flang${extra_man_page_projects}" \
-DLLVM_ENABLE_RUNTIMES="libcxx;libcxxabi;libunwind;${extra_man_page_runtimes}" \
>From eb9667fa754e0b49d46d0ae5993968e20cb94d94 Mon Sep 17 00:00:00 2001
From: Tom Stellard <tstellar at redhat.com>
Date: Wed, 29 Jul 2026 14:42:26 -0700
Subject: [PATCH 07/43] Fix typo
---
llvm/utils/release/build-docs.sh | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/llvm/utils/release/build-docs.sh b/llvm/utils/release/build-docs.sh
index 0f630b2e600d5..c7f440c638d34 100755
--- a/llvm/utils/release/build-docs.sh
+++ b/llvm/utils/release/build-docs.sh
@@ -150,7 +150,7 @@ export CXX=clang++
set -ex
cmake -G Ninja $srcdir -B $builddir \
-DLLVM_ENABLE_PROJECTS="clang;clang-tools-extra;lld;polly;flang${extra_man_page_projects}" \
- -DLLVM_ENABLE_RUNTIMES="libcxx;libcxxabi;libunwind;${extra_man_page_runtimes}" \
+ -DLLVM_ENABLE_RUNTIMES="libcxx;libcxxabi;libunwind${extra_man_page_runtimes}" \
-DCMAKE_BUILD_TYPE=Release \
-DLLVM_BUILD_DOCS=ON \
$sphinx_flag \
>From d207ede60437c8809a253ae3bed441527bacdd6b Mon Sep 17 00:00:00 2001
From: Tom Stellard <tstellar at redhat.com>
Date: Wed, 29 Jul 2026 16:00:55 -0700
Subject: [PATCH 08/43] Revert "Fix typo"
This reverts commit a5d98fb1210839d7b0fe58b0be77ed6d379226b4.
---
llvm/utils/release/build-docs.sh | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/llvm/utils/release/build-docs.sh b/llvm/utils/release/build-docs.sh
index c7f440c638d34..0f630b2e600d5 100755
--- a/llvm/utils/release/build-docs.sh
+++ b/llvm/utils/release/build-docs.sh
@@ -150,7 +150,7 @@ export CXX=clang++
set -ex
cmake -G Ninja $srcdir -B $builddir \
-DLLVM_ENABLE_PROJECTS="clang;clang-tools-extra;lld;polly;flang${extra_man_page_projects}" \
- -DLLVM_ENABLE_RUNTIMES="libcxx;libcxxabi;libunwind${extra_man_page_runtimes}" \
+ -DLLVM_ENABLE_RUNTIMES="libcxx;libcxxabi;libunwind;${extra_man_page_runtimes}" \
-DCMAKE_BUILD_TYPE=Release \
-DLLVM_BUILD_DOCS=ON \
$sphinx_flag \
>From 552261e3848c3c5d726235a056cf675f82883f1d Mon Sep 17 00:00:00 2001
From: Tom Stellard <tstellar at redhat.com>
Date: Wed, 29 Jul 2026 16:00:58 -0700
Subject: [PATCH 09/43] Revert "XXX: Debug"
This reverts commit 028443c5e4e259ca9f4d38145350a7d3d6494a66.
---
llvm/utils/release/build-docs.sh | 1 -
1 file changed, 1 deletion(-)
diff --git a/llvm/utils/release/build-docs.sh b/llvm/utils/release/build-docs.sh
index 0f630b2e600d5..04f17b629c669 100755
--- a/llvm/utils/release/build-docs.sh
+++ b/llvm/utils/release/build-docs.sh
@@ -147,7 +147,6 @@ fi
export CC=clang
export CXX=clang++
-set -ex
cmake -G Ninja $srcdir -B $builddir \
-DLLVM_ENABLE_PROJECTS="clang;clang-tools-extra;lld;polly;flang${extra_man_page_projects}" \
-DLLVM_ENABLE_RUNTIMES="libcxx;libcxxabi;libunwind;${extra_man_page_runtimes}" \
>From e896a5010132f0911a697682cd9d6701e2a42adb Mon Sep 17 00:00:00 2001
From: Tom Stellard <tstellar at redhat.com>
Date: Wed, 29 Jul 2026 16:01:00 -0700
Subject: [PATCH 10/43] Revert "Fix typo"
This reverts commit f90c6dd3e5c5855b327b059982eb94d0ab3a0f73.
---
llvm/utils/release/build-docs.sh | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/llvm/utils/release/build-docs.sh b/llvm/utils/release/build-docs.sh
index 04f17b629c669..12f437e1d3ca7 100755
--- a/llvm/utils/release/build-docs.sh
+++ b/llvm/utils/release/build-docs.sh
@@ -128,7 +128,7 @@ if [ "${no_man_pages}" != "yes" ]; then
install_prefix=${builddir}/install
man_page_flag=" -DLLVM_ENABLE_SPHINX=ON -DSPHINX_WARNINGS_AS_ERRORS=OFF -DSPHINX_OUTPUT_MAN:BOOL=ON -DCMAKE_INSTALL_PREFIX=${install_prefix}"
extra_man_page_projects=";lldb;mlir;bolt"
- extra_man_page_runtimes=";compiler-rt;openmp"
+ extra_man_page_runtimes=";compiler-rt;openmp;"
else
echo "Man pages: disabled"
fi
>From cf5a93a31a41fdbebc29da37926c95f7d8ed81d7 Mon Sep 17 00:00:00 2001
From: Tom Stellard <tstellar at redhat.com>
Date: Wed, 29 Jul 2026 16:01:02 -0700
Subject: [PATCH 11/43] Revert "Fix build of libcxx docs"
This reverts commit 179432674685f1eb5a7546f1fa1434ab75fee36f.
---
llvm/utils/release/build-docs.sh | 14 +++++++++++---
1 file changed, 11 insertions(+), 3 deletions(-)
diff --git a/llvm/utils/release/build-docs.sh b/llvm/utils/release/build-docs.sh
index 12f437e1d3ca7..648c829a62618 100755
--- a/llvm/utils/release/build-docs.sh
+++ b/llvm/utils/release/build-docs.sh
@@ -149,14 +149,22 @@ export CXX=clang++
cmake -G Ninja $srcdir -B $builddir \
-DLLVM_ENABLE_PROJECTS="clang;clang-tools-extra;lld;polly;flang${extra_man_page_projects}" \
- -DLLVM_ENABLE_RUNTIMES="libcxx;libcxxabi;libunwind;${extra_man_page_runtimes}" \
-DCMAKE_BUILD_TYPE=Release \
-DLLVM_BUILD_DOCS=ON \
$sphinx_flag \
$doxygen_flag \
$man_page_flag
-ninja -C $builddir $sphinx_targets $doxygen_targets $man_page_targets docs-libcxx-html
+ninja -C $builddir $sphinx_targets $doxygen_targets $man_page_targets
+
+cmake -G Ninja $srcdir/../runtimes -B $builddir/runtimes-doc \
+ -DLLVM_ENABLE_RUNTIMES="libcxx;libcxxabi;libunwind;${extra_man_page_runtimes}" \
+ -DLLVM_ENABLE_SPHINX=ON \
+ -DLLVM_BUILD_DOCS=ON \
+ -DSPHINX_WARNINGS_AS_ERRORS=OFF
+
+ninja -C $builddir/runtimes-doc \
+ docs-libcxx-html
if [ "${no_man_page}" != "yes" ]; then
output="llvm_man_pages-${release}"
@@ -188,5 +196,5 @@ done
# Keep the documentation for the runtimes under /projects/ to avoid breaking existing links.
for d in libcxx/docs/; do
mkdir -p $html_dir/projects/$d
- mv $builddir/$d/html/* $html_dir/projects/$d/
+ mv $builddir/runtimes-doc/$d/html/* $html_dir/projects/$d/
done
>From f834d30965598fd138d333f47e2ff749fe874fc5 Mon Sep 17 00:00:00 2001
From: Tom Stellard <tstellar at redhat.com>
Date: Wed, 29 Jul 2026 16:10:40 -0700
Subject: [PATCH 12/43] Fix
---
llvm/utils/release/build-docs.sh | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/llvm/utils/release/build-docs.sh b/llvm/utils/release/build-docs.sh
index 648c829a62618..e19d1a39aeabc 100755
--- a/llvm/utils/release/build-docs.sh
+++ b/llvm/utils/release/build-docs.sh
@@ -144,8 +144,8 @@ fi
# This is just to ensure we're using the right compiler
# When running this locally, the script otherwise might
# prefer GCC.
-export CC=clang
-export CXX=clang++
+#export CC=clang
+#export CXX=clang++
cmake -G Ninja $srcdir -B $builddir \
-DLLVM_ENABLE_PROJECTS="clang;clang-tools-extra;lld;polly;flang${extra_man_page_projects}" \
>From d315d49db09582c6bb17487fc85770fdde6bb6cd Mon Sep 17 00:00:00 2001
From: Tom Stellard <tstellar at redhat.com>
Date: Wed, 29 Jul 2026 16:25:07 -0700
Subject: [PATCH 13/43] debug
---
llvm/utils/release/build-docs.sh | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/llvm/utils/release/build-docs.sh b/llvm/utils/release/build-docs.sh
index e19d1a39aeabc..a2c6a3776d03c 100755
--- a/llvm/utils/release/build-docs.sh
+++ b/llvm/utils/release/build-docs.sh
@@ -20,7 +20,7 @@
# * pip install --user -r ./llvm/docs/requirements.txt
#===------------------------------------------------------------------------===#
-set -e
+set -ex
builddir=docs-build
srcdir=$(readlink -f $(dirname "$(readlink -f "$0")")/../..)
>From 94ddb9013b63a1f69c69bdd3fb2ac0eb1a45ad5e Mon Sep 17 00:00:00 2001
From: Tom Stellard <tstellar at redhat.com>
Date: Wed, 29 Jul 2026 16:41:12 -0700
Subject: [PATCH 14/43] Fix
---
.github/workflows/release-documentation.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/release-documentation.yml b/.github/workflows/release-documentation.yml
index b1bc2f586f935..0efb9e5ff44c4 100644
--- a/.github/workflows/release-documentation.yml
+++ b/.github/workflows/release-documentation.yml
@@ -102,7 +102,7 @@ jobs:
run: |
./llvm/utils/release/build-docs.sh \
$(test -n "$INPUTS_RELEASE_VERSION" && echo -release $INPUTS_RELEASE_VERSION || echo -srcdir llvm) -no-doxygen
- echo "man-page-tarball-name=$(find . -iname 'llvm_man_pages-*')" >> "$GITHUB_OUTPUT"
+ echo "man-page-tarball-name=$(basename $(find . -iname 'llvm_man_pages-*'))" >> "$GITHUB_OUTPUT"
- name: Generate sha256 digest for man page tarball
>From c5cafa6d6add19fcbf42e3e61f9864d008a3ad61 Mon Sep 17 00:00:00 2001
From: Tom Stellard <tstellar at redhat.com>
Date: Wed, 29 Jul 2026 16:58:50 -0700
Subject: [PATCH 15/43] Add artifact name
---
.github/workflows/release-documentation.yml | 1 +
1 file changed, 1 insertion(+)
diff --git a/.github/workflows/release-documentation.yml b/.github/workflows/release-documentation.yml
index 0efb9e5ff44c4..bf9c400d3bfc2 100644
--- a/.github/workflows/release-documentation.yml
+++ b/.github/workflows/release-documentation.yml
@@ -116,6 +116,7 @@ jobs:
- id: man-page-artifact-upload
uses: actions/upload-artifact at 043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
+ name: man-pages
path: |
${{ steps.build.outputs.man-page-tarball-name }}
>From 69f79bb0526e5a2914b1db7f3bdb3620bd72b8a8 Mon Sep 17 00:00:00 2001
From: Tom Stellard <tstellar at redhat.com>
Date: Wed, 29 Jul 2026 17:12:40 -0700
Subject: [PATCH 16/43] Fixes and cleanups
---
.github/workflows/release-documentation.yml | 10 +++++-----
llvm/utils/release/build-docs.sh | 8 +-------
2 files changed, 6 insertions(+), 12 deletions(-)
diff --git a/.github/workflows/release-documentation.yml b/.github/workflows/release-documentation.yml
index bf9c400d3bfc2..03fa40edcc91b 100644
--- a/.github/workflows/release-documentation.yml
+++ b/.github/workflows/release-documentation.yml
@@ -67,17 +67,17 @@ jobs:
man-page-digest: ${{ steps.man-page-digest.outputs.man-page-digest }}
man-page-artifact-id: ${{ steps.man-page-artifact-upload.outputs.artifact-id }}
steps:
+ - name: Checkout LLVM
+ uses: actions/checkout at df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
+ with:
+ persist-credentials: false
+
- name: Validate Input
if: inputs.release-version
uses: ./.github/workflows/validate-release-version
with:
release-version: ${{ inputs.release-version }}
- - name: Checkout LLVM
- uses: actions/checkout at df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- with:
- persist-credentials: false
-
- name: Setup Python env
uses: actions/setup-python at ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
with:
diff --git a/llvm/utils/release/build-docs.sh b/llvm/utils/release/build-docs.sh
index a2c6a3776d03c..3c80af1317d11 100755
--- a/llvm/utils/release/build-docs.sh
+++ b/llvm/utils/release/build-docs.sh
@@ -20,7 +20,7 @@
# * pip install --user -r ./llvm/docs/requirements.txt
#===------------------------------------------------------------------------===#
-set -ex
+set -e
builddir=docs-build
srcdir=$(readlink -f $(dirname "$(readlink -f "$0")")/../..)
@@ -141,12 +141,6 @@ else
echo "Doxygen: disabled"
fi
-# This is just to ensure we're using the right compiler
-# When running this locally, the script otherwise might
-# prefer GCC.
-#export CC=clang
-#export CXX=clang++
-
cmake -G Ninja $srcdir -B $builddir \
-DLLVM_ENABLE_PROJECTS="clang;clang-tools-extra;lld;polly;flang${extra_man_page_projects}" \
-DCMAKE_BUILD_TYPE=Release \
>From fdd1f1c979c72e48acbc9e405c29259a4f4a9e16 Mon Sep 17 00:00:00 2001
From: Tom Stellard <tstellar at redhat.com>
Date: Thu, 30 Jul 2026 09:25:50 -0700
Subject: [PATCH 17/43] Fix
---
.github/workflows/release-documentation.yml | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/.github/workflows/release-documentation.yml b/.github/workflows/release-documentation.yml
index 03fa40edcc91b..7e6171f2ab1d0 100644
--- a/.github/workflows/release-documentation.yml
+++ b/.github/workflows/release-documentation.yml
@@ -102,7 +102,7 @@ jobs:
run: |
./llvm/utils/release/build-docs.sh \
$(test -n "$INPUTS_RELEASE_VERSION" && echo -release $INPUTS_RELEASE_VERSION || echo -srcdir llvm) -no-doxygen
- echo "man-page-tarball-name=$(basename $(find . -iname 'llvm_man_pages-*'))" >> "$GITHUB_OUTPUT"
+ echo "man-page-tarball-name=$(basename $(find . -iname 'llvm_man_pages-*.tar.xz'))" >> "$GITHUB_OUTPUT"
- name: Generate sha256 digest for man page tarball
@@ -151,15 +151,20 @@ jobs:
path: www-releases
persist-credentials: false
+ - name: Download Release Notes Artifact
+ uses: actions/download-artifact at 3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
+ id: download-artifact
+ with:
+ name: ${{ github.workspace }}/www-releases/${{ inputs.release-version }}
+
- name: Upload Release Notes
env:
PUSH_TOKEN: ${{ secrets.LLVMBOT_WWW_RELEASES_PUSH }}
GH_TOKEN: ${{ secrets.WWW_RELEASES_TOKEN }}
INPUTS_RELEASE_VERSION: ${{ inputs.release-version }}
run: |
- mkdir -p www-releases/$INPUTS_RELEASE_VERSION
- mv ./docs-build/html-export/* www-releases/$INPUTS_RELEASE_VERSION
cd www-releases
+ ls -ltr www-releases/$INPUT_RELEASE_VERSION/*
git checkout -b $INPUTS_RELEASE_VERSION
git add $INPUTS_RELEASE_VERSION
git config user.email "llvmbot at llvm.org"
>From 1c65ba5f1d8c813e498edb0a77a827c7e5b9bc9e Mon Sep 17 00:00:00 2001
From: Tom Stellard <tstellar at redhat.com>
Date: Thu, 30 Jul 2026 09:27:46 -0700
Subject: [PATCH 18/43] XXX: Debug
---
.github/workflows/release-documentation.yml | 7 -------
1 file changed, 7 deletions(-)
diff --git a/.github/workflows/release-documentation.yml b/.github/workflows/release-documentation.yml
index 7e6171f2ab1d0..f5dd9b170c3e7 100644
--- a/.github/workflows/release-documentation.yml
+++ b/.github/workflows/release-documentation.yml
@@ -130,15 +130,8 @@ jobs:
upload-release-notes:
name: "Upload Release Notes"
runs-on: ubuntu-24.04
- environment:
- deployment: false
- name: release
needs:
- release-documentation
- if: >-
- github.event_name != 'pull_request' &&
- inputs.upload &&
- !contains(inputs.release-version, 'rc')
permissions:
contents: read
steps:
>From b6a39d128577f7ee07ae9ab9109246bdb1ca1a24 Mon Sep 17 00:00:00 2001
From: Tom Stellard <tstellar at redhat.com>
Date: Thu, 30 Jul 2026 09:45:58 -0700
Subject: [PATCH 19/43] Fix
---
.github/workflows/release-documentation.yml | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/.github/workflows/release-documentation.yml b/.github/workflows/release-documentation.yml
index f5dd9b170c3e7..c082c1245ed74 100644
--- a/.github/workflows/release-documentation.yml
+++ b/.github/workflows/release-documentation.yml
@@ -148,7 +148,8 @@ jobs:
uses: actions/download-artifact at 3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
id: download-artifact
with:
- name: ${{ github.workspace }}/www-releases/${{ inputs.release-version }}
+ name: release-notes
+ path: ${{ github.workspace }}/www-releases/${{ inputs.release-version }}
- name: Upload Release Notes
env:
>From d3f3fb4c19e23a3d8f9f0a82b1b770c100840be4 Mon Sep 17 00:00:00 2001
From: Tom Stellard <tstellar at redhat.com>
Date: Thu, 30 Jul 2026 10:00:32 -0700
Subject: [PATCH 20/43] Debug
---
.github/workflows/release-documentation.yml | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/.github/workflows/release-documentation.yml b/.github/workflows/release-documentation.yml
index c082c1245ed74..cf16df8fa6b78 100644
--- a/.github/workflows/release-documentation.yml
+++ b/.github/workflows/release-documentation.yml
@@ -158,7 +158,8 @@ jobs:
INPUTS_RELEASE_VERSION: ${{ inputs.release-version }}
run: |
cd www-releases
- ls -ltr www-releases/$INPUT_RELEASE_VERSION/*
+ ls -ltr *
+ ls -ltr $INPUT_RELEASE_VERSION/*
git checkout -b $INPUTS_RELEASE_VERSION
git add $INPUTS_RELEASE_VERSION
git config user.email "llvmbot at llvm.org"
>From c110e71d569ea0f95e8226bb0c840961985c0948 Mon Sep 17 00:00:00 2001
From: Tom Stellard <tstellar at redhat.com>
Date: Thu, 30 Jul 2026 10:25:49 -0700
Subject: [PATCH 21/43] Remove debug
---
.github/workflows/release-documentation.yml | 2 --
1 file changed, 2 deletions(-)
diff --git a/.github/workflows/release-documentation.yml b/.github/workflows/release-documentation.yml
index cf16df8fa6b78..4ecd012d337d2 100644
--- a/.github/workflows/release-documentation.yml
+++ b/.github/workflows/release-documentation.yml
@@ -158,8 +158,6 @@ jobs:
INPUTS_RELEASE_VERSION: ${{ inputs.release-version }}
run: |
cd www-releases
- ls -ltr *
- ls -ltr $INPUT_RELEASE_VERSION/*
git checkout -b $INPUTS_RELEASE_VERSION
git add $INPUTS_RELEASE_VERSION
git config user.email "llvmbot at llvm.org"
>From 977d086160d917cd95cb0bc6176f24f05adc8d36 Mon Sep 17 00:00:00 2001
From: Tom Stellard <tstellar at redhat.com>
Date: Thu, 30 Jul 2026 10:27:05 -0700
Subject: [PATCH 22/43] Revert "XXX: Debug"
This reverts commit ef443b1bebd360a4aad44d46b2a63621ccaba589.
---
.github/workflows/release-documentation.yml | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/.github/workflows/release-documentation.yml b/.github/workflows/release-documentation.yml
index 4ecd012d337d2..ccfc649ba151e 100644
--- a/.github/workflows/release-documentation.yml
+++ b/.github/workflows/release-documentation.yml
@@ -130,8 +130,15 @@ jobs:
upload-release-notes:
name: "Upload Release Notes"
runs-on: ubuntu-24.04
+ environment:
+ deployment: false
+ name: release
needs:
- release-documentation
+ if: >-
+ github.event_name != 'pull_request' &&
+ inputs.upload &&
+ !contains(inputs.release-version, 'rc')
permissions:
contents: read
steps:
>From d15670a49c5636f8fc78c8ef268391f09fd3a5e2 Mon Sep 17 00:00:00 2001
From: Tom Stellard <tstellar at redhat.com>
Date: Thu, 30 Jul 2026 16:56:28 -0700
Subject: [PATCH 23/43] Remove permissions
---
.github/workflows/release-documentation.yml | 2 --
1 file changed, 2 deletions(-)
diff --git a/.github/workflows/release-documentation.yml b/.github/workflows/release-documentation.yml
index ccfc649ba151e..58229407b0f5b 100644
--- a/.github/workflows/release-documentation.yml
+++ b/.github/workflows/release-documentation.yml
@@ -61,8 +61,6 @@ jobs:
release-documentation:
name: Build and Upload Release Documentation and Man Pages
runs-on: ubuntu-24.04
- permissions:
- contents: read
outputs:
man-page-digest: ${{ steps.man-page-digest.outputs.man-page-digest }}
man-page-artifact-id: ${{ steps.man-page-artifact-upload.outputs.artifact-id }}
>From 07b6aef5b643f2e3c41f6be62398e9e988c513dd Mon Sep 17 00:00:00 2001
From: Tom Stellard <tstellar at redhat.com>
Date: Fri, 31 Jul 2026 05:11:43 -0700
Subject: [PATCH 24/43] Add missing if
---
.github/workflows/release-documentation.yml | 3 +++
1 file changed, 3 insertions(+)
diff --git a/.github/workflows/release-documentation.yml b/.github/workflows/release-documentation.yml
index 58229407b0f5b..c0b188eac6d24 100644
--- a/.github/workflows/release-documentation.yml
+++ b/.github/workflows/release-documentation.yml
@@ -61,6 +61,9 @@ jobs:
release-documentation:
name: Build and Upload Release Documentation and Man Pages
runs-on: ubuntu-24.04
+ if: >-
+ github.repository_owner == 'llvm' &&
+ github.event.action != 'closed'
outputs:
man-page-digest: ${{ steps.man-page-digest.outputs.man-page-digest }}
man-page-artifact-id: ${{ steps.man-page-artifact-upload.outputs.artifact-id }}
>From 8f376b886e99d93f5ae78838244918abe2767211 Mon Sep 17 00:00:00 2001
From: Tom Stellard <tstellar at redhat.com>
Date: Fri, 31 Jul 2026 08:53:29 -0700
Subject: [PATCH 25/43] Fixes
---
.github/workflows/release-documentation.yml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/.github/workflows/release-documentation.yml b/.github/workflows/release-documentation.yml
index c0b188eac6d24..34e8e59f094d9 100644
--- a/.github/workflows/release-documentation.yml
+++ b/.github/workflows/release-documentation.yml
@@ -55,7 +55,7 @@ on:
concurrency:
group: ${{ github.workflow }}-${{ inputs.release-version || github.event.pull_request.number }}
- cancel-in-progress: True
+ cancel-in-progress: true
jobs:
release-documentation:
@@ -102,7 +102,7 @@ jobs:
INPUTS_RELEASE_VERSION: ${{ inputs.release-version }}
run: |
./llvm/utils/release/build-docs.sh \
- $(test -n "$INPUTS_RELEASE_VERSION" && echo -release $INPUTS_RELEASE_VERSION || echo -srcdir llvm) -no-doxygen
+ $(test -n "$INPUTS_RELEASE_VERSION" && echo -release "$INPUTS_RELEASE_VERSION" || echo -srcdir llvm) -no-doxygen
echo "man-page-tarball-name=$(basename $(find . -iname 'llvm_man_pages-*.tar.xz'))" >> "$GITHUB_OUTPUT"
>From 9b5c4a56d7dd6b8d45e07477f0c6cfefceacadad Mon Sep 17 00:00:00 2001
From: Tom Stellard <tstellar at redhat.com>
Date: Fri, 31 Jul 2026 11:37:13 -0700
Subject: [PATCH 26/43] Quote variable
---
.github/workflows/release-documentation.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/release-documentation.yml b/.github/workflows/release-documentation.yml
index 34e8e59f094d9..82cbfd72416e0 100644
--- a/.github/workflows/release-documentation.yml
+++ b/.github/workflows/release-documentation.yml
@@ -112,7 +112,7 @@ jobs:
env:
TARBALL_NAME: ${{ steps.build.outputs.man-page-tarball-name }}
run: |
- echo "man-page-digest=$(cat "$TARBALL_NAME" | sha256sum | cut -d ' ' -f 1)" >> $GITHUB_OUTPUT
+ echo "man-page-digest=$(cat "$TARBALL_NAME" | sha256sum | cut -d ' ' -f 1)" >> "$GITHUB_OUTPUT"
- id: man-page-artifact-upload
uses: actions/upload-artifact at 043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
>From b11533f1725d153727fb434ff23e164b60ea0ecb Mon Sep 17 00:00:00 2001
From: Tom Stellard <tstellar at redhat.com>
Date: Sat, 1 Aug 2026 15:48:36 -0700
Subject: [PATCH 27/43] Fix concurrency
---
.github/workflows/release-documentation.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/release-documentation.yml b/.github/workflows/release-documentation.yml
index 82cbfd72416e0..c19148017cfec 100644
--- a/.github/workflows/release-documentation.yml
+++ b/.github/workflows/release-documentation.yml
@@ -54,7 +54,7 @@ on:
- closed
concurrency:
- group: ${{ github.workflow }}-${{ inputs.release-version || github.event.pull_request.number }}
+ group: release-documentation-${{ inputs.release-version || github.event.pull_request.number }}
cancel-in-progress: true
jobs:
>From 6145f43f50ebc69124f43de3dc38aa676e4df3a5 Mon Sep 17 00:00:00 2001
From: Tom Stellard <tstellar at redhat.com>
Date: Fri, 31 Jul 2026 16:59:35 -0700
Subject: [PATCH 28/43] workflows: Merge release-doxygen into
release-documenation
These two workflows use the same script and have the same structure,
so it's easier just to have one job that builds both.
---
.github/workflows/release-documentation.yml | 45 ++++++++++++++++-----
1 file changed, 35 insertions(+), 10 deletions(-)
diff --git a/.github/workflows/release-documentation.yml b/.github/workflows/release-documentation.yml
index c19148017cfec..b32de1d056492 100644
--- a/.github/workflows/release-documentation.yml
+++ b/.github/workflows/release-documentation.yml
@@ -67,6 +67,8 @@ jobs:
outputs:
man-page-digest: ${{ steps.man-page-digest.outputs.man-page-digest }}
man-page-artifact-id: ${{ steps.man-page-artifact-upload.outputs.artifact-id }}
+ doxygen-digest: ${{ steps.man-page-digest.outputs.doxygen-digest }}
+ doxygen-artifact-id: ${{ steps.doxygen-artifact-upload.outputs.artifact-id }}
steps:
- name: Checkout LLVM
uses: actions/checkout at df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
@@ -95,6 +97,12 @@ jobs:
texlive-font-utils
pip3 install --require-hashes --user -r ./llvm/docs/requirements.txt
+ # Install Doxygen
+ curl -L https://github.com/doxygen/doxygen/releases/download/Release_1_17_0/doxygen-1.17.0.linux.bin.tar.gz -o doxygen.tar.gz
+ echo "75419ef4f446fc1c24ef12514b574e66e898ee6f527c6ae2ad84f91a905823c2 doxygen.tar.gz" | shasum --check -
+ tar -xf doxygen.tar.gz
+ sudo install -m 755 doxygen-1.17.0/bin/doxygen /usr/local/bin/doxygen
+
- name: Build Documentation
id: build
env:
@@ -102,17 +110,20 @@ jobs:
INPUTS_RELEASE_VERSION: ${{ inputs.release-version }}
run: |
./llvm/utils/release/build-docs.sh \
- $(test -n "$INPUTS_RELEASE_VERSION" && echo -release "$INPUTS_RELEASE_VERSION" || echo -srcdir llvm) -no-doxygen
+ $(test -n "$INPUTS_RELEASE_VERSION" && echo -release "$INPUTS_RELEASE_VERSION" || echo -srcdir llvm)
echo "man-page-tarball-name=$(basename $(find . -iname 'llvm_man_pages-*.tar.xz'))" >> "$GITHUB_OUTPUT"
+ echo "doxygen-tarball-name=$(baename $(find . -iname '*doxygen*.tar.xz')) >> "$GITHUB_OUTPUT"
- - name: Generate sha256 digest for man page tarball
+ - name: Generate sha256 digest for tarballs
id: man-page-digest
shell: bash
env:
- TARBALL_NAME: ${{ steps.build.outputs.man-page-tarball-name }}
+ MAN_PAGE_TARBALL_NAME: ${{ steps.build.outputs.man-page-tarball-name }}
+ DOXYGEN_TARBALL_NAME: ${{ steps.build.outputs.man-page-tarball-name }}
run: |
- echo "man-page-digest=$(cat "$TARBALL_NAME" | sha256sum | cut -d ' ' -f 1)" >> "$GITHUB_OUTPUT"
+ echo "man-page-digest=$(cat "$MAN_PAGE_TARBALL_NAME" | sha256sum | cut -d ' ' -f 1)" >> "$GITHUB_OUTPUT"
+ echo "doxygen-digest=$(cat "$DOXYGEN_TARBALL_NAME" | sha256sum | cut -d ' ' -f 1)" >> "$GITHUB_OUTPUT"
- id: man-page-artifact-upload
uses: actions/upload-artifact at 043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
@@ -121,6 +132,13 @@ jobs:
path: |
${{ steps.build.outputs.man-page-tarball-name }}
+ - id: doxygen-artifact-upload
+ uses: actions/upload-artifact at 043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
+ with:
+ name: doxygen
+ path: |
+ ${{ steps.build.outputs.doxygen-tarball-name }}
+
- name: Create Release Notes Artifact
uses: actions/upload-artifact at 043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
@@ -174,8 +192,8 @@ jobs:
git push --force "https://$PUSH_TOKEN@github.com/llvmbot/www-releases.git" HEAD:refs/heads/$INPUTS_RELEASE_VERSION
gh pr create -f -B main -H llvmbot:$INPUTS_RELEASE_VERSION
- upload-man-pages:
- name: "Upload Man Pages"
+ upload-documentation:
+ name: "Upload Documentation"
runs-on: ubuntu-24.04
environment:
deployment: false
@@ -188,16 +206,23 @@ jobs:
contents: write # For man page uploads
id-token: write # For artifact attestations
attestations: write # For artifact attestations
-
+ matrix:
+ include:
+ - artifact-id: ${{ needs.release-documentation.outputs.man-page-artifact-id }}
+ attestation-name: release-man-page-attestation
+ digest: ${{ needs.release-documentation.outputs.man-page-digest }}
+ - artifact-id: ${{ needs.release-documentation.outputs.doxygen-artifact-id }}
+ attestation-name: release-doxygen-attestation
+ digest: ${{ needs.release-documentation.outputs.doxygen-digest }}
steps:
- name: Upload Man Page Artifacts
id: man-page-artifact-upload
uses: $/.github/workflows/upload-release-artifact
with:
release-version: ${{ inputs.release-version }}
- artifact-id: ${{ needs.release-documentation.outputs.man-page-artifact-id }}
- attestation-name: ${{ runner.os }}-${{ runner.arch }}-release-man-page-attestation
- digest: ${{ needs.release-documentation.outputs.man-page-digest }}
+ artifact-id: ${{ matrix.artifact-id }}
+ attestation-name: ${{ runner.os }}-${{ runner.arch }}-${{ matrix.attestation_name }}
+ digest: ${{ matrix.digest }}
upload: ${{ inputs.upload }}
LLVM_TOKEN_GENERATOR_CLIENT_ID: ${{ secrets.LLVM_TOKEN_GENERATOR_CLIENT_ID }}
LLVM_TOKEN_GENERATOR_PRIVATE_KEY: ${{ secrets.LLVM_TOKEN_GENERATOR_PRIVATE_KEY }}
>From 51b938c32b9338b9babf78eba48e45d7fe42f05f Mon Sep 17 00:00:00 2001
From: Tom Stellard <tstellar at redhat.com>
Date: Fri, 31 Jul 2026 17:00:41 -0700
Subject: [PATCH 29/43] ebug
---
.github/workflows/release-documentation.yml | 5 -----
1 file changed, 5 deletions(-)
diff --git a/.github/workflows/release-documentation.yml b/.github/workflows/release-documentation.yml
index b32de1d056492..ca4c7ab6312aa 100644
--- a/.github/workflows/release-documentation.yml
+++ b/.github/workflows/release-documentation.yml
@@ -195,13 +195,8 @@ jobs:
upload-documentation:
name: "Upload Documentation"
runs-on: ubuntu-24.04
- environment:
- deployment: false
- name: release
needs:
- release-documentation
- if: >-
- github.event_name != 'pull_request'
permissions:
contents: write # For man page uploads
id-token: write # For artifact attestations
>From 37ddf1de0f01dd88479b8cf6faec1fe690edf5ff Mon Sep 17 00:00:00 2001
From: Alexey Bataev <a.bataev at outlook.com>
Date: Fri, 31 Jul 2026 17:38:16 -0400
Subject: [PATCH 30/43] [SLP][NFC]Add an extra check for fmul to fmuladd
promotion, NFC
Reviewers:
Pull Request: https://github.com/llvm/llvm-project/pull/213361
---
.../X86/fmuladd-copyable-fmul.ll | 138 ++++++++++++++++++
1 file changed, 138 insertions(+)
diff --git a/llvm/test/Transforms/SLPVectorizer/X86/fmuladd-copyable-fmul.ll b/llvm/test/Transforms/SLPVectorizer/X86/fmuladd-copyable-fmul.ll
index 3614f8b1f1a91..28ca0b93a06f7 100644
--- a/llvm/test/Transforms/SLPVectorizer/X86/fmuladd-copyable-fmul.ll
+++ b/llvm/test/Transforms/SLPVectorizer/X86/fmuladd-copyable-fmul.ll
@@ -1,6 +1,7 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
; RUN: opt -passes=slp-vectorizer -slp-threshold=-99999 -S -mtriple=x86_64-unknown-linux-gnu < %s | FileCheck %s --check-prefixes=ENABLED
; RUN: opt -passes=slp-vectorizer -slp-threshold=-99999 -slp-copyable-elements=false -S -mtriple=x86_64-unknown-linux-gnu < %s | FileCheck %s --check-prefixes=DISABLED
+; RUN: opt -passes=slp-vectorizer -S -mtriple=x86_64-unknown-linux-gnu < %s | FileCheck %s --check-prefixes=COST
declare float @llvm.fmuladd.f32(float, float, float)
@@ -59,6 +60,27 @@ define <4 x float> @buildvec_fmul_absorb(float %p, float %q, float %r, float %s,
; DISABLED-NEXT: [[V31:%.*]] = shufflevector <4 x float> [[TMP19]], <4 x float> [[TMP20]], <4 x i32> <i32 0, i32 1, i32 4, i32 5>
; DISABLED-NEXT: ret <4 x float> [[V31]]
;
+; COST-LABEL: define <4 x float> @buildvec_fmul_absorb(
+; COST-SAME: float [[P:%.*]], float [[Q:%.*]], float [[R:%.*]], float [[S:%.*]], float [[T:%.*]], float [[U:%.*]], float [[N:%.*]], float [[M:%.*]], float [[E:%.*]], float [[F:%.*]], float [[G:%.*]], float [[H:%.*]], ptr [[SRCB:%.*]]) {
+; COST-NEXT: [[ENTRY:.*:]]
+; COST-NEXT: [[TMP0:%.*]] = insertelement <2 x float> poison, float [[P]], i64 0
+; COST-NEXT: [[TMP1:%.*]] = insertelement <2 x float> [[TMP0]], float [[R]], i64 1
+; COST-NEXT: [[TMP2:%.*]] = insertelement <2 x float> poison, float [[Q]], i64 0
+; COST-NEXT: [[TMP3:%.*]] = insertelement <2 x float> [[TMP2]], float [[S]], i64 1
+; COST-NEXT: [[TMP4:%.*]] = fmul <2 x float> [[TMP1]], [[TMP3]]
+; COST-NEXT: [[X:%.*]] = fmul float [[T]], [[U]]
+; COST-NEXT: [[Z:%.*]] = fmul float [[N]], [[M]]
+; COST-NEXT: [[C0:%.*]] = fadd float [[E]], [[F]]
+; COST-NEXT: [[C1:%.*]] = fsub float [[G]], [[H]]
+; COST-NEXT: [[TMP5:%.*]] = load <2 x float>, ptr [[SRCB]], align 4
+; COST-NEXT: [[TMP6:%.*]] = insertelement <2 x float> poison, float [[C0]], i64 0
+; COST-NEXT: [[TMP7:%.*]] = insertelement <2 x float> [[TMP6]], float [[C1]], i64 1
+; COST-NEXT: [[TMP8:%.*]] = call <2 x float> @llvm.fmuladd.v2f32(<2 x float> [[TMP4]], <2 x float> [[TMP5]], <2 x float> [[TMP7]])
+; COST-NEXT: [[TMP9:%.*]] = shufflevector <2 x float> [[TMP8]], <2 x float> poison, <4 x i32> <i32 0, i32 1, i32 poison, i32 poison>
+; COST-NEXT: [[V2:%.*]] = insertelement <4 x float> [[TMP9]], float [[X]], i32 2
+; COST-NEXT: [[V3:%.*]] = insertelement <4 x float> [[V2]], float [[Z]], i32 3
+; COST-NEXT: ret <4 x float> [[V3]]
+;
entry:
%a0 = fmul float %p, %q
%a1 = fmul float %r, %s
@@ -146,6 +168,33 @@ define void @storechain_1fmul(ptr %dst, ptr %srcB, float %p, float %q, float %r,
; DISABLED-NEXT: store float [[FMA2]], ptr [[D3]], align 4
; DISABLED-NEXT: ret void
;
+; COST-LABEL: define void @storechain_1fmul(
+; COST-SAME: ptr [[DST:%.*]], ptr [[SRCB:%.*]], float [[P:%.*]], float [[Q:%.*]], float [[R:%.*]], float [[S:%.*]], float [[T:%.*]], float [[U:%.*]], float [[N:%.*]], float [[M:%.*]], float [[E:%.*]], float [[F:%.*]], float [[G:%.*]], float [[H:%.*]], float [[I:%.*]], float [[J:%.*]], float [[K:%.*]], float [[L:%.*]]) {
+; COST-NEXT: [[ENTRY:.*:]]
+; COST-NEXT: [[TMP0:%.*]] = insertelement <2 x float> poison, float [[P]], i64 0
+; COST-NEXT: [[TMP1:%.*]] = insertelement <2 x float> [[TMP0]], float [[R]], i64 1
+; COST-NEXT: [[TMP2:%.*]] = insertelement <2 x float> poison, float [[Q]], i64 0
+; COST-NEXT: [[TMP3:%.*]] = insertelement <2 x float> [[TMP2]], float [[S]], i64 1
+; COST-NEXT: [[TMP4:%.*]] = fmul <2 x float> [[TMP1]], [[TMP3]]
+; COST-NEXT: [[A2:%.*]] = fmul float [[I]], [[J]]
+; COST-NEXT: [[X:%.*]] = fmul float [[T]], [[U]]
+; COST-NEXT: [[C0:%.*]] = fadd float [[E]], [[F]]
+; COST-NEXT: [[C1:%.*]] = fsub float [[G]], [[H]]
+; COST-NEXT: [[C2:%.*]] = fadd float [[K]], [[L]]
+; COST-NEXT: [[GEPB2:%.*]] = getelementptr float, ptr [[SRCB]], i32 2
+; COST-NEXT: [[B2:%.*]] = load float, ptr [[GEPB2]], align 4
+; COST-NEXT: [[FMA2:%.*]] = call float @llvm.fmuladd.f32(float [[A2]], float [[B2]], float [[C2]])
+; COST-NEXT: [[D1:%.*]] = getelementptr float, ptr [[DST]], i32 1
+; COST-NEXT: [[TMP5:%.*]] = load <2 x float>, ptr [[SRCB]], align 4
+; COST-NEXT: [[TMP6:%.*]] = insertelement <2 x float> poison, float [[C0]], i64 0
+; COST-NEXT: [[TMP7:%.*]] = insertelement <2 x float> [[TMP6]], float [[C1]], i64 1
+; COST-NEXT: [[TMP8:%.*]] = call <2 x float> @llvm.fmuladd.v2f32(<2 x float> [[TMP4]], <2 x float> [[TMP5]], <2 x float> [[TMP7]])
+; COST-NEXT: store float [[X]], ptr [[DST]], align 4
+; COST-NEXT: store <2 x float> [[TMP8]], ptr [[D1]], align 4
+; COST-NEXT: [[D3:%.*]] = getelementptr float, ptr [[DST]], i32 3
+; COST-NEXT: store float [[FMA2]], ptr [[D3]], align 4
+; COST-NEXT: ret void
+;
entry:
%a0 = fmul float %p, %q
%a1 = fmul float %r, %s
@@ -231,6 +280,28 @@ define <4 x float> @buildvec_fmul_absorb_rev(float %p, float %q, float %r, float
; DISABLED-NEXT: [[V31:%.*]] = shufflevector <4 x float> [[TMP19]], <4 x float> [[TMP20]], <4 x i32> <i32 0, i32 1, i32 4, i32 5>
; DISABLED-NEXT: ret <4 x float> [[V31]]
;
+; COST-LABEL: define <4 x float> @buildvec_fmul_absorb_rev(
+; COST-SAME: float [[P:%.*]], float [[Q:%.*]], float [[R:%.*]], float [[S:%.*]], float [[T:%.*]], float [[U:%.*]], float [[N:%.*]], float [[M:%.*]], float [[E:%.*]], float [[F:%.*]], float [[G:%.*]], float [[H:%.*]], ptr [[SRCB:%.*]]) {
+; COST-NEXT: [[ENTRY:.*:]]
+; COST-NEXT: [[TMP0:%.*]] = insertelement <2 x float> poison, float [[P]], i64 0
+; COST-NEXT: [[TMP1:%.*]] = insertelement <2 x float> [[TMP0]], float [[R]], i64 1
+; COST-NEXT: [[TMP2:%.*]] = insertelement <2 x float> poison, float [[Q]], i64 0
+; COST-NEXT: [[TMP3:%.*]] = insertelement <2 x float> [[TMP2]], float [[S]], i64 1
+; COST-NEXT: [[TMP4:%.*]] = fmul <2 x float> [[TMP1]], [[TMP3]]
+; COST-NEXT: [[X:%.*]] = fmul float [[T]], [[U]]
+; COST-NEXT: [[Z:%.*]] = fmul float [[N]], [[M]]
+; COST-NEXT: [[C0:%.*]] = fadd float [[E]], [[F]]
+; COST-NEXT: [[C1:%.*]] = fsub float [[G]], [[H]]
+; COST-NEXT: [[TMP5:%.*]] = load <2 x float>, ptr [[SRCB]], align 4
+; COST-NEXT: [[TMP6:%.*]] = insertelement <2 x float> poison, float [[C0]], i64 0
+; COST-NEXT: [[TMP7:%.*]] = insertelement <2 x float> [[TMP6]], float [[C1]], i64 1
+; COST-NEXT: [[TMP8:%.*]] = call <2 x float> @llvm.fmuladd.v2f32(<2 x float> [[TMP4]], <2 x float> [[TMP5]], <2 x float> [[TMP7]])
+; COST-NEXT: [[V0:%.*]] = insertelement <4 x float> poison, float [[X]], i32 0
+; COST-NEXT: [[V1:%.*]] = insertelement <4 x float> [[V0]], float [[Z]], i32 1
+; COST-NEXT: [[TMP9:%.*]] = shufflevector <2 x float> [[TMP8]], <2 x float> poison, <4 x i32> <i32 0, i32 1, i32 poison, i32 poison>
+; COST-NEXT: [[V31:%.*]] = shufflevector <4 x float> [[V1]], <4 x float> [[TMP9]], <4 x i32> <i32 0, i32 1, i32 4, i32 5>
+; COST-NEXT: ret <4 x float> [[V31]]
+;
entry:
%a0 = fmul float %p, %q
%a1 = fmul float %r, %s
@@ -317,6 +388,30 @@ define <4 x float> @buildvec_fmul_no_absorb_multiuse_rev(float %p, float %q, flo
; DISABLED-NEXT: [[V31:%.*]] = shufflevector <4 x float> [[TMP21]], <4 x float> [[TMP22]], <4 x i32> <i32 0, i32 1, i32 4, i32 5>
; DISABLED-NEXT: ret <4 x float> [[V31]]
;
+; COST-LABEL: define <4 x float> @buildvec_fmul_no_absorb_multiuse_rev(
+; COST-SAME: float [[P:%.*]], float [[Q:%.*]], float [[R:%.*]], float [[S:%.*]], float [[T:%.*]], float [[U:%.*]], float [[N:%.*]], float [[M:%.*]], float [[E:%.*]], float [[F:%.*]], float [[G:%.*]], float [[H:%.*]], ptr [[SRCB:%.*]], ptr [[DST2:%.*]]) {
+; COST-NEXT: [[ENTRY:.*:]]
+; COST-NEXT: [[TMP0:%.*]] = insertelement <2 x float> poison, float [[P]], i64 0
+; COST-NEXT: [[TMP1:%.*]] = insertelement <2 x float> [[TMP0]], float [[R]], i64 1
+; COST-NEXT: [[TMP2:%.*]] = insertelement <2 x float> poison, float [[Q]], i64 0
+; COST-NEXT: [[TMP3:%.*]] = insertelement <2 x float> [[TMP2]], float [[S]], i64 1
+; COST-NEXT: [[TMP4:%.*]] = fmul <2 x float> [[TMP1]], [[TMP3]]
+; COST-NEXT: [[X:%.*]] = fmul float [[T]], [[U]]
+; COST-NEXT: [[Z:%.*]] = fmul float [[N]], [[M]]
+; COST-NEXT: [[C0:%.*]] = fadd float [[E]], [[F]]
+; COST-NEXT: [[C1:%.*]] = fsub float [[G]], [[H]]
+; COST-NEXT: [[TMP5:%.*]] = load <2 x float>, ptr [[SRCB]], align 4
+; COST-NEXT: [[TMP6:%.*]] = insertelement <2 x float> poison, float [[C0]], i64 0
+; COST-NEXT: [[TMP7:%.*]] = insertelement <2 x float> [[TMP6]], float [[C1]], i64 1
+; COST-NEXT: [[TMP8:%.*]] = call <2 x float> @llvm.fmuladd.v2f32(<2 x float> [[TMP4]], <2 x float> [[TMP5]], <2 x float> [[TMP7]])
+; COST-NEXT: store float [[X]], ptr [[DST2]], align 4
+; COST-NEXT: store float [[Z]], ptr [[DST2]], align 4
+; COST-NEXT: [[V0:%.*]] = insertelement <4 x float> poison, float [[X]], i32 0
+; COST-NEXT: [[V1:%.*]] = insertelement <4 x float> [[V0]], float [[Z]], i32 1
+; COST-NEXT: [[TMP9:%.*]] = shufflevector <2 x float> [[TMP8]], <2 x float> poison, <4 x i32> <i32 0, i32 1, i32 poison, i32 poison>
+; COST-NEXT: [[V31:%.*]] = shufflevector <4 x float> [[V1]], <4 x float> [[TMP9]], <4 x i32> <i32 0, i32 1, i32 4, i32 5>
+; COST-NEXT: ret <4 x float> [[V31]]
+;
entry:
%a0 = fmul float %p, %q
%a1 = fmul float %r, %s
@@ -391,6 +486,26 @@ define <4 x float> @buildvec_fmul_absorb_const(float %p, float %q, float %r, flo
; DISABLED-NEXT: [[V31:%.*]] = shufflevector <4 x float> [[TMP17]], <4 x float> [[TMP18]], <4 x i32> <i32 0, i32 1, i32 4, i32 5>
; DISABLED-NEXT: ret <4 x float> [[V31]]
;
+; COST-LABEL: define <4 x float> @buildvec_fmul_absorb_const(
+; COST-SAME: float [[P:%.*]], float [[Q:%.*]], float [[R:%.*]], float [[S:%.*]], float [[T:%.*]], float [[U:%.*]], float [[E:%.*]], float [[F:%.*]], float [[G:%.*]], float [[H:%.*]], ptr [[SRCB:%.*]]) {
+; COST-NEXT: [[ENTRY:.*:]]
+; COST-NEXT: [[A0:%.*]] = fmul float [[P]], [[Q]]
+; COST-NEXT: [[A1:%.*]] = fmul float [[R]], [[S]]
+; COST-NEXT: [[C0:%.*]] = fadd float [[E]], [[F]]
+; COST-NEXT: [[C1:%.*]] = fsub float [[G]], [[H]]
+; COST-NEXT: [[TMP0:%.*]] = load <2 x float>, ptr [[SRCB]], align 4
+; COST-NEXT: [[TMP1:%.*]] = insertelement <4 x float> poison, float [[U]], i64 2
+; COST-NEXT: [[TMP2:%.*]] = insertelement <4 x float> [[TMP1]], float [[A0]], i64 0
+; COST-NEXT: [[TMP3:%.*]] = insertelement <4 x float> [[TMP2]], float [[A1]], i64 1
+; COST-NEXT: [[TMP4:%.*]] = shufflevector <4 x float> [[TMP3]], <4 x float> poison, <4 x i32> <i32 0, i32 1, i32 2, i32 2>
+; COST-NEXT: [[TMP5:%.*]] = shufflevector <2 x float> [[TMP0]], <2 x float> poison, <4 x i32> <i32 0, i32 1, i32 poison, i32 poison>
+; COST-NEXT: [[TMP6:%.*]] = shufflevector <4 x float> <float poison, float poison, float 1.000000e+00, float 1.000000e+00>, <4 x float> [[TMP5]], <4 x i32> <i32 4, i32 5, i32 2, i32 3>
+; COST-NEXT: [[TMP7:%.*]] = insertelement <4 x float> <float poison, float poison, float -0.000000e+00, float -0.000000e+00>, float [[C0]], i64 0
+; COST-NEXT: [[TMP8:%.*]] = insertelement <4 x float> [[TMP7]], float [[C1]], i64 1
+; COST-NEXT: [[TMP9:%.*]] = call <4 x float> @llvm.fmuladd.v4f32(<4 x float> [[TMP4]], <4 x float> [[TMP6]], <4 x float> [[TMP8]])
+; COST-NEXT: [[TMP10:%.*]] = fmul <4 x float> [[TMP9]], <float 1.000000e+00, float 1.000000e+00, float 2.000000e+00, float 4.000000e+00>
+; COST-NEXT: ret <4 x float> [[TMP10]]
+;
entry:
%a0 = fmul float %p, %q
%a1 = fmul float %r, %s
@@ -473,6 +588,29 @@ define <4 x float> @buildvec_fmul_no_absorb_multiuse(float %p, float %q, float %
; DISABLED-NEXT: [[V31:%.*]] = shufflevector <4 x float> [[TMP21]], <4 x float> [[TMP22]], <4 x i32> <i32 0, i32 1, i32 4, i32 5>
; DISABLED-NEXT: ret <4 x float> [[V31]]
;
+; COST-LABEL: define <4 x float> @buildvec_fmul_no_absorb_multiuse(
+; COST-SAME: float [[P:%.*]], float [[Q:%.*]], float [[R:%.*]], float [[S:%.*]], float [[T:%.*]], float [[U:%.*]], float [[N:%.*]], float [[M:%.*]], float [[E:%.*]], float [[F:%.*]], float [[G:%.*]], float [[H:%.*]], ptr [[SRCB:%.*]], ptr [[DST2:%.*]]) {
+; COST-NEXT: [[ENTRY:.*:]]
+; COST-NEXT: [[TMP0:%.*]] = insertelement <2 x float> poison, float [[P]], i64 0
+; COST-NEXT: [[TMP1:%.*]] = insertelement <2 x float> [[TMP0]], float [[R]], i64 1
+; COST-NEXT: [[TMP2:%.*]] = insertelement <2 x float> poison, float [[Q]], i64 0
+; COST-NEXT: [[TMP3:%.*]] = insertelement <2 x float> [[TMP2]], float [[S]], i64 1
+; COST-NEXT: [[TMP4:%.*]] = fmul <2 x float> [[TMP1]], [[TMP3]]
+; COST-NEXT: [[X:%.*]] = fmul float [[T]], [[U]]
+; COST-NEXT: [[Z:%.*]] = fmul float [[N]], [[M]]
+; COST-NEXT: [[C0:%.*]] = fadd float [[E]], [[F]]
+; COST-NEXT: [[C1:%.*]] = fsub float [[G]], [[H]]
+; COST-NEXT: [[TMP5:%.*]] = load <2 x float>, ptr [[SRCB]], align 4
+; COST-NEXT: [[TMP6:%.*]] = insertelement <2 x float> poison, float [[C0]], i64 0
+; COST-NEXT: [[TMP7:%.*]] = insertelement <2 x float> [[TMP6]], float [[C1]], i64 1
+; COST-NEXT: [[TMP8:%.*]] = call <2 x float> @llvm.fmuladd.v2f32(<2 x float> [[TMP4]], <2 x float> [[TMP5]], <2 x float> [[TMP7]])
+; COST-NEXT: store float [[X]], ptr [[DST2]], align 4
+; COST-NEXT: store float [[Z]], ptr [[DST2]], align 4
+; COST-NEXT: [[TMP9:%.*]] = shufflevector <2 x float> [[TMP8]], <2 x float> poison, <4 x i32> <i32 0, i32 1, i32 poison, i32 poison>
+; COST-NEXT: [[V2:%.*]] = insertelement <4 x float> [[TMP9]], float [[X]], i32 2
+; COST-NEXT: [[V3:%.*]] = insertelement <4 x float> [[V2]], float [[Z]], i32 3
+; COST-NEXT: ret <4 x float> [[V3]]
+;
entry:
%a0 = fmul float %p, %q
%a1 = fmul float %r, %s
>From a53548854785e06e291e5517d0a72212f58a721d Mon Sep 17 00:00:00 2001
From: Zhen Wang <zhenw at nvidia.com>
Date: Fri, 31 Jul 2026 14:38:24 -0700
Subject: [PATCH 31/43] [flang-rt][cuda] Skip scope-exit cleanup when the
context has a sticky error (#213184)
A sticky CUDA error (e.g. an illegal memory access in a kernel) leaves
the primary context active but unusable, so CUFDeviceIsActive() reports
it as fine and the compiler-generated scope-exit frees abort a program
that ran to completion: 'cudaFree(p)' failed with
'cudaErrorIllegalAddress'.
Detect this by freeing a null pointer, a no-op that still reports the
sticky error. It runs only once the primary context is known active, so
it cannot lazily create one.
---
flang-rt/lib/cuda/allocator.cpp | 7 +++++++
flang/test/Lower/CUDA/cuda-return01.cuf | 6 ++++++
2 files changed, 13 insertions(+)
diff --git a/flang-rt/lib/cuda/allocator.cpp b/flang-rt/lib/cuda/allocator.cpp
index 4161caa7cb022..d8287d6f696e3 100644
--- a/flang-rt/lib/cuda/allocator.cpp
+++ b/flang-rt/lib/cuda/allocator.cpp
@@ -59,6 +59,13 @@ static bool deviceContextTornDown() {
int active{0};
if (getState(device, &flags, &active) == CUDA_SUCCESS) {
tornDown = active == 0;
+ // A sticky error (e.g. an illegal kernel memory access) leaves the
+ // primary context active but unusable: later calls all fail, so
+ // scope-exit frees would abort an otherwise successful program. A
+ // null free is a no-op that surfaces this without creating a context.
+ if (!tornDown && cudaFree(nullptr) != cudaSuccess) {
+ tornDown = true;
+ }
}
}
} else {
diff --git a/flang/test/Lower/CUDA/cuda-return01.cuf b/flang/test/Lower/CUDA/cuda-return01.cuf
index 6e5d02c3b3962..9ea5ce1538081 100644
--- a/flang/test/Lower/CUDA/cuda-return01.cuf
+++ b/flang/test/Lower/CUDA/cuda-return01.cuf
@@ -31,13 +31,19 @@ end
program main
integer, allocatable, device :: a(:)
+ integer, device, pointer :: p(:)
return
end
+! The descriptor of a device pointer lives in managed memory and is freed at
+! scope exit, under the same device-active guard as the other cleanup.
+
! CHECK-LABEL: func.func @_QQmain() attributes {fir.bindc_name = "MAIN"}
! CHECK: cuf.alloc !fir.box<!fir.heap<!fir.array<?xi32>>> {bindc_name = "a", data_attr = #cuf.cuda<device>, uniq_name = "_QFEa"} -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>
+! CHECK: %[[PTR:.*]]:2 = hlfir.declare %{{.*}} {data_attr = #cuf.cuda<device>, fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFEp"}
! CHECK: %[[ACTIVE:.*]] = fir.call @_FortranACUFDeviceIsActive() {{.*}} : () -> i1
! CHECK-NEXT: fir.if %[[ACTIVE]] {
+! CHECK-NEXT: cuf.free %[[PTR]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>{{.*}}
! CHECK: cuf.deallocate
! CHECK: cuf.free{{.*}}
! CHECK-NEXT: }
>From 21ca681775641d012ddad0d7359a3393afc24866 Mon Sep 17 00:00:00 2001
From: Sam Elliott <aelliott at qti.qualcomm.com>
Date: Fri, 31 Jul 2026 15:03:31 -0700
Subject: [PATCH 32/43] [IPO] Remove IR Outliner (#211971)
The IR Outliner has major bugs and no active maintainer, and is disabled
by default. The new LLVM Policy states the pass should be removed.
This commit removes:
- The IROutliner pass
- The IRSimilarity analysis
- The `llvm-sim` executable, used for understanding the latter
- All tests of the above
Related discussion:
https://discourse.llvm.org/t/ir-outliner-status-interest/89672
---
llvm/docs/ReleaseNotes.md | 3 +
.../llvm/Analysis/IRSimilarityIdentifier.h | 1192 -------
llvm/include/llvm/InitializePasses.h | 1 -
llvm/include/llvm/Transforms/IPO/IROutliner.h | 469 ---
llvm/lib/Analysis/Analysis.cpp | 1 -
llvm/lib/Analysis/CMakeLists.txt | 1 -
llvm/lib/Analysis/IRSimilarityIdentifier.cpp | 1519 ---------
llvm/lib/Passes/PassBuilder.cpp | 1 -
llvm/lib/Passes/PassBuilderPipelines.cpp | 12 -
llvm/lib/Passes/PassRegistry.def | 3 -
llvm/lib/Transforms/IPO/CMakeLists.txt | 1 -
llvm/lib/Transforms/IPO/IROutliner.cpp | 2975 -----------------
.../Analysis/IRSimilarityIdentifier/basic.ll | 140 -
.../debug-inst-starts-block.ll | 77 -
.../IRSimilarityIdentifier/different.ll | 48 -
.../IRSimilarityIdentifier/nothing.ll | 14 -
llvm/test/CMakeLists.txt | 1 -
llvm/test/DebugInfo/AArch64/ir-outliner.ll | 162 -
llvm/test/Other/new-pm-defaults.ll | 6 -
.../IROutliner/alloca-addrspace-1.ll | 46 -
.../Transforms/IROutliner/alloca-addrspace.ll | 46 -
.../IROutliner/different-intrinsics.ll | 92 -
.../IROutliner/different-order-phi-merges.ll | 113 -
.../IROutliner/duplicate-merging-phis.ll | 113 -
.../exit-block-phi-node-value-attribution.ll | 96 -
...-nodes-incoming-value-constant-argument.ll | 110 -
llvm/test/Transforms/IROutliner/extraction.ll | 127 -
.../IROutliner/gvn-output-set-overload.ll | 119 -
.../Transforms/IROutliner/gvn-phi-debug.ll | 175 -
.../Transforms/IROutliner/illegal-allocas.ll | 36 -
.../Transforms/IROutliner/illegal-assumes.ll | 143 -
.../Transforms/IROutliner/illegal-branches.ll | 51 -
.../Transforms/IROutliner/illegal-callbr.ll | 64 -
.../Transforms/IROutliner/illegal-catchpad.ll | 70 -
.../Transforms/IROutliner/illegal-cleanup.ll | 62 -
.../Transforms/IROutliner/illegal-frozen.ll | 49 -
.../IROutliner/illegal-indirect-calls.ll | 58 -
.../Transforms/IROutliner/illegal-invoke.ll | 64 -
.../IROutliner/illegal-landingpad.ll | 64 -
.../Transforms/IROutliner/illegal-memcpy.ll | 65 -
.../Transforms/IROutliner/illegal-memmove.ll | 65 -
.../Transforms/IROutliner/illegal-memset.ll | 41 -
.../Transforms/IROutliner/illegal-nomerge.ll | 104 -
.../IROutliner/illegal-phi-nodes.ll | 49 -
.../IROutliner/illegal-returns-twice.ll | 66 -
.../IROutliner/illegal-typeid-for.ll | 127 -
.../Transforms/IROutliner/illegal-vaarg.ll | 79 -
.../IROutliner/included-phi-nodes-begin.ll | 93 -
.../IROutliner/included-phi-nodes-end.ll | 94 -
.../test/Transforms/IROutliner/legal-debug.ll | 139 -
.../IROutliner/legal-indirect-calls.ll | 71 -
...matched-phi-exits-not-in-first-outlined.ll | 84 -
.../IROutliner/mismatched-phi-exits.ll | 84 -
.../mismatched-phi-outputs-ordering.ll | 145 -
.../must-capture-all-phi-nodes-begin.ll | 106 -
.../must-capture-all-phi-nodes-end.ll | 88 -
.../IROutliner/no-external-block-entries.ll | 75 -
.../IROutliner/no-outlining-optnone.ll | 61 -
.../IROutliner/nooutline-attribute.ll | 30 -
.../one-external-incoming-block-phi-node.ll | 71 -
.../test/Transforms/IROutliner/opt-remarks.ll | 405 ---
.../Transforms/IROutliner/outline-memcpy.ll | 60 -
.../Transforms/IROutliner/outline-memmove.ll | 60 -
.../Transforms/IROutliner/outline-memset.ll | 52 -
.../IROutliner/outline-vaarg-intrinsic.ll | 95 -
.../IROutliner/outlining-across-branch.ll | 77 -
.../IROutliner/outlining-address-taken.ll | 91 -
.../IROutliner/outlining-basic-branches.ll | 50 -
.../IROutliner/outlining-bitcasts.ll | 127 -
.../outlining-branches-phi-nodes.ll | 171 -
.../IROutliner/outlining-call-and-indirect.ll | 70 -
.../outlining-calls-names-must-match.ll | 93 -
.../Transforms/IROutliner/outlining-calls.ll | 96 -
.../IROutliner/outlining-commutative-fp.ll | 107 -
...ing-commutative-operands-opposite-order.ll | 40 -
.../IROutliner/outlining-commutative.ll | 254 --
...ining-compatible-and-attribute-transfer.ll | 125 -
...ing-compatible-and-never-transfer-riscv.ll | 298 --
...lining-compatible-or-attribute-transfer.ll | 67 -
.../outlining-constants-vs-registers.ll | 82 -
.../IROutliner/outlining-cost-model.ll | 187 --
.../IROutliner/outlining-debug-statements.ll | 65 -
.../outlining-different-constants.ll | 58 -
.../IROutliner/outlining-different-globals.ll | 42 -
.../outlining-different-output-blocks.ll | 106 -
.../outlining-different-structure.ll | 62 -
.../IROutliner/outlining-exits-to-phi-node.ll | 92 -
.../IROutliner/outlining-first-instruction.ll | 67 -
.../Transforms/IROutliner/outlining-gep.ll | 68 -
.../outlining-isomorphic-predicates.ll | 170 -
.../outlining-larger-size-commutative.ll | 89 -
.../outlining-multiple-exits-diff-outputs.ll | 221 --
...outlining-multiple-exits-one-output-set.ll | 192 --
.../IROutliner/outlining-multiple-exits.ll | 200 --
.../IROutliner/outlining-musttail.ll | 34 -
.../outlining-no-return-functions.ll | 54 -
.../Transforms/IROutliner/outlining-odr.ll | 70 -
.../IROutliner/outlining-remapped-outputs.ll | 70 -
.../IROutliner/outlining-same-constants.ll | 58 -
.../IROutliner/outlining-same-globals.ll | 41 -
.../outlining-same-output-blocks.ll | 94 -
.../IROutliner/outlining-special-state.ll | 163 -
.../IROutliner/outlining-strip-loop-info.ll | 78 -
.../IROutliner/outlining-swift-error.ll | 44 -
.../IROutliner/outlining-swifttailcc.ll | 33 -
.../Transforms/IROutliner/outlining-tailcc.ll | 33 -
.../IROutliner/phi-node-exit-path-order.ll | 120 -
.../IROutliner/phi-nodes-non-constant.ll | 74 -
.../IROutliner/phi-nodes-output-overload.ll | 110 -
.../phi-nodes-parent-block-referential.ll | 98 -
.../Transforms/IROutliner/phi-nodes-simple.ll | 56 -
.../IROutliner/region-end-of-module.ll | 112 -
.../IROutliner/region-inputs-in-phi-nodes.ll | 110 -
llvm/test/lit.cfg.py | 2 -
llvm/test/tools/llvm-sim/Inputs/sim1.ll | 27 -
llvm/test/tools/llvm-sim/fail-cases.test | 8 -
llvm/test/tools/llvm-sim/single-sim-file.test | 57 -
llvm/test/tools/llvm-sim/single-sim.test | 56 -
llvm/tools/llvm-sim/CMakeLists.txt | 9 -
llvm/tools/llvm-sim/llvm-sim.cpp | 148 -
llvm/unittests/Analysis/CMakeLists.txt | 1 -
.../Analysis/IRSimilarityIdentifierTest.cpp | 2850 ----------------
.../gn/secondary/llvm/lib/Analysis/BUILD.gn | 1 -
.../llvm/lib/Transforms/IPO/BUILD.gn | 1 -
llvm/utils/gn/secondary/llvm/test/BUILD.gn | 1 -
.../gn/secondary/llvm/tools/llvm-sim/BUILD.gn | 8 -
.../llvm/unittests/Analysis/BUILD.gn | 1 -
llvm/utils/profcheck-xfail.txt | 1 -
.../llvm-project-overlay/llvm/BUILD.bazel | 17 -
129 files changed, 3 insertions(+), 18737 deletions(-)
delete mode 100644 llvm/include/llvm/Analysis/IRSimilarityIdentifier.h
delete mode 100644 llvm/include/llvm/Transforms/IPO/IROutliner.h
delete mode 100644 llvm/lib/Analysis/IRSimilarityIdentifier.cpp
delete mode 100644 llvm/lib/Transforms/IPO/IROutliner.cpp
delete mode 100644 llvm/test/Analysis/IRSimilarityIdentifier/basic.ll
delete mode 100644 llvm/test/Analysis/IRSimilarityIdentifier/debug-inst-starts-block.ll
delete mode 100644 llvm/test/Analysis/IRSimilarityIdentifier/different.ll
delete mode 100644 llvm/test/Analysis/IRSimilarityIdentifier/nothing.ll
delete mode 100644 llvm/test/DebugInfo/AArch64/ir-outliner.ll
delete mode 100644 llvm/test/Transforms/IROutliner/alloca-addrspace-1.ll
delete mode 100644 llvm/test/Transforms/IROutliner/alloca-addrspace.ll
delete mode 100644 llvm/test/Transforms/IROutliner/different-intrinsics.ll
delete mode 100644 llvm/test/Transforms/IROutliner/different-order-phi-merges.ll
delete mode 100644 llvm/test/Transforms/IROutliner/duplicate-merging-phis.ll
delete mode 100644 llvm/test/Transforms/IROutliner/exit-block-phi-node-value-attribution.ll
delete mode 100644 llvm/test/Transforms/IROutliner/exit-phi-nodes-incoming-value-constant-argument.ll
delete mode 100644 llvm/test/Transforms/IROutliner/extraction.ll
delete mode 100644 llvm/test/Transforms/IROutliner/gvn-output-set-overload.ll
delete mode 100644 llvm/test/Transforms/IROutliner/gvn-phi-debug.ll
delete mode 100644 llvm/test/Transforms/IROutliner/illegal-allocas.ll
delete mode 100644 llvm/test/Transforms/IROutliner/illegal-assumes.ll
delete mode 100644 llvm/test/Transforms/IROutliner/illegal-branches.ll
delete mode 100644 llvm/test/Transforms/IROutliner/illegal-callbr.ll
delete mode 100644 llvm/test/Transforms/IROutliner/illegal-catchpad.ll
delete mode 100644 llvm/test/Transforms/IROutliner/illegal-cleanup.ll
delete mode 100644 llvm/test/Transforms/IROutliner/illegal-frozen.ll
delete mode 100644 llvm/test/Transforms/IROutliner/illegal-indirect-calls.ll
delete mode 100644 llvm/test/Transforms/IROutliner/illegal-invoke.ll
delete mode 100644 llvm/test/Transforms/IROutliner/illegal-landingpad.ll
delete mode 100644 llvm/test/Transforms/IROutliner/illegal-memcpy.ll
delete mode 100644 llvm/test/Transforms/IROutliner/illegal-memmove.ll
delete mode 100644 llvm/test/Transforms/IROutliner/illegal-memset.ll
delete mode 100644 llvm/test/Transforms/IROutliner/illegal-nomerge.ll
delete mode 100644 llvm/test/Transforms/IROutliner/illegal-phi-nodes.ll
delete mode 100644 llvm/test/Transforms/IROutliner/illegal-returns-twice.ll
delete mode 100644 llvm/test/Transforms/IROutliner/illegal-typeid-for.ll
delete mode 100644 llvm/test/Transforms/IROutliner/illegal-vaarg.ll
delete mode 100644 llvm/test/Transforms/IROutliner/included-phi-nodes-begin.ll
delete mode 100644 llvm/test/Transforms/IROutliner/included-phi-nodes-end.ll
delete mode 100644 llvm/test/Transforms/IROutliner/legal-debug.ll
delete mode 100644 llvm/test/Transforms/IROutliner/legal-indirect-calls.ll
delete mode 100644 llvm/test/Transforms/IROutliner/mismatched-phi-exits-not-in-first-outlined.ll
delete mode 100644 llvm/test/Transforms/IROutliner/mismatched-phi-exits.ll
delete mode 100644 llvm/test/Transforms/IROutliner/mismatched-phi-outputs-ordering.ll
delete mode 100644 llvm/test/Transforms/IROutliner/must-capture-all-phi-nodes-begin.ll
delete mode 100644 llvm/test/Transforms/IROutliner/must-capture-all-phi-nodes-end.ll
delete mode 100644 llvm/test/Transforms/IROutliner/no-external-block-entries.ll
delete mode 100644 llvm/test/Transforms/IROutliner/no-outlining-optnone.ll
delete mode 100644 llvm/test/Transforms/IROutliner/nooutline-attribute.ll
delete mode 100644 llvm/test/Transforms/IROutliner/one-external-incoming-block-phi-node.ll
delete mode 100644 llvm/test/Transforms/IROutliner/opt-remarks.ll
delete mode 100644 llvm/test/Transforms/IROutliner/outline-memcpy.ll
delete mode 100644 llvm/test/Transforms/IROutliner/outline-memmove.ll
delete mode 100644 llvm/test/Transforms/IROutliner/outline-memset.ll
delete mode 100644 llvm/test/Transforms/IROutliner/outline-vaarg-intrinsic.ll
delete mode 100644 llvm/test/Transforms/IROutliner/outlining-across-branch.ll
delete mode 100644 llvm/test/Transforms/IROutliner/outlining-address-taken.ll
delete mode 100644 llvm/test/Transforms/IROutliner/outlining-basic-branches.ll
delete mode 100644 llvm/test/Transforms/IROutliner/outlining-bitcasts.ll
delete mode 100644 llvm/test/Transforms/IROutliner/outlining-branches-phi-nodes.ll
delete mode 100644 llvm/test/Transforms/IROutliner/outlining-call-and-indirect.ll
delete mode 100644 llvm/test/Transforms/IROutliner/outlining-calls-names-must-match.ll
delete mode 100644 llvm/test/Transforms/IROutliner/outlining-calls.ll
delete mode 100644 llvm/test/Transforms/IROutliner/outlining-commutative-fp.ll
delete mode 100644 llvm/test/Transforms/IROutliner/outlining-commutative-operands-opposite-order.ll
delete mode 100644 llvm/test/Transforms/IROutliner/outlining-commutative.ll
delete mode 100644 llvm/test/Transforms/IROutliner/outlining-compatible-and-attribute-transfer.ll
delete mode 100644 llvm/test/Transforms/IROutliner/outlining-compatible-and-never-transfer-riscv.ll
delete mode 100644 llvm/test/Transforms/IROutliner/outlining-compatible-or-attribute-transfer.ll
delete mode 100644 llvm/test/Transforms/IROutliner/outlining-constants-vs-registers.ll
delete mode 100644 llvm/test/Transforms/IROutliner/outlining-cost-model.ll
delete mode 100644 llvm/test/Transforms/IROutliner/outlining-debug-statements.ll
delete mode 100644 llvm/test/Transforms/IROutliner/outlining-different-constants.ll
delete mode 100644 llvm/test/Transforms/IROutliner/outlining-different-globals.ll
delete mode 100644 llvm/test/Transforms/IROutliner/outlining-different-output-blocks.ll
delete mode 100644 llvm/test/Transforms/IROutliner/outlining-different-structure.ll
delete mode 100644 llvm/test/Transforms/IROutliner/outlining-exits-to-phi-node.ll
delete mode 100644 llvm/test/Transforms/IROutliner/outlining-first-instruction.ll
delete mode 100644 llvm/test/Transforms/IROutliner/outlining-gep.ll
delete mode 100644 llvm/test/Transforms/IROutliner/outlining-isomorphic-predicates.ll
delete mode 100644 llvm/test/Transforms/IROutliner/outlining-larger-size-commutative.ll
delete mode 100644 llvm/test/Transforms/IROutliner/outlining-multiple-exits-diff-outputs.ll
delete mode 100644 llvm/test/Transforms/IROutliner/outlining-multiple-exits-one-output-set.ll
delete mode 100644 llvm/test/Transforms/IROutliner/outlining-multiple-exits.ll
delete mode 100644 llvm/test/Transforms/IROutliner/outlining-musttail.ll
delete mode 100644 llvm/test/Transforms/IROutliner/outlining-no-return-functions.ll
delete mode 100644 llvm/test/Transforms/IROutliner/outlining-odr.ll
delete mode 100644 llvm/test/Transforms/IROutliner/outlining-remapped-outputs.ll
delete mode 100644 llvm/test/Transforms/IROutliner/outlining-same-constants.ll
delete mode 100644 llvm/test/Transforms/IROutliner/outlining-same-globals.ll
delete mode 100644 llvm/test/Transforms/IROutliner/outlining-same-output-blocks.ll
delete mode 100644 llvm/test/Transforms/IROutliner/outlining-special-state.ll
delete mode 100644 llvm/test/Transforms/IROutliner/outlining-strip-loop-info.ll
delete mode 100644 llvm/test/Transforms/IROutliner/outlining-swift-error.ll
delete mode 100644 llvm/test/Transforms/IROutliner/outlining-swifttailcc.ll
delete mode 100644 llvm/test/Transforms/IROutliner/outlining-tailcc.ll
delete mode 100644 llvm/test/Transforms/IROutliner/phi-node-exit-path-order.ll
delete mode 100644 llvm/test/Transforms/IROutliner/phi-nodes-non-constant.ll
delete mode 100644 llvm/test/Transforms/IROutliner/phi-nodes-output-overload.ll
delete mode 100644 llvm/test/Transforms/IROutliner/phi-nodes-parent-block-referential.ll
delete mode 100644 llvm/test/Transforms/IROutliner/phi-nodes-simple.ll
delete mode 100644 llvm/test/Transforms/IROutliner/region-end-of-module.ll
delete mode 100644 llvm/test/Transforms/IROutliner/region-inputs-in-phi-nodes.ll
delete mode 100644 llvm/test/tools/llvm-sim/Inputs/sim1.ll
delete mode 100644 llvm/test/tools/llvm-sim/fail-cases.test
delete mode 100644 llvm/test/tools/llvm-sim/single-sim-file.test
delete mode 100644 llvm/test/tools/llvm-sim/single-sim.test
delete mode 100644 llvm/tools/llvm-sim/CMakeLists.txt
delete mode 100644 llvm/tools/llvm-sim/llvm-sim.cpp
delete mode 100644 llvm/unittests/Analysis/IRSimilarityIdentifierTest.cpp
delete mode 100644 llvm/utils/gn/secondary/llvm/tools/llvm-sim/BUILD.gn
diff --git a/llvm/docs/ReleaseNotes.md b/llvm/docs/ReleaseNotes.md
index b26fb21e3ad29..e567f4b0a37f9 100644
--- a/llvm/docs/ReleaseNotes.md
+++ b/llvm/docs/ReleaseNotes.md
@@ -64,6 +64,9 @@ Makes programs 10x faster by doing Special New Thing.
### Changes to Interprocedural Optimizations
+- The IR Outliner has been removed, due to lack of a maintainer and the presence
+ of correctness issues.
+
### Changes to Vectorizers
### Changes to the AArch64 Backend
diff --git a/llvm/include/llvm/Analysis/IRSimilarityIdentifier.h b/llvm/include/llvm/Analysis/IRSimilarityIdentifier.h
deleted file mode 100644
index c9eb5a40f0477..0000000000000
--- a/llvm/include/llvm/Analysis/IRSimilarityIdentifier.h
+++ /dev/null
@@ -1,1192 +0,0 @@
-//===- IRSimilarityIdentifier.h - Find similarity in a module --------------==//
-//
-// Part of the LLVM Project, under the Apache 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
-// Interface file for the IRSimilarityIdentifier for identifying similarities in
-// IR including the IRInstructionMapper, which maps an Instruction to unsigned
-// integers.
-//
-// Two sequences of instructions are called "similar" if they perform the same
-// series of operations for all inputs.
-//
-// \code
-// %1 = add i32 %a, 10
-// %2 = add i32 %a, %1
-// %3 = icmp slt icmp %1, %2
-// \endcode
-//
-// and
-//
-// \code
-// %1 = add i32 11, %a
-// %2 = sub i32 %a, %1
-// %3 = icmp sgt icmp %2, %1
-// \endcode
-//
-// ultimately have the same result, even if the inputs, and structure are
-// slightly different.
-//
-// For instructions, we do not worry about operands that do not have fixed
-// semantic meaning to the program. We consider the opcode that the instruction
-// has, the types, parameters, and extra information such as the function name,
-// or comparison predicate. These are used to create a hash to map instructions
-// to integers to be used in similarity matching in sequences of instructions
-//
-// Terminology:
-// An IRSimilarityCandidate is a region of IRInstructionData (wrapped
-// Instructions), usually used to denote a region of similarity has been found.
-//
-// A SimilarityGroup is a set of IRSimilarityCandidates that are structurally
-// similar to one another.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_ANALYSIS_IRSIMILARITYIDENTIFIER_H
-#define LLVM_ANALYSIS_IRSIMILARITYIDENTIFIER_H
-
-#include "llvm/IR/InstVisitor.h"
-#include "llvm/IR/Instructions.h"
-#include "llvm/IR/PassManager.h"
-#include "llvm/Pass.h"
-#include "llvm/Support/Allocator.h"
-#include "llvm/Support/Compiler.h"
-#include <optional>
-
-namespace llvm {
-
-namespace IRSimilarity {
-
-struct IRInstructionDataList;
-
-/// This represents what is and is not supported when finding similarity in
-/// Instructions.
-///
-/// Legal Instructions are considered when looking at similarity between
-/// Instructions.
-///
-/// Illegal Instructions cannot be considered when looking for similarity
-/// between Instructions. They act as boundaries between similarity regions.
-///
-/// Invisible Instructions are skipped over during analysis.
-// TODO: Shared with MachineOutliner
-enum InstrType { Legal, Illegal, Invisible };
-
-/// This provides the utilities for hashing an Instruction to an unsigned
-/// integer. Two IRInstructionDatas produce the same hash value when their
-/// underlying Instructions perform the same operation (even if they don't have
-/// the same input operands.)
-/// As a more concrete example, consider the following:
-///
-/// \code
-/// %add1 = add i32 %a, %b
-/// %add2 = add i32 %c, %d
-/// %add3 = add i64 %e, %f
-/// \endcode
-///
-// Then the IRInstructionData wrappers for these Instructions may be hashed like
-/// so:
-///
-/// \code
-/// ; These two adds have the same types and operand types, so they hash to the
-/// ; same number.
-/// %add1 = add i32 %a, %b ; Hash: 1
-/// %add2 = add i32 %c, %d ; Hash: 1
-/// ; This add produces an i64. This differentiates it from %add1 and %add2. So,
-/// ; it hashes to a different number.
-/// %add3 = add i64 %e, %f; Hash: 2
-/// \endcode
-///
-///
-/// This hashing scheme will be used to represent the program as a very long
-/// string. This string can then be placed in a data structure which can be used
-/// for similarity queries.
-///
-/// TODO: Handle types of Instructions which can be equal even with different
-/// operands. (E.g. comparisons with swapped predicates.)
-/// TODO: Handle CallInsts, which are only checked for function type
-/// by \ref isSameOperationAs.
-/// TODO: Handle GetElementPtrInsts, as some of the operands have to be the
-/// exact same, and some do not.
-struct IRInstructionData
- : ilist_node<IRInstructionData, ilist_sentinel_tracking<true>> {
-
- /// The source Instruction that is being wrapped.
- Instruction *Inst = nullptr;
- /// The values of the operands in the Instruction.
- SmallVector<Value *, 4> OperVals;
- /// The legality of the wrapped instruction. This is informed by InstrType,
- /// and is used when checking when two instructions are considered similar.
- /// If either instruction is not legal, the instructions are automatically not
- /// considered similar.
- bool Legal = false;
-
- /// This is only relevant if we are wrapping a CmpInst where we needed to
- /// change the predicate of a compare instruction from a greater than form
- /// to a less than form. It is std::nullopt otherwise.
- std::optional<CmpInst::Predicate> RevisedPredicate;
-
- /// This is only relevant if we are wrapping a CallInst. If we are requiring
- /// that the function calls have matching names as well as types, and the
- /// call is not an indirect call, this will hold the name of the function. If
- /// it is an indirect string, it will be the empty string. However, if this
- /// requirement is not in place it will be the empty string regardless of the
- /// function call type. The value held here is used to create the hash of the
- /// instruction, and check to make sure two instructions are close to one
- /// another.
- std::optional<std::string> CalleeName;
-
- /// This structure holds the distances of how far "ahead of" or "behind" the
- /// target blocks of a branch, or the incoming blocks of a phi nodes are.
- /// If the value is negative, it means that the block was registered before
- /// the block of this instruction in terms of blocks in the function.
- /// Code Example:
- /// \code
- /// block_1:
- /// br i1 %0, label %block_2, label %block_3
- /// block_2:
- /// br i1 %1, label %block_1, label %block_2
- /// block_3:
- /// br i1 %2, label %block_2, label %block_1
- /// ; Replacing the labels with relative values, this becomes:
- /// block_1:
- /// br i1 %0, distance 1, distance 2
- /// block_2:
- /// br i1 %1, distance -1, distance 0
- /// block_3:
- /// br i1 %2, distance -1, distance -2
- /// \endcode
- /// Taking block_2 as our example, block_1 is "behind" block_2, and block_2 is
- /// "ahead" of block_2.
- SmallVector<int, 4> RelativeBlockLocations;
-
- /// Gather the information that is difficult to gather for an Instruction, or
- /// is changed. i.e. the operands of an Instruction and the Types of those
- /// operands. This extra information allows for similarity matching to make
- /// assertions that allow for more flexibility when checking for whether an
- /// Instruction performs the same operation.
- LLVM_ABI IRInstructionData(Instruction &I, bool Legality,
- IRInstructionDataList &IDL);
- LLVM_ABI IRInstructionData(IRInstructionDataList &IDL);
-
- /// Fills data stuctures for IRInstructionData when it is constructed from a
- // reference or a pointer.
- LLVM_ABI void initializeInstruction();
-
- /// Get the predicate that the compare instruction is using for hashing the
- /// instruction. the IRInstructionData must be wrapping a CmpInst.
- LLVM_ABI CmpInst::Predicate getPredicate() const;
-
- /// Get the callee name that the call instruction is using for hashing the
- /// instruction. The IRInstructionData must be wrapping a CallInst.
- LLVM_ABI StringRef getCalleeName() const;
-
- /// A function that swaps the predicates to their less than form if they are
- /// in a greater than form. Otherwise, the predicate is unchanged.
- ///
- /// \param CI - The comparison operation to find a consistent preidcate for.
- /// \return the consistent comparison predicate.
- LLVM_ABI static CmpInst::Predicate predicateForConsistency(CmpInst *CI);
-
- /// For an IRInstructionData containing a branch, finds the
- /// relative distances from the source basic block to the target by taking
- /// the difference of the number assigned to the current basic block and the
- /// target basic block of the branch.
- ///
- /// \param BasicBlockToInteger - The mapping of basic blocks to their location
- /// in the module.
- LLVM_ABI void
- setBranchSuccessors(DenseMap<BasicBlock *, unsigned> &BasicBlockToInteger);
-
- /// For an IRInstructionData containing a CallInst, set the function name
- /// appropriately. This will be an empty string if it is an indirect call,
- /// or we are not matching by name of the called function. It will be the
- /// name of the function if \p MatchByName is true and it is not an indirect
- /// call. We may decide not to match by name in order to expand the
- /// size of the regions we can match. If a function name has the same type
- /// signature, but the different name, the region of code is still almost the
- /// same. Since function names can be treated as constants, the name itself
- /// could be extrapolated away. However, matching by name provides a
- /// specificity and more "identical" code than not matching by name.
- ///
- /// \param MatchByName - A flag to mark whether we are using the called
- /// function name as a differentiating parameter.
- LLVM_ABI void setCalleeName(bool MatchByName = true);
-
- /// For an IRInstructionData containing a PHINode, finds the
- /// relative distances from the incoming basic block to the current block by
- /// taking the difference of the number assigned to the current basic block
- /// and the incoming basic block of the branch.
- ///
- /// \param BasicBlockToInteger - The mapping of basic blocks to their location
- /// in the module.
- LLVM_ABI void
- setPHIPredecessors(DenseMap<BasicBlock *, unsigned> &BasicBlockToInteger);
-
- /// Get the BasicBlock based operands for PHINodes and BranchInsts.
- ///
- /// \returns A list of relevant BasicBlocks.
- LLVM_ABI ArrayRef<Value *> getBlockOperVals();
-
- /// Hashes \p Value based on its opcode, types, and operand types.
- /// Two IRInstructionData instances produce the same hash when they perform
- /// the same operation.
- ///
- /// As a simple example, consider the following instructions.
- ///
- /// \code
- /// %add1 = add i32 %x1, %y1
- /// %add2 = add i32 %x2, %y2
- ///
- /// %sub = sub i32 %x1, %y1
- ///
- /// %add_i64 = add i64 %x2, %y2
- /// \endcode
- ///
- /// Because the first two adds operate the same types, and are performing the
- /// same action, they will be hashed to the same value.
- ///
- /// However, the subtraction instruction is not the same as an addition, and
- /// will be hashed to a different value.
- ///
- /// Finally, the last add has a different type compared to the first two add
- /// instructions, so it will also be hashed to a different value that any of
- /// the previous instructions.
- ///
- /// \param [in] ID - The IRInstructionData instance to be hashed.
- /// \returns A hash_value of the IRInstructionData.
- friend hash_code hash_value(const IRInstructionData &ID) {
- SmallVector<Type *, 4> OperTypes;
- for (Value *V : ID.OperVals)
- OperTypes.push_back(V->getType());
-
- if (isa<CmpInst>(ID.Inst))
- return llvm::hash_combine(llvm::hash_value(ID.Inst->getOpcode()),
- llvm::hash_value(ID.Inst->getType()),
- llvm::hash_value(ID.getPredicate()),
- llvm::hash_combine_range(OperTypes));
-
- if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(ID.Inst)) {
- // To hash intrinsics, we use the opcode, and types like the other
- // instructions, but also, the Intrinsic ID, and the Name of the
- // intrinsic.
- Intrinsic::ID IntrinsicID = II->getIntrinsicID();
- return llvm::hash_combine(llvm::hash_value(ID.Inst->getOpcode()),
- llvm::hash_value(ID.Inst->getType()),
- llvm::hash_value(IntrinsicID),
- llvm::hash_value(*ID.CalleeName),
- llvm::hash_combine_range(OperTypes));
- }
-
- if (isa<CallInst>(ID.Inst)) {
- std::string FunctionName = *ID.CalleeName;
- return llvm::hash_combine(llvm::hash_value(ID.Inst->getOpcode()),
- llvm::hash_value(ID.Inst->getType()),
- llvm::hash_value(ID.Inst->getType()),
- llvm::hash_value(FunctionName),
- llvm::hash_combine_range(OperTypes));
- }
-
- return llvm::hash_combine(llvm::hash_value(ID.Inst->getOpcode()),
- llvm::hash_value(ID.Inst->getType()),
- llvm::hash_combine_range(OperTypes));
- }
-
- IRInstructionDataList *IDL = nullptr;
-};
-
-struct IRInstructionDataList
- : simple_ilist<IRInstructionData, ilist_sentinel_tracking<true>> {};
-
-/// Compare one IRInstructionData class to another IRInstructionData class for
-/// whether they are performing a the same operation, and can mapped to the
-/// same value. For regular instructions if the hash value is the same, then
-/// they will also be close.
-///
-/// \param A - The first IRInstructionData class to compare
-/// \param B - The second IRInstructionData class to compare
-/// \returns true if \p A and \p B are similar enough to be mapped to the same
-/// value.
-LLVM_ABI bool isClose(const IRInstructionData &A, const IRInstructionData &B);
-
-struct IRInstructionDataTraits : DenseMapInfo<IRInstructionData *> {
- static unsigned getHashValue(const IRInstructionData *E) {
- using llvm::hash_value;
- assert(E && "IRInstructionData is a nullptr?");
- return hash_value(*E);
- }
-
- static bool isEqual(const IRInstructionData *LHS,
- const IRInstructionData *RHS) {
- assert(LHS && RHS && "nullptr is not expected as a key");
- return isClose(*LHS, *RHS);
- }
-};
-
-/// Helper struct for converting the Instructions in a Module into a vector of
-/// unsigned integers. This vector of unsigned integers can be thought of as a
-/// "numeric string". This numeric string can then be queried by, for example,
-/// data structures that find repeated substrings.
-///
-/// This hashing is done per BasicBlock in the module. To hash Instructions
-/// based off of their operations, each Instruction is wrapped in an
-/// IRInstructionData struct. The unsigned integer for an IRInstructionData
-/// depends on:
-/// - The hash provided by the IRInstructionData.
-/// - Which member of InstrType the IRInstructionData is classified as.
-// See InstrType for more details on the possible classifications, and how they
-// manifest in the numeric string.
-///
-/// The numeric string for an individual BasicBlock is terminated by an unique
-/// unsigned integer. This prevents data structures which rely on repetition
-/// from matching across BasicBlocks. (For example, the SuffixTree.)
-/// As a concrete example, if we have the following two BasicBlocks:
-/// \code
-/// bb0:
-/// %add1 = add i32 %a, %b
-/// %add2 = add i32 %c, %d
-/// %add3 = add i64 %e, %f
-/// bb1:
-/// %sub = sub i32 %c, %d
-/// \endcode
-/// We may hash the Instructions like this (via IRInstructionData):
-/// \code
-/// bb0:
-/// %add1 = add i32 %a, %b ; Hash: 1
-/// %add2 = add i32 %c, %d; Hash: 1
-/// %add3 = add i64 %e, %f; Hash: 2
-/// bb1:
-/// %sub = sub i32 %c, %d; Hash: 3
-/// %add4 = add i32 %c, %d ; Hash: 1
-/// \endcode
-/// And produce a "numeric string representation" like so:
-/// 1, 1, 2, unique_integer_1, 3, 1, unique_integer_2
-///
-/// TODO: This is very similar to the MachineOutliner, and should be
-/// consolidated into the same interface.
-struct IRInstructionMapper {
- /// The starting illegal instruction number to map to.
- ///
- /// Set to -3 for compatibility with DenseMapInfo<unsigned>.
- unsigned IllegalInstrNumber = static_cast<unsigned>(-3);
-
- /// The next available integer to assign to a legal Instruction to.
- unsigned LegalInstrNumber = 0;
-
- /// Correspondence from IRInstructionData to unsigned integers.
- DenseMap<IRInstructionData *, unsigned, IRInstructionDataTraits>
- InstructionIntegerMap;
-
- /// A mapping for a basic block in a module to its assigned number/location
- /// in the module.
- DenseMap<BasicBlock *, unsigned> BasicBlockToInteger;
-
- /// Set if we added an illegal number in the previous step.
- /// Since each illegal number is unique, we only need one of them between
- /// each range of legal numbers. This lets us make sure we don't add more
- /// than one illegal number per range.
- bool AddedIllegalLastTime = false;
-
- /// Marks whether we found a illegal instruction in the previous step.
- bool CanCombineWithPrevInstr = false;
-
- /// Marks whether we have found a set of instructions that is long enough
- /// to be considered for similarity.
- bool HaveLegalRange = false;
-
- /// Marks whether we should use exact function names, as well as types to
- /// find similarity between calls.
- bool EnableMatchCallsByName = false;
-
- /// This allocator pointer is in charge of holding on to the IRInstructionData
- /// so it is not deallocated until whatever external tool is using it is done
- /// with the information.
- SpecificBumpPtrAllocator<IRInstructionData> *InstDataAllocator = nullptr;
-
- /// This allocator pointer is in charge of creating the IRInstructionDataList
- /// so it is not deallocated until whatever external tool is using it is done
- /// with the information.
- SpecificBumpPtrAllocator<IRInstructionDataList> *IDLAllocator = nullptr;
-
- /// Get an allocated IRInstructionData struct using the InstDataAllocator.
- ///
- /// \param I - The Instruction to wrap with IRInstructionData.
- /// \param Legality - A boolean value that is true if the instruction is to
- /// be considered for similarity, and false if not.
- /// \param IDL - The InstructionDataList that the IRInstructionData is
- /// inserted into.
- /// \returns An allocated IRInstructionData struct.
- LLVM_ABI IRInstructionData *
- allocateIRInstructionData(Instruction &I, bool Legality,
- IRInstructionDataList &IDL);
-
- /// Get an empty allocated IRInstructionData struct using the
- /// InstDataAllocator.
- ///
- /// \param IDL - The InstructionDataList that the IRInstructionData is
- /// inserted into.
- /// \returns An allocated IRInstructionData struct.
- LLVM_ABI IRInstructionData *
- allocateIRInstructionData(IRInstructionDataList &IDL);
-
- /// Get an allocated IRInstructionDataList object using the IDLAllocator.
- ///
- /// \returns An allocated IRInstructionDataList object.
- LLVM_ABI IRInstructionDataList *allocateIRInstructionDataList();
-
- IRInstructionDataList *IDL = nullptr;
-
- /// Assigns values to all the basic blocks in function \p F starting from
- /// integer \p BBNumber.
- ///
- /// \param F - The function containing the basic blocks to assign numbers to.
- /// \param BBNumber - The number to start from.
- void initializeForBBs(Function &F, unsigned &BBNumber) {
- for (BasicBlock &BB : F)
- BasicBlockToInteger.insert(std::make_pair(&BB, BBNumber++));
- }
-
- /// Assigns values to all the basic blocks in Module \p M.
- /// \param M - The module containing the basic blocks to assign numbers to.
- void initializeForBBs(Module &M) {
- unsigned BBNumber = 0;
- for (Function &F : M)
- initializeForBBs(F, BBNumber);
- }
-
- /// Maps the Instructions in a BasicBlock \p BB to legal or illegal integers
- /// determined by \p InstrType. Two Instructions are mapped to the same value
- /// if they are close as defined by the InstructionData class above.
- ///
- /// \param [in] BB - The BasicBlock to be mapped to integers.
- /// \param [in,out] InstrList - Vector of IRInstructionData to append to.
- /// \param [in,out] IntegerMapping - Vector of unsigned integers to append to.
- LLVM_ABI void
- convertToUnsignedVec(BasicBlock &BB,
- std::vector<IRInstructionData *> &InstrList,
- std::vector<unsigned> &IntegerMapping);
-
- /// Maps an Instruction to a legal integer.
- ///
- /// \param [in] It - The Instruction to be mapped to an integer.
- /// \param [in,out] IntegerMappingForBB - Vector of unsigned integers to
- /// append to.
- /// \param [in,out] InstrListForBB - Vector of InstructionData to append to.
- /// \returns The integer \p It was mapped to.
- LLVM_ABI unsigned
- mapToLegalUnsigned(BasicBlock::iterator &It,
- std::vector<unsigned> &IntegerMappingForBB,
- std::vector<IRInstructionData *> &InstrListForBB);
-
- /// Maps an Instruction to an illegal integer.
- ///
- /// \param [in] It - The \p Instruction to be mapped to an integer.
- /// \param [in,out] IntegerMappingForBB - Vector of unsigned integers to
- /// append to.
- /// \param [in,out] InstrListForBB - Vector of IRInstructionData to append to.
- /// \param End - true if creating a dummy IRInstructionData at the end of a
- /// basic block.
- /// \returns The integer \p It was mapped to.
- LLVM_ABI unsigned mapToIllegalUnsigned(
- BasicBlock::iterator &It, std::vector<unsigned> &IntegerMappingForBB,
- std::vector<IRInstructionData *> &InstrListForBB, bool End = false);
-
- IRInstructionMapper(SpecificBumpPtrAllocator<IRInstructionData> *IDA,
- SpecificBumpPtrAllocator<IRInstructionDataList> *IDLA)
- : InstDataAllocator(IDA), IDLAllocator(IDLA) {
- IDL = new (IDLAllocator->Allocate())
- IRInstructionDataList();
- }
-
- /// Custom InstVisitor to classify different instructions for whether it can
- /// be analyzed for similarity.
- struct InstructionClassification
- : public InstVisitor<InstructionClassification, InstrType> {
- InstructionClassification() = default;
-
- // TODO: Determine a scheme to resolve when the label is similar enough.
- InstrType visitUncondBrInst(UncondBrInst &BI) {
- if (EnableBranches)
- return Legal;
- return Illegal;
- }
- InstrType visitCondBrInst(CondBrInst &BI) {
- if (EnableBranches)
- return Legal;
- return Illegal;
- }
- InstrType visitPHINode(PHINode &PN) {
- if (EnableBranches)
- return Legal;
- return Illegal;
- }
- // TODO: Handle allocas.
- InstrType visitAllocaInst(AllocaInst &AI) { return Illegal; }
- // We exclude variable argument instructions since variable arguments
- // requires extra checking of the argument list.
- InstrType visitVAArgInst(VAArgInst &VI) { return Illegal; }
- // We exclude all exception handling cases since they are so context
- // dependent.
- InstrType visitLandingPadInst(LandingPadInst &LPI) { return Illegal; }
- InstrType visitFuncletPadInst(FuncletPadInst &FPI) { return Illegal; }
- InstrType visitIntrinsicInst(IntrinsicInst &II) {
- // These are disabled due to complications in the CodeExtractor when
- // outlining these instructions. For instance, It is unclear what we
- // should do when moving only the start or end lifetime instruction into
- // an outlined function. Also, assume-like intrinsics could be removed
- // from the region, removing arguments, causing discrepencies in the
- // number of inputs between different regions.
- if (II.isAssumeLikeIntrinsic())
- return Illegal;
- return EnableIntrinsics ? Legal : Illegal;
- }
- // We only allow call instructions where the function has a name and
- // is not an indirect call.
- InstrType visitCallInst(CallInst &CI) {
- Function *F = CI.getCalledFunction();
- bool IsIndirectCall = CI.isIndirectCall();
- if (IsIndirectCall && !EnableIndirectCalls)
- return Illegal;
- if (!F && !IsIndirectCall)
- return Illegal;
- // Functions marked with the swifttailcc and tailcc calling conventions
- // require special handling when outlining musttail functions. The
- // calling convention must be passed down to the outlined function as
- // well. Further, there is special handling for musttail calls as well,
- // requiring a return call directly after. For now, the outliner does not
- // support this, so we do not handle matching this case either.
- if ((CI.getCallingConv() == CallingConv::SwiftTail ||
- CI.getCallingConv() == CallingConv::Tail) &&
- !EnableMustTailCalls)
- return Illegal;
- if (CI.isMustTailCall() && !EnableMustTailCalls)
- return Illegal;
- return Legal;
- }
- // TODO: We do not current handle similarity that changes the control flow.
- InstrType visitInvokeInst(InvokeInst &II) { return Illegal; }
- // TODO: We do not current handle similarity that changes the control flow.
- InstrType visitCallBrInst(CallBrInst &CBI) { return Illegal; }
- // TODO: Handle interblock similarity.
- InstrType visitTerminator(Instruction &I) { return Illegal; }
- InstrType visitInstruction(Instruction &I) { return Legal; }
-
- // The flag variable that lets the classifier know whether we should
- // allow branches to be checked for similarity.
- bool EnableBranches = false;
-
- // The flag variable that lets the classifier know whether we should
- // allow indirect calls to be considered legal instructions.
- bool EnableIndirectCalls = false;
-
- // Flag that lets the classifier know whether we should allow intrinsics to
- // be checked for similarity.
- bool EnableIntrinsics = false;
-
- // Flag that lets the classifier know whether we should allow tail calls to
- // be checked for similarity.
- bool EnableMustTailCalls = false;
- };
-
- /// Maps an Instruction to a member of InstrType.
- InstructionClassification InstClassifier;
-};
-
-/// This is a class that wraps a range of IRInstructionData from one point to
-/// another in the vector of IRInstructionData, which is a region of the
-/// program. It is also responsible for defining the structure within this
-/// region of instructions.
-///
-/// The structure of a region is defined through a value numbering system
-/// assigned to each unique value in a region at the creation of the
-/// IRSimilarityCandidate.
-///
-/// For example, for each Instruction we add a mapping for each new
-/// value seen in that Instruction.
-/// IR: Mapping Added:
-/// %add1 = add i32 %a, c1 %add1 -> 3, %a -> 1, c1 -> 2
-/// %add2 = add i32 %a, %1 %add2 -> 4
-/// %add3 = add i32 c2, c1 %add3 -> 6, c2 -> 5
-///
-/// We can compare IRSimilarityCandidates against one another.
-/// The \ref isSimilar function compares each IRInstructionData against one
-/// another and if we have the same sequences of IRInstructionData that would
-/// create the same hash, we have similar IRSimilarityCandidates.
-///
-/// We can also compare the structure of IRSimilarityCandidates. If we can
-/// create a mapping of registers in the region contained by one
-/// IRSimilarityCandidate to the region contained by different
-/// IRSimilarityCandidate, they can be considered structurally similar.
-///
-/// IRSimilarityCandidate1: IRSimilarityCandidate2:
-/// %add1 = add i32 %a, %b %add1 = add i32 %d, %e
-/// %add2 = add i32 %a, %c %add2 = add i32 %d, %f
-/// %add3 = add i32 c1, c2 %add3 = add i32 c3, c4
-///
-/// Can have the following mapping from candidate to candidate of:
-/// %a -> %d, %b -> %e, %c -> %f, c1 -> c3, c2 -> c4
-/// and can be considered similar.
-///
-/// IRSimilarityCandidate1: IRSimilarityCandidate2:
-/// %add1 = add i32 %a, %b %add1 = add i32 %d, c4
-/// %add2 = add i32 %a, %c %add2 = add i32 %d, %f
-/// %add3 = add i32 c1, c2 %add3 = add i32 c3, c4
-///
-/// We cannot create the same mapping since the use of c4 is not used in the
-/// same way as %b or c2.
-class IRSimilarityCandidate {
-private:
- /// The start index of this IRSimilarityCandidate in the instruction list.
- unsigned StartIdx = 0;
-
- /// The number of instructions in this IRSimilarityCandidate.
- unsigned Len = 0;
-
- /// The first instruction in this IRSimilarityCandidate.
- IRInstructionData *FirstInst = nullptr;
-
- /// The last instruction in this IRSimilarityCandidate.
- IRInstructionData *LastInst = nullptr;
-
- /// Global Value Numbering structures
- /// @{
- /// Stores the mapping of the value to the number assigned to it in the
- /// IRSimilarityCandidate.
- DenseMap<Value *, unsigned> ValueToNumber;
- /// Stores the mapping of the number to the value assigned this number.
- DenseMap<unsigned, Value *> NumberToValue;
- /// Stores the mapping of a value's number to canonical numbering in the
- /// candidate's respective similarity group.
- DenseMap<unsigned, unsigned> NumberToCanonNum;
- /// Stores the mapping of canonical number in the candidate's respective
- /// similarity group to a value number.
- DenseMap<unsigned, unsigned> CanonNumToNumber;
- /// @}
-
-public:
- /// \param StartIdx - The starting location of the region.
- /// \param Len - The length of the region.
- /// \param FirstInstIt - The starting IRInstructionData of the region.
- /// \param LastInstIt - The ending IRInstructionData of the region.
- LLVM_ABI IRSimilarityCandidate(unsigned StartIdx, unsigned Len,
- IRInstructionData *FirstInstIt,
- IRInstructionData *LastInstIt);
-
- /// \param A - The first IRInstructionCandidate to compare.
- /// \param B - The second IRInstructionCandidate to compare.
- /// \returns True when every IRInstructionData in \p A is similar to every
- /// IRInstructionData in \p B.
- LLVM_ABI static bool isSimilar(const IRSimilarityCandidate &A,
- const IRSimilarityCandidate &B);
-
- /// \param [in] A - The first IRInstructionCandidate to compare.
- /// \param [in] B - The second IRInstructionCandidate to compare.
- /// \returns True when every IRInstructionData in \p A is structurally similar
- /// to \p B.
- LLVM_ABI static bool compareStructure(const IRSimilarityCandidate &A,
- const IRSimilarityCandidate &B);
-
- /// \param [in] A - The first IRInstructionCandidate to compare.
- /// \param [in] B - The second IRInstructionCandidate to compare.
- /// \param [in,out] ValueNumberMappingA - A mapping of value numbers from
- /// candidate \p A to candidate \B.
- /// \param [in,out] ValueNumberMappingB - A mapping of value numbers from
- /// candidate \p B to candidate \A.
- /// \returns True when every IRInstructionData in \p A is structurally similar
- /// to \p B.
- LLVM_ABI static bool
- compareStructure(const IRSimilarityCandidate &A,
- const IRSimilarityCandidate &B,
- DenseMap<unsigned, DenseSet<unsigned>> &ValueNumberMappingA,
- DenseMap<unsigned, DenseSet<unsigned>> &ValueNumberMappingB);
-
- struct OperandMapping {
- /// The IRSimilarityCandidate that holds the instruction the OperVals were
- /// pulled from.
- const IRSimilarityCandidate &IRSC;
-
- /// The operand values to be analyzed.
- ArrayRef<Value *> &OperVals;
-
- /// The current mapping of global value numbers from one IRSimilarityCandidate
- /// to another IRSimilarityCandidate.
- DenseMap<unsigned, DenseSet<unsigned>> &ValueNumberMapping;
- };
-
- /// A helper struct to hold the candidate, for a branch instruction, the
- /// relative location of a label, and the label itself. This is mostly to
- /// group the values together before passing them as a bundle to a function.
- struct RelativeLocMapping {
- /// The IRSimilarityCandidate that holds the instruction the relative
- /// location was pulled from.
- const IRSimilarityCandidate &IRSC;
-
- /// The relative location to be analyzed.
- int RelativeLocation;
-
- /// The corresponding value.
- Value *OperVal;
- };
-
- /// Compare the operands in \p A and \p B and check that the current mapping
- /// of global value numbers from \p A to \p B and \p B to \A is consistent.
- ///
- /// \param A - The first IRInstructionCandidate, operand values, and current
- /// operand mappings to compare.
- /// \param B - The second IRInstructionCandidate, operand values, and current
- /// operand mappings to compare.
- /// \returns true if the IRSimilarityCandidates operands are compatible.
- LLVM_ABI static bool compareNonCommutativeOperandMapping(OperandMapping A,
- OperandMapping B);
-
- /// Compare the operands in \p A and \p B and check that the current mapping
- /// of global value numbers from \p A to \p B and \p B to \A is consistent
- /// given that the operands are commutative.
- ///
- /// \param A - The first IRInstructionCandidate, operand values, and current
- /// operand mappings to compare.
- /// \param B - The second IRInstructionCandidate, operand values, and current
- /// operand mappings to compare.
- /// \returns true if the IRSimilarityCandidates operands are compatible.
- LLVM_ABI static bool compareCommutativeOperandMapping(OperandMapping A,
- OperandMapping B);
-
- /// Compare the GVN of the assignment value in corresponding instructions in
- /// IRSimilarityCandidates \p A and \p B and check that there exists a mapping
- /// between the values and replaces the mapping with a one-to-one value if
- /// needed.
- ///
- /// \param InstValA - The assignment GVN from the first IRSimilarityCandidate.
- /// \param InstValB - The assignment GVN from the second
- /// IRSimilarityCandidate.
- /// \param [in,out] ValueNumberMappingA - A mapping of value numbers from
- /// candidate \p A to candidate \B.
- /// \param [in,out] ValueNumberMappingB - A mapping of value numbers from
- /// candidate \p B to candidate \A.
- /// \returns true if the IRSimilarityCandidates assignments are compatible.
- LLVM_ABI static bool compareAssignmentMapping(
- const unsigned InstValA, const unsigned &InstValB,
- DenseMap<unsigned, DenseSet<unsigned>> &ValueNumberMappingA,
- DenseMap<unsigned, DenseSet<unsigned>> &ValueNumberMappingB);
-
- /// Compare the relative locations in \p A and \p B and check that the
- /// distances match if both locations are contained in the region, and that
- /// the branches both point outside the region if they do not.
- /// Example Region:
- /// \code
- /// entry:
- /// br i1 %0, label %block_1, label %block_3
- /// block_0:
- /// br i1 %0, label %block_1, label %block_2
- /// block_1:
- /// br i1 %0, label %block_2, label %block_3
- /// block_2:
- /// br i1 %1, label %block_1, label %block_4
- /// block_3:
- /// br i1 %2, label %block_2, label %block_5
- /// \endcode
- /// If we compare the branches in block_0 and block_1 the relative values are
- /// 1 and 2 for both, so we consider this a match.
- ///
- /// If we compare the branches in entry and block_0 the relative values are
- /// 2 and 3, and 1 and 2 respectively. Since these are not the same we do not
- /// consider them a match.
- ///
- /// If we compare the branches in block_1 and block_2 the relative values are
- /// 1 and 2, and -1 and None respectively. As a result we do not consider
- /// these to be the same
- ///
- /// If we compare the branches in block_2 and block_3 the relative values are
- /// -1 and None for both. We do consider these to be a match.
- ///
- /// \param A - The first IRInstructionCandidate, relative location value,
- /// and incoming block.
- /// \param B - The second IRInstructionCandidate, relative location value,
- /// and incoming block.
- /// \returns true if the relative locations match.
- LLVM_ABI static bool checkRelativeLocations(RelativeLocMapping A,
- RelativeLocMapping B);
-
- /// Create a mapping from the value numbering to a different separate set of
- /// numbers. This will serve as a guide for relating one candidate to another.
- /// The canonical number gives use the ability identify which global value
- /// number in one candidate relates to the global value number in the other.
- ///
- /// \param [in, out] CurrCand - The IRSimilarityCandidate to create a
- /// canonical numbering for.
- LLVM_ABI static void
- createCanonicalMappingFor(IRSimilarityCandidate &CurrCand);
-
- /// Create a mapping for the value numbering of the calling
- /// IRSimilarityCandidate, to a different separate set of numbers, based on
- /// the canonical ordering in \p SourceCand. These are defined based on the
- /// found mappings in \p ToSourceMapping and \p FromSourceMapping. Both of
- /// these relationships should have the same information, just in opposite
- /// directions.
- ///
- /// \param [in, out] SourceCand - The IRSimilarityCandidate to create a
- /// canonical numbering from.
- /// \param ToSourceMapping - The mapping of value numbers from this candidate
- /// to \p SourceCand.
- /// \param FromSourceMapping - The mapping of value numbers from \p SoureCand
- /// to this candidate.
- LLVM_ABI void createCanonicalRelationFrom(
- IRSimilarityCandidate &SourceCand,
- DenseMap<unsigned, DenseSet<unsigned>> &ToSourceMapping,
- DenseMap<unsigned, DenseSet<unsigned>> &FromSourceMapping);
-
- /// Create a mapping for the value numbering of the calling
- /// IRSimilarityCandidate, to a different separate set of numbers, based on
- /// the canonical ordering in \p SourceCand. These are defined based on the
- /// found mappings in \p ToSourceMapping and \p FromSourceMapping. Both of
- /// these relationships should have the same information, just in opposite
- /// directions. Uses the \p OneToOne mapping from target candidate to \p
- /// SourceCand GVNs to determine the mapping first for values with multiple
- /// mappings. This mapping is created by the ordering of operands in the
- /// instruction they are first seen in the candidates.
- ///
- /// \param [in, out] SourceCand - The IRSimilarityCandidate to create a
- /// canonical numbering from.
- /// \param [in,out] OneToOne - A mapping of value numbers from candidate
- /// \p A to candidate \B using the structure of the original instructions.
- /// \param ToSourceMapping - The mapping of value numbers from this candidate
- /// to \p SourceCand.
- /// \param FromSourceMapping - The mapping of value numbers from \p SoureCand
- /// to this candidate.
- LLVM_ABI void createCanonicalRelationFrom(
- IRSimilarityCandidate &SourceCand, DenseMap<unsigned, unsigned> &OneToOne,
- DenseMap<unsigned, DenseSet<unsigned>> &ToSourceMapping,
- DenseMap<unsigned, DenseSet<unsigned>> &FromSourceMapping);
-
- /// Create a mapping for the value numbering of the calling
- /// IRSimilarityCandidate, to a different separate set of numbers, based on
- /// the canonical ordering in \p SourceCand. These are defined based on the
- /// canonical mapping defined between \p SoureCandLarge and
- /// \p TargetCandLarge. These IRSimilarityCandidates are already structurally
- /// similar, and fully encapsulate the IRSimilarityCandidates in question.
- /// These are used as a "bridge" from the \p SourceCand to the target.
- ///
- /// \param [in, out] SourceCand - The IRSimilarityCandidate to create a
- /// canonical numbering from.
- /// \param SoureCandLarge - The IRSimilarityCandidate fully containing
- /// \p SourceCand.
- /// \param TargetCandLarge - The IRSimilarityCandidate fully containing
- /// this Candidate.
- LLVM_ABI void
- createCanonicalRelationFrom(IRSimilarityCandidate &SourceCand,
- IRSimilarityCandidate &SourceCandLarge,
- IRSimilarityCandidate &TargetCandLarge);
-
- /// \param [in,out] BBSet - The set to track the basic blocks.
- void getBasicBlocks(DenseSet<BasicBlock *> &BBSet) const {
- for (IRInstructionData &ID : *this) {
- BasicBlock *BB = ID.Inst->getParent();
- BBSet.insert(BB);
- }
- }
-
- /// \param [in,out] BBSet - The set to track the basic blocks.
- /// \param [in,out] BBList - A list in order of use to track the basic blocks.
- void getBasicBlocks(DenseSet<BasicBlock *> &BBSet,
- SmallVector<BasicBlock *> &BBList) const {
- for (IRInstructionData &ID : *this) {
- BasicBlock *BB = ID.Inst->getParent();
- if (BBSet.insert(BB).second)
- BBList.push_back(BB);
- }
- }
-
- /// Compare the start and end indices of the two IRSimilarityCandidates for
- /// whether they overlap. If the start instruction of one
- /// IRSimilarityCandidate is less than the end instruction of the other, and
- /// the start instruction of one is greater than the start instruction of the
- /// other, they overlap.
- ///
- /// \returns true if the IRSimilarityCandidates do not have overlapping
- /// instructions.
- LLVM_ABI static bool overlap(const IRSimilarityCandidate &A,
- const IRSimilarityCandidate &B);
-
- /// \returns the number of instructions in this Candidate.
- unsigned getLength() const { return Len; }
-
- /// \returns the start index of this IRSimilarityCandidate.
- unsigned getStartIdx() const { return StartIdx; }
-
- /// \returns the end index of this IRSimilarityCandidate.
- unsigned getEndIdx() const { return StartIdx + Len - 1; }
-
- /// \returns The first IRInstructionData.
- IRInstructionData *front() const { return FirstInst; }
- /// \returns The last IRInstructionData.
- IRInstructionData *back() const { return LastInst; }
-
- /// \returns The first Instruction.
- Instruction *frontInstruction() { return FirstInst->Inst; }
- /// \returns The last Instruction
- Instruction *backInstruction() { return LastInst->Inst; }
-
- /// \returns The BasicBlock the IRSimilarityCandidate starts in.
- BasicBlock *getStartBB() { return FirstInst->Inst->getParent(); }
- /// \returns The BasicBlock the IRSimilarityCandidate ends in.
- BasicBlock *getEndBB() { return LastInst->Inst->getParent(); }
-
- /// \returns The Function that the IRSimilarityCandidate is located in.
- Function *getFunction() { return getStartBB()->getParent(); }
-
- /// Finds the positive number associated with \p V if it has been mapped.
- /// \param [in] V - the Value to find.
- /// \returns The positive number corresponding to the value.
- /// \returns std::nullopt if not present.
- std::optional<unsigned> getGVN(Value *V) {
- assert(V != nullptr && "Value is a nullptr?");
- auto VNIt = ValueToNumber.find(V);
- if (VNIt == ValueToNumber.end())
- return std::nullopt;
- return VNIt->second;
- }
-
- /// Finds the Value associate with \p Num if it exists.
- /// \param [in] Num - the number to find.
- /// \returns The Value associated with the number.
- /// \returns std::nullopt if not present.
- std::optional<Value *> fromGVN(unsigned Num) {
- auto VNIt = NumberToValue.find(Num);
- if (VNIt == NumberToValue.end())
- return std::nullopt;
- assert(VNIt->second != nullptr && "Found value is a nullptr!");
- return VNIt->second;
- }
-
- /// Find the canonical number from the global value number \p N stored in the
- /// candidate.
- ///
- /// \param N - The global value number to find the canonical number for.
- /// \returns An optional containing the value, and std::nullopt if it could
- /// not be found.
- std::optional<unsigned> getCanonicalNum(unsigned N) {
- auto NCIt = NumberToCanonNum.find(N);
- if (NCIt == NumberToCanonNum.end())
- return std::nullopt;
- return NCIt->second;
- }
-
- /// Find the global value number from the canonical number \p N stored in the
- /// candidate.
- ///
- /// \param N - The canonical number to find the global vlaue number for.
- /// \returns An optional containing the value, and std::nullopt if it could
- /// not be found.
- std::optional<unsigned> fromCanonicalNum(unsigned N) {
- auto CNIt = CanonNumToNumber.find(N);
- if (CNIt == CanonNumToNumber.end())
- return std::nullopt;
- return CNIt->second;
- }
-
- /// \param RHS -The IRSimilarityCandidate to compare against
- /// \returns true if the IRSimilarityCandidate is occurs after the
- /// IRSimilarityCandidate in the program.
- bool operator<(const IRSimilarityCandidate &RHS) const {
- return getStartIdx() > RHS.getStartIdx();
- }
-
- using iterator = IRInstructionDataList::iterator;
- iterator begin() const { return iterator(front()); }
- iterator end() const { return std::next(iterator(back())); }
-};
-
-typedef DenseMap<IRSimilarityCandidate *,
- DenseMap<unsigned, DenseSet<unsigned>>>
- CandidateGVNMapping;
-typedef std::vector<IRSimilarityCandidate> SimilarityGroup;
-typedef std::vector<SimilarityGroup> SimilarityGroupList;
-
-/// This class puts all the pieces of the IRInstructionData,
-/// IRInstructionMapper, IRSimilarityCandidate together.
-///
-/// It first feeds the Module or vector of Modules into the IRInstructionMapper,
-/// and puts all the mapped instructions into a single long list of
-/// IRInstructionData.
-///
-/// The list of unsigned integers is given to the Suffix Tree or similar data
-/// structure to find repeated subsequences. We construct an
-/// IRSimilarityCandidate for each instance of the subsequence. We compare them
-/// against one another since These repeated subsequences can have different
-/// structure. For each different kind of structure found, we create a
-/// similarity group.
-///
-/// If we had four IRSimilarityCandidates A, B, C, and D where A, B and D are
-/// structurally similar to one another, while C is different we would have two
-/// SimilarityGroups:
-///
-/// SimilarityGroup 1: SimilarityGroup 2
-/// A, B, D C
-///
-/// A list of the different similarity groups is then returned after
-/// analyzing the module.
-class IRSimilarityIdentifier {
-public:
- IRSimilarityIdentifier(bool MatchBranches = true,
- bool MatchIndirectCalls = true,
- bool MatchCallsWithName = false,
- bool MatchIntrinsics = true,
- bool MatchMustTailCalls = true)
- : Mapper(&InstDataAllocator, &InstDataListAllocator),
- EnableBranches(MatchBranches), EnableIndirectCalls(MatchIndirectCalls),
- EnableMatchingCallsByName(MatchCallsWithName),
- EnableIntrinsics(MatchIntrinsics),
- EnableMustTailCalls(MatchMustTailCalls) {}
-
-private:
- /// Map the instructions in the module to unsigned integers, using mapping
- /// already present in the Mapper if possible.
- ///
- /// \param [in] M Module - To map to integers.
- /// \param [in,out] InstrList - The vector to append IRInstructionData to.
- /// \param [in,out] IntegerMapping - The vector to append integers to.
- void populateMapper(Module &M, std::vector<IRInstructionData *> &InstrList,
- std::vector<unsigned> &IntegerMapping);
-
- /// Map the instructions in the modules vector to unsigned integers, using
- /// mapping already present in the mapper if possible.
- ///
- /// \param [in] Modules - The list of modules to use to populate the mapper
- /// \param [in,out] InstrList - The vector to append IRInstructionData to.
- /// \param [in,out] IntegerMapping - The vector to append integers to.
- void populateMapper(ArrayRef<std::unique_ptr<Module>> &Modules,
- std::vector<IRInstructionData *> &InstrList,
- std::vector<unsigned> &IntegerMapping);
-
- /// Find the similarity candidates in \p InstrList and corresponding
- /// \p UnsignedVec
- ///
- /// \param [in,out] InstrList - The vector to append IRInstructionData to.
- /// \param [in,out] IntegerMapping - The vector to append integers to.
- /// candidates found in the program.
- void findCandidates(std::vector<IRInstructionData *> &InstrList,
- std::vector<unsigned> &IntegerMapping);
-
-public:
- // Find the IRSimilarityCandidates in the \p Modules and group by structural
- // similarity in a SimilarityGroup, each group is returned in a
- // SimilarityGroupList.
- //
- // \param [in] Modules - the modules to analyze.
- // \returns The groups of similarity ranges found in the modules.
- LLVM_ABI SimilarityGroupList &
- findSimilarity(ArrayRef<std::unique_ptr<Module>> Modules);
-
- // Find the IRSimilarityCandidates in the given Module grouped by structural
- // similarity in a SimilarityGroup, contained inside a SimilarityGroupList.
- //
- // \param [in] M - the module to analyze.
- // \returns The groups of similarity ranges found in the module.
- LLVM_ABI SimilarityGroupList &findSimilarity(Module &M);
-
- // Clears \ref SimilarityCandidates if it is already filled by a previous run.
- void resetSimilarityCandidates() {
- // If we've already analyzed a Module or set of Modules, so we must clear
- // the SimilarityCandidates to make sure we do not have only old values
- // hanging around.
- if (SimilarityCandidates)
- SimilarityCandidates->clear();
- else
- SimilarityCandidates = SimilarityGroupList();
- }
-
- // \returns The groups of similarity ranges found in the most recently passed
- // set of modules.
- std::optional<SimilarityGroupList> &getSimilarity() {
- return SimilarityCandidates;
- }
-
-private:
- /// The allocator for IRInstructionData.
- SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
-
- /// The allocator for IRInstructionDataLists.
- SpecificBumpPtrAllocator<IRInstructionDataList> InstDataListAllocator;
-
- /// Map Instructions to unsigned integers and wraps the Instruction in an
- /// instance of IRInstructionData.
- IRInstructionMapper Mapper;
-
- /// The flag variable that marks whether we should check branches for
- /// similarity, or only look within basic blocks.
- bool EnableBranches = true;
-
- /// The flag variable that marks whether we allow indirect calls to be checked
- /// for similarity, or exclude them as a legal instruction.
- bool EnableIndirectCalls = true;
-
- /// The flag variable that marks whether we allow calls to be marked as
- /// similar if they do not have the same name, only the same calling
- /// convention, attributes and type signature.
- bool EnableMatchingCallsByName = true;
-
- /// The flag variable that marks whether we should check intrinsics for
- /// similarity.
- bool EnableIntrinsics = true;
-
- // The flag variable that marks whether we should allow tailcalls
- // to be checked for similarity.
- bool EnableMustTailCalls = false;
-
- /// The SimilarityGroups found with the most recent run of \ref
- /// findSimilarity. std::nullopt if there is no recent run.
- std::optional<SimilarityGroupList> SimilarityCandidates;
-};
-
-} // end namespace IRSimilarity
-
-/// An analysis pass based on legacy pass manager that runs and returns
-/// IRSimilarityIdentifier run on the Module.
-class LLVM_ABI IRSimilarityIdentifierWrapperPass : public ModulePass {
- std::unique_ptr<IRSimilarity::IRSimilarityIdentifier> IRSI;
-
-public:
- static char ID;
- IRSimilarityIdentifierWrapperPass();
-
- IRSimilarity::IRSimilarityIdentifier &getIRSI() { return *IRSI; }
- const IRSimilarity::IRSimilarityIdentifier &getIRSI() const { return *IRSI; }
-
- bool doInitialization(Module &M) override;
- bool doFinalization(Module &M) override;
- bool runOnModule(Module &M) override;
- void getAnalysisUsage(AnalysisUsage &AU) const override {
- AU.setPreservesAll();
- }
-};
-
-/// An analysis pass that runs and returns the IRSimilarityIdentifier run on the
-/// Module.
-class IRSimilarityAnalysis : public AnalysisInfoMixin<IRSimilarityAnalysis> {
-public:
- typedef IRSimilarity::IRSimilarityIdentifier Result;
-
- LLVM_ABI Result run(Module &M, ModuleAnalysisManager &);
-
-private:
- friend AnalysisInfoMixin<IRSimilarityAnalysis>;
- LLVM_ABI static AnalysisKey Key;
-};
-
-/// Printer pass that uses \c IRSimilarityAnalysis.
-class IRSimilarityAnalysisPrinterPass
- : public RequiredPassInfoMixin<IRSimilarityAnalysisPrinterPass> {
- raw_ostream &OS;
-
-public:
- explicit IRSimilarityAnalysisPrinterPass(raw_ostream &OS) : OS(OS) {}
- LLVM_ABI PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM);
-};
-
-} // end namespace llvm
-
-#endif // LLVM_ANALYSIS_IRSIMILARITYIDENTIFIER_H
diff --git a/llvm/include/llvm/InitializePasses.h b/llvm/include/llvm/InitializePasses.h
index 55b54913d6d70..d80e02dcb356f 100644
--- a/llvm/include/llvm/InitializePasses.h
+++ b/llvm/include/llvm/InitializePasses.h
@@ -134,7 +134,6 @@ LLVM_ABI void initializeGlobalsAAWrapperPassPass(PassRegistry &);
LLVM_ABI void initializeHardwareLoopsLegacyPass(PassRegistry &);
LLVM_ABI void initializeLibcallLoweringInfoWrapperPass(PassRegistry &);
LLVM_ABI void initializeMIRProfileLoaderPassPass(PassRegistry &);
-LLVM_ABI void initializeIRSimilarityIdentifierWrapperPassPass(PassRegistry &);
LLVM_ABI void initializeIRTranslatorPass(PassRegistry &);
LLVM_ABI void initializeIVUsersWrapperPassPass(PassRegistry &);
LLVM_ABI void initializeIfConverterPass(PassRegistry &);
diff --git a/llvm/include/llvm/Transforms/IPO/IROutliner.h b/llvm/include/llvm/Transforms/IPO/IROutliner.h
deleted file mode 100644
index e7cc728124a9a..0000000000000
--- a/llvm/include/llvm/Transforms/IPO/IROutliner.h
+++ /dev/null
@@ -1,469 +0,0 @@
-//===- IROutliner.h - Extract similar IR regions into 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
-//
-//===----------------------------------------------------------------------===//
-//
-// \file
-// The interface file for the IROutliner which is used by the IROutliner Pass.
-//
-// The outliner uses the IRSimilarityIdentifier to identify the similar regions
-// of code. It evaluates each set of IRSimilarityCandidates with an estimate of
-// whether it will provide code size reduction. Each region is extracted using
-// the code extractor. These extracted functions are consolidated into a single
-// function and called from the extracted call site.
-//
-// For example:
-// \code
-// %1 = add i32 %a, %b
-// %2 = add i32 %b, %a
-// %3 = add i32 %b, %a
-// %4 = add i32 %a, %b
-// \endcode
-// would become function
-// \code
-// define internal void outlined_ir_function(i32 %0, i32 %1) {
-// %1 = add i32 %0, %1
-// %2 = add i32 %1, %0
-// ret void
-// }
-// \endcode
-// with calls:
-// \code
-// call void outlined_ir_function(i32 %a, i32 %b)
-// call void outlined_ir_function(i32 %b, i32 %a)
-// \endcode
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_TRANSFORMS_IPO_IROUTLINER_H
-#define LLVM_TRANSFORMS_IPO_IROUTLINER_H
-
-#include "llvm/Analysis/IRSimilarityIdentifier.h"
-#include "llvm/IR/PassManager.h"
-#include "llvm/Support/InstructionCost.h"
-#include "llvm/Transforms/Utils/CodeExtractor.h"
-
-struct OutlinableGroup;
-
-namespace llvm {
-using namespace CallingConv;
-using namespace IRSimilarity;
-
-class Module;
-class TargetTransformInfo;
-class OptimizationRemarkEmitter;
-
-/// The OutlinableRegion holds all the information for a specific region, or
-/// sequence of instructions. This includes what values need to be hoisted to
-/// arguments from the extracted function, inputs and outputs to the region, and
-/// mapping from the extracted function arguments to overall function arguments.
-struct OutlinableRegion {
- /// Describes the region of code.
- IRSimilarityCandidate *Candidate = nullptr;
-
- /// If this region is outlined, the front and back IRInstructionData could
- /// potentially become invalidated if the only new instruction is a call.
- /// This ensures that we replace in the instruction in the IRInstructionData.
- IRInstructionData *NewFront = nullptr;
- IRInstructionData *NewBack = nullptr;
-
- /// The number of extracted inputs from the CodeExtractor.
- unsigned NumExtractedInputs = 0;
-
- /// The corresponding BasicBlock with the appropriate stores for this
- /// OutlinableRegion in the overall function.
- unsigned OutputBlockNum = -1;
-
- /// Mapping the extracted argument number to the argument number in the
- /// overall function. Since there will be inputs, such as elevated constants
- /// that are not the same in each region in a SimilarityGroup, or values that
- /// cannot be sunk into the extracted section in every region, we must keep
- /// track of which extracted argument maps to which overall argument.
- DenseMap<unsigned, unsigned> ExtractedArgToAgg;
- DenseMap<unsigned, unsigned> AggArgToExtracted;
-
- /// Values in the outlined functions will often be replaced by arguments. When
- /// finding corresponding values from one region to another, the found value
- /// will be the value the argument previously replaced. This structure maps
- /// any replaced values for the region to the aggregate aggregate argument
- /// in the overall function.
- DenseMap<Value *, Value *> RemappedArguments;
-
- /// Marks whether we need to change the order of the arguments when mapping
- /// the old extracted function call to the new aggregate outlined function
- /// call.
- bool ChangedArgOrder = false;
-
- /// Marks whether this region ends in a branch, there is special handling
- /// required for the following basic blocks in this case.
- bool EndsInBranch = false;
-
- /// The PHIBlocks with their corresponding return block based on the return
- /// value as the key.
- DenseMap<Value *, BasicBlock *> PHIBlocks;
-
- /// Mapping of the argument number in the deduplicated function
- /// to a given constant, which is used when creating the arguments to the call
- /// to the newly created deduplicated function. This is handled separately
- /// since the CodeExtractor does not recognize constants.
- DenseMap<unsigned, Constant *> AggArgToConstant;
-
- /// The global value numbers that are used as outputs for this section. Once
- /// extracted, each output will be stored to an output register. This
- /// documents the global value numbers that are used in this pattern.
- SmallVector<unsigned, 4> GVNStores;
-
- /// Used to create an outlined function.
- CodeExtractor *CE = nullptr;
-
- /// The call site of the extracted region.
- CallInst *Call = nullptr;
-
- /// The function for the extracted region.
- Function *ExtractedFunction = nullptr;
-
- /// Flag for whether we have split out the IRSimilarityCanidate. That is,
- /// make the region contained the IRSimilarityCandidate its own BasicBlock.
- bool CandidateSplit = false;
-
- /// Flag for whether we should not consider this region for extraction.
- bool IgnoreRegion = false;
-
- /// The BasicBlock that is before the start of the region BasicBlock,
- /// only defined when the region has been split.
- BasicBlock *PrevBB = nullptr;
-
- /// The BasicBlock that contains the starting instruction of the region.
- BasicBlock *StartBB = nullptr;
-
- /// The BasicBlock that contains the ending instruction of the region.
- BasicBlock *EndBB = nullptr;
-
- /// The BasicBlock that is after the start of the region BasicBlock,
- /// only defined when the region has been split.
- BasicBlock *FollowBB = nullptr;
-
- /// The Outlinable Group that contains this region and structurally similar
- /// regions to this region.
- OutlinableGroup *Parent = nullptr;
-
- OutlinableRegion(IRSimilarityCandidate &C, OutlinableGroup &Group)
- : Candidate(&C), Parent(&Group) {
- StartBB = C.getStartBB();
- EndBB = C.getEndBB();
- }
-
- /// For the contained region, split the parent BasicBlock at the starting and
- /// ending instructions of the contained IRSimilarityCandidate.
- LLVM_ABI void splitCandidate();
-
- /// For the contained region, reattach the BasicBlock at the starting and
- /// ending instructions of the contained IRSimilarityCandidate, or if the
- /// function has been extracted, the start and end of the BasicBlock
- /// containing the called function.
- LLVM_ABI void reattachCandidate();
-
- /// Find a corresponding value for \p V in similar OutlinableRegion \p Other.
- ///
- /// \param Other [in] - The OutlinableRegion to find the corresponding Value
- /// in.
- /// \param V [in] - The Value to look for in the other region.
- /// \return The corresponding Value to \p V if it exists, otherwise nullptr.
- LLVM_ABI Value *findCorrespondingValueIn(const OutlinableRegion &Other,
- Value *V);
-
- /// Find a corresponding BasicBlock for \p BB in similar OutlinableRegion \p Other.
- ///
- /// \param Other [in] - The OutlinableRegion to find the corresponding
- /// BasicBlock in.
- /// \param BB [in] - The BasicBlock to look for in the other region.
- /// \return The corresponding Value to \p V if it exists, otherwise nullptr.
- LLVM_ABI BasicBlock *findCorrespondingBlockIn(const OutlinableRegion &Other,
- BasicBlock *BB);
-
- /// Get the size of the code removed from the region.
- ///
- /// \param [in] TTI - The TargetTransformInfo for the parent function.
- /// \returns the code size of the region
- LLVM_ABI InstructionCost getBenefit(TargetTransformInfo &TTI);
-};
-
-/// This class is a pass that identifies similarity in a Module, extracts
-/// instances of the similarity, and then consolidating the similar regions
-/// in an effort to reduce code size. It uses the IRSimilarityIdentifier pass
-/// to identify the similar regions of code, and then extracts the similar
-/// sections into a single function. See the above for an example as to
-/// how code is extracted and consolidated into a single function.
-class IROutliner {
-public:
- IROutliner(function_ref<TargetTransformInfo &(Function &)> GTTI,
- function_ref<IRSimilarityIdentifier &(Module &)> GIRSI,
- function_ref<OptimizationRemarkEmitter &(Function &)> GORE)
- : getTTI(GTTI), getIRSI(GIRSI), getORE(GORE) {}
- LLVM_ABI bool run(Module &M);
-
-private:
- /// Find repeated similar code sequences in \p M and outline them into new
- /// Functions.
- ///
- /// \param [in] M - The module to outline from.
- /// \returns The number of Functions created.
- unsigned doOutline(Module &M);
-
- /// Check whether an OutlinableRegion is incompatible with code already
- /// outlined. OutlinableRegions are incomptaible when there are overlapping
- /// instructions, or code that has not been recorded has been added to the
- /// instructions.
- ///
- /// \param [in] Region - The OutlinableRegion to check for conflicts with
- /// already outlined code.
- /// \returns whether the region can safely be outlined.
- bool isCompatibleWithAlreadyOutlinedCode(const OutlinableRegion &Region);
-
- /// Remove all the IRSimilarityCandidates from \p CandidateVec that have
- /// instructions contained in a previously outlined region and put the
- /// remaining regions in \p CurrentGroup.
- ///
- /// \param [in] CandidateVec - List of similarity candidates for regions with
- /// the same similarity structure.
- /// \param [in,out] CurrentGroup - Contains the potential sections to
- /// be outlined.
- void
- pruneIncompatibleRegions(std::vector<IRSimilarityCandidate> &CandidateVec,
- OutlinableGroup &CurrentGroup);
-
- /// Create the function based on the overall types found in the current
- /// regions being outlined.
- ///
- /// \param M - The module to outline from.
- /// \param [in,out] CG - The OutlinableGroup for the regions to be outlined.
- /// \param [in] FunctionNameSuffix - How many functions have we previously
- /// created.
- /// \returns the newly created function.
- Function *createFunction(Module &M, OutlinableGroup &CG,
- unsigned FunctionNameSuffix);
-
- /// Identify the needed extracted inputs in a section, and add to the overall
- /// function if needed.
- ///
- /// \param [in] M - The module to outline from.
- /// \param [in,out] Region - The region to be extracted.
- /// \param [in] NotSame - The global value numbers of the Values in the region
- /// that do not have the same Constant in each strucutrally similar region.
- void findAddInputsOutputs(Module &M, OutlinableRegion &Region,
- DenseSet<unsigned> &NotSame);
-
- /// Find the number of instructions that will be removed by extracting the
- /// OutlinableRegions in \p CurrentGroup.
- ///
- /// \param [in] CurrentGroup - The collection of OutlinableRegions to be
- /// analyzed.
- /// \returns the number of outlined instructions across all regions.
- InstructionCost findBenefitFromAllRegions(OutlinableGroup &CurrentGroup);
-
- /// Find the number of instructions that will be added by reloading arguments.
- ///
- /// \param [in] CurrentGroup - The collection of OutlinableRegions to be
- /// analyzed.
- /// \returns the number of added reload instructions across all regions.
- InstructionCost findCostOutputReloads(OutlinableGroup &CurrentGroup);
-
- /// Find the cost and the benefit of \p CurrentGroup and save it back to
- /// \p CurrentGroup.
- ///
- /// \param [in] M - The module being analyzed
- /// \param [in,out] CurrentGroup - The overall outlined section
- void findCostBenefit(Module &M, OutlinableGroup &CurrentGroup);
-
- /// Update the output mapping based on the load instruction, and the outputs
- /// of the extracted function.
- ///
- /// \param Region - The region extracted
- /// \param Outputs - The outputs from the extracted function.
- /// \param LI - The load instruction used to update the mapping.
- void updateOutputMapping(OutlinableRegion &Region,
- ArrayRef<Value *> Outputs, LoadInst *LI);
-
- /// Extract \p Region into its own function.
- ///
- /// \param [in] Region - The region to be extracted into its own function.
- /// \returns True if it was successfully outlined.
- bool extractSection(OutlinableRegion &Region);
-
- /// For the similarities found, and the extracted sections, create a single
- /// outlined function with appropriate output blocks as necessary.
- ///
- /// \param [in] M - The module to outline from
- /// \param [in] CurrentGroup - The set of extracted sections to consolidate.
- /// \param [in,out] FuncsToRemove - List of functions to remove from the
- /// module after outlining is completed.
- /// \param [in,out] OutlinedFunctionNum - the number of new outlined
- /// functions.
- void deduplicateExtractedSections(Module &M, OutlinableGroup &CurrentGroup,
- std::vector<Function *> &FuncsToRemove,
- unsigned &OutlinedFunctionNum);
-
- /// Fill the new function that will serve as the replacement function for all
- /// of the extracted regions of a certain structure from the first region in
- /// the list of regions. Replace this first region's extracted function with
- /// the new overall function.
- ///
- /// \param [in] M - The module we are outlining from.
- /// \param [in] CurrentGroup - The group of regions to be outlined.
- /// \param [in,out] OutputStoreBBs - The output blocks for each different
- /// set of stores needed for the different functions.
- /// \param [in,out] FuncsToRemove - Extracted functions to erase from module
- /// once outlining is complete.
- void fillOverallFunction(
- Module &M, OutlinableGroup &CurrentGroup,
- std::vector<DenseMap<Value *, BasicBlock *>> &OutputStoreBBs,
- std::vector<Function *> &FuncsToRemove);
-
- /// If true, enables us to outline from functions that have LinkOnceFromODR
- /// linkages.
- bool OutlineFromLinkODRs = false;
-
- /// If false, we do not worry if the cost is greater than the benefit. This
- /// is for debugging and testing, so that we can test small cases to ensure
- /// that the outlining is being done correctly.
- bool CostModel = true;
-
- /// The set of outlined Instructions, identified by their location in the
- /// sequential ordering of instructions in a Module.
- DenseSet<unsigned> Outlined;
-
- /// TargetTransformInfo lambda for target specific information.
- function_ref<TargetTransformInfo &(Function &)> getTTI;
-
- /// A mapping from newly created reloaded output values to the original value.
- /// If an value is replace by an output from an outlined region, this maps
- /// that Value, back to its original Value.
- DenseMap<Value *, Value *> OutputMappings;
-
- /// IRSimilarityIdentifier lambda to retrieve IRSimilarityIdentifier.
- function_ref<IRSimilarityIdentifier &(Module &)> getIRSI;
-
- /// The optimization remark emitter for the pass.
- function_ref<OptimizationRemarkEmitter &(Function &)> getORE;
-
- /// The memory allocator used to allocate the CodeExtractors.
- SpecificBumpPtrAllocator<CodeExtractor> ExtractorAllocator;
-
- /// The memory allocator used to allocate the OutlinableRegions.
- SpecificBumpPtrAllocator<OutlinableRegion> RegionAllocator;
-
- /// The memory allocator used to allocate new IRInstructionData.
- SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
-
- /// Custom InstVisitor to classify different instructions for whether it can
- /// be analyzed for similarity. This is needed as there may be instruction we
- /// can identify as having similarity, but are more complicated to outline.
- struct InstructionAllowed : public InstVisitor<InstructionAllowed, bool> {
- InstructionAllowed() = default;
-
- bool visitUncondBrInst(UncondBrInst &BI) { return EnableBranches; }
- bool visitCondBrInst(CondBrInst &BI) { return EnableBranches; }
- bool visitPHINode(PHINode &PN) { return EnableBranches; }
- // TODO: Handle allocas.
- bool visitAllocaInst(AllocaInst &AI) { return false; }
- // VAArg instructions are not allowed since this could cause difficulty when
- // differentiating between different sets of variable instructions in
- // the deduplicated outlined regions.
- bool visitVAArgInst(VAArgInst &VI) { return false; }
- // We exclude all exception handling cases since they are so context
- // dependent.
- bool visitLandingPadInst(LandingPadInst &LPI) { return false; }
- bool visitFuncletPadInst(FuncletPadInst &FPI) { return false; }
- // DebugInfo should be included in the regions, but should not be
- // analyzed for similarity as it has no bearing on the outcome of the
- // program.
- bool visitDbgInfoIntrinsic(DbgInfoIntrinsic &DII) { return true; }
- // TODO: Handle specific intrinsics individually from those that can be
- // handled.
- bool IntrinsicInst(IntrinsicInst &II) { return EnableIntrinsics; }
- // We only handle CallInsts that are not indirect, since we cannot guarantee
- // that they have a name in these cases.
- bool visitCallInst(CallInst &CI) {
- Function *F = CI.getCalledFunction();
- bool IsIndirectCall = CI.isIndirectCall();
- if (IsIndirectCall && !EnableIndirectCalls)
- return false;
- if (!F && !IsIndirectCall)
- return false;
- // Returning twice can cause issues with the state of the function call
- // that were not expected when the function was used, so we do not include
- // the call in outlined functions.
- if (CI.canReturnTwice())
- return false;
- // TODO: Update the outliner to capture whether the outlined function
- // needs these extra attributes.
-
- // `nomerge` states that calls to this function should never be merged
- // during optimisation. Outlining would have the effect of merging
- // callsites from separate functions into a single callsite in the
- // outlined function.
- if (CI.hasFnAttr(Attribute::NoMerge))
- return false;
-
- // Functions marked with the swifttailcc and tailcc calling conventions
- // require special handling when outlining musttail functions. The
- // calling convention must be passed down to the outlined function as
- // well. Further, there is special handling for musttail calls as well,
- // requiring a return call directly after. For now, the outliner does not
- // support this.
- bool IsTailCC = CI.getCallingConv() == CallingConv::SwiftTail ||
- CI.getCallingConv() == CallingConv::Tail;
- if (IsTailCC && !EnableMustTailCalls)
- return false;
- if (CI.isMustTailCall() && !EnableMustTailCalls)
- return false;
- // The outliner can only handle musttail items if it is also accompanied
- // by the tailcc or swifttailcc calling convention.
- if (CI.isMustTailCall() && !IsTailCC)
- return false;
- return true;
- }
- // TODO: Handle FreezeInsts. Since a frozen value could be frozen inside
- // the outlined region, and then returned as an output, this will have to be
- // handled differently.
- bool visitFreezeInst(FreezeInst &CI) { return false; }
- // TODO: We do not current handle similarity that changes the control flow.
- bool visitInvokeInst(InvokeInst &II) { return false; }
- // TODO: We do not current handle similarity that changes the control flow.
- bool visitCallBrInst(CallBrInst &CBI) { return false; }
- // TODO: Handle interblock similarity.
- bool visitTerminator(Instruction &I) { return false; }
- bool visitInstruction(Instruction &I) { return true; }
-
- // The flag variable that marks whether we should allow branch instructions
- // to be outlined.
- bool EnableBranches = false;
-
- // The flag variable that marks whether we should allow indirect calls
- // to be outlined.
- bool EnableIndirectCalls = true;
-
- // The flag variable that marks whether we should allow intrinsics
- // instructions to be outlined.
- bool EnableIntrinsics = false;
-
- // The flag variable that marks whether we should allow musttail calls.
- bool EnableMustTailCalls = false;
- };
-
- /// A InstVisitor used to exclude certain instructions from being outlined.
- InstructionAllowed InstructionClassifier;
-};
-
-/// Pass to outline similar regions.
-class IROutlinerPass : public OptionalPassInfoMixin<IROutlinerPass> {
-public:
- LLVM_ABI PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM);
-};
-
-} // end namespace llvm
-
-#endif // LLVM_TRANSFORMS_IPO_IROUTLINER_H
diff --git a/llvm/lib/Analysis/Analysis.cpp b/llvm/lib/Analysis/Analysis.cpp
index aaac2cf187281..0e978723ad52a 100644
--- a/llvm/lib/Analysis/Analysis.cpp
+++ b/llvm/lib/Analysis/Analysis.cpp
@@ -46,7 +46,6 @@ void llvm::initializeAnalysis(PassRegistry &Registry) {
initializeExternalAAWrapperPassPass(Registry);
initializeImmutableModuleSummaryIndexWrapperPassPass(Registry);
initializeIVUsersWrapperPassPass(Registry);
- initializeIRSimilarityIdentifierWrapperPassPass(Registry);
initializeLazyBranchProbabilityInfoPassPass(Registry);
initializeLazyBFIPassPass(Registry);
initializeLazyBlockFrequencyInfoPassPass(Registry);
diff --git a/llvm/lib/Analysis/CMakeLists.txt b/llvm/lib/Analysis/CMakeLists.txt
index f3586c66cb056..aecea1bb92a1f 100644
--- a/llvm/lib/Analysis/CMakeLists.txt
+++ b/llvm/lib/Analysis/CMakeLists.txt
@@ -85,7 +85,6 @@ add_llvm_component_library(LLVMAnalysis
HashRecognize.cpp
HeatUtils.cpp
IR2Vec.cpp
- IRSimilarityIdentifier.cpp
IVDescriptors.cpp
IVUsers.cpp
ImportedFunctionsInliningStatistics.cpp
diff --git a/llvm/lib/Analysis/IRSimilarityIdentifier.cpp b/llvm/lib/Analysis/IRSimilarityIdentifier.cpp
deleted file mode 100644
index 256835bdba474..0000000000000
--- a/llvm/lib/Analysis/IRSimilarityIdentifier.cpp
+++ /dev/null
@@ -1,1519 +0,0 @@
-//===- IRSimilarityIdentifier.cpp - Find similarity in a module -----------===//
-//
-// Part of the LLVM Project, under the Apache 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
-// Implementation file for the IRSimilarityIdentifier for identifying
-// similarities in IR including the IRInstructionMapper.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Analysis/IRSimilarityIdentifier.h"
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/SetOperations.h"
-#include "llvm/IR/Intrinsics.h"
-#include "llvm/IR/Operator.h"
-#include "llvm/IR/User.h"
-#include "llvm/InitializePasses.h"
-#include "llvm/Support/SuffixTree.h"
-
-using namespace llvm;
-using namespace IRSimilarity;
-
-namespace llvm {
-cl::opt<bool>
- DisableBranches("no-ir-sim-branch-matching", cl::init(false),
- cl::ReallyHidden,
- cl::desc("disable similarity matching, and outlining, "
- "across branches for debugging purposes."));
-
-cl::opt<bool>
- DisableIndirectCalls("no-ir-sim-indirect-calls", cl::init(false),
- cl::ReallyHidden,
- cl::desc("disable outlining indirect calls."));
-
-static cl::opt<bool>
- MatchCallsByName("ir-sim-calls-by-name", cl::init(false), cl::ReallyHidden,
- cl::desc("only allow matching call instructions if the "
- "name and type signature match."));
-
-cl::opt<bool>
- DisableIntrinsics("no-ir-sim-intrinsics", cl::init(false), cl::ReallyHidden,
- cl::desc("Don't match or outline intrinsics"));
-} // namespace llvm
-
-IRInstructionData::IRInstructionData(Instruction &I, bool Legality,
- IRInstructionDataList &IDList)
- : Inst(&I), Legal(Legality), IDL(&IDList) {
- initializeInstruction();
-}
-
-void IRInstructionData::initializeInstruction() {
- // We check for whether we have a comparison instruction. If it is, we
- // find the "less than" version of the predicate for consistency for
- // comparison instructions throught the program.
- if (CmpInst *C = dyn_cast<CmpInst>(Inst)) {
- CmpInst::Predicate Predicate = predicateForConsistency(C);
- if (Predicate != C->getPredicate())
- RevisedPredicate = Predicate;
- }
-
- // Here we collect the operands and their types for determining whether
- // the structure of the operand use matches between two different candidates.
- for (Use &OI : Inst->operands()) {
- if (isa<CmpInst>(Inst) && RevisedPredicate) {
- // If we have a CmpInst where the predicate is reversed, it means the
- // operands must be reversed as well.
- OperVals.insert(OperVals.begin(), OI.get());
- continue;
- }
-
- OperVals.push_back(OI.get());
- }
-
- // We capture the incoming BasicBlocks as values as well as the incoming
- // Values in order to check for structural similarity.
- if (PHINode *PN = dyn_cast<PHINode>(Inst))
- llvm::append_range(OperVals, PN->blocks());
-}
-
-IRInstructionData::IRInstructionData(IRInstructionDataList &IDList)
- : IDL(&IDList) {}
-
-void IRInstructionData::setBranchSuccessors(
- DenseMap<BasicBlock *, unsigned> &BasicBlockToInteger) {
- assert((isa<UncondBrInst, CondBrInst>(Inst)) && "Instruction must be branch");
-
- DenseMap<BasicBlock *, unsigned>::iterator BBNumIt;
-
- BBNumIt = BasicBlockToInteger.find(Inst->getParent());
- assert(BBNumIt != BasicBlockToInteger.end() &&
- "Could not find location for BasicBlock!");
-
- int CurrentBlockNumber = static_cast<int>(BBNumIt->second);
-
- for (Value *V : getBlockOperVals()) {
- BasicBlock *Successor = cast<BasicBlock>(V);
- BBNumIt = BasicBlockToInteger.find(Successor);
- assert(BBNumIt != BasicBlockToInteger.end() &&
- "Could not find number for BasicBlock!");
- int OtherBlockNumber = static_cast<int>(BBNumIt->second);
-
- int Relative = OtherBlockNumber - CurrentBlockNumber;
- RelativeBlockLocations.push_back(Relative);
- }
-}
-
-ArrayRef<Value *> IRInstructionData::getBlockOperVals() {
- if (isa<UncondBrInst>(Inst))
- return OperVals;
- if (isa<CondBrInst>(Inst))
- return ArrayRef<Value *>(OperVals).drop_front(1);
-
- if (PHINode *PN = dyn_cast<PHINode>(Inst))
- return ArrayRef<Value *>(
- std::next(OperVals.begin(), PN->getNumIncomingValues()),
- OperVals.end()
- );
-
- llvm_unreachable("Instruction must be branch or PHINode");
-}
-
-void IRInstructionData::setCalleeName(bool MatchByName) {
- CallInst *CI = dyn_cast<CallInst>(Inst);
- assert(CI && "Instruction must be call");
-
- CalleeName = "";
- if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(Inst)) {
- // To hash intrinsics, we use the opcode, and types like the other
- // instructions, but also, the Intrinsic ID, and the Name of the
- // intrinsic.
- Intrinsic::ID IntrinsicID = II->getIntrinsicID();
- FunctionType *FT = II->getFunctionType();
- // If there is an overloaded name, we have to use the complex version
- // of getName to get the entire string.
- if (Intrinsic::isOverloaded(IntrinsicID))
- CalleeName =
- Intrinsic::getName(IntrinsicID, FT->params(), II->getModule(), FT);
- // If there is not an overloaded name, we only need to use this version.
- else
- CalleeName = Intrinsic::getName(IntrinsicID).str();
-
- return;
- }
-
- if (!CI->isIndirectCall() && MatchByName)
- CalleeName = CI->getCalledFunction()->getName().str();
-}
-
-void IRInstructionData::setPHIPredecessors(
- DenseMap<BasicBlock *, unsigned> &BasicBlockToInteger) {
- assert(isa<PHINode>(Inst) && "Instruction must be phi node");
-
- PHINode *PN = cast<PHINode>(Inst);
- DenseMap<BasicBlock *, unsigned>::iterator BBNumIt;
-
- BBNumIt = BasicBlockToInteger.find(PN->getParent());
- assert(BBNumIt != BasicBlockToInteger.end() &&
- "Could not find location for BasicBlock!");
-
- int CurrentBlockNumber = static_cast<int>(BBNumIt->second);
-
- // Convert the incoming blocks of the PHINode to an integer value, based on
- // the relative distances between the current block and the incoming block.
- for (unsigned Idx = 0; Idx < PN->getNumIncomingValues(); Idx++) {
- BasicBlock *Incoming = PN->getIncomingBlock(Idx);
- BBNumIt = BasicBlockToInteger.find(Incoming);
- assert(BBNumIt != BasicBlockToInteger.end() &&
- "Could not find number for BasicBlock!");
- int OtherBlockNumber = static_cast<int>(BBNumIt->second);
-
- int Relative = OtherBlockNumber - CurrentBlockNumber;
- RelativeBlockLocations.push_back(Relative);
- }
-}
-
-CmpInst::Predicate IRInstructionData::predicateForConsistency(CmpInst *CI) {
- switch (CI->getPredicate()) {
- case CmpInst::FCMP_OGT:
- case CmpInst::FCMP_UGT:
- case CmpInst::FCMP_OGE:
- case CmpInst::FCMP_UGE:
- case CmpInst::ICMP_SGT:
- case CmpInst::ICMP_UGT:
- case CmpInst::ICMP_SGE:
- case CmpInst::ICMP_UGE:
- return CI->getSwappedPredicate();
- default:
- return CI->getPredicate();
- }
-}
-
-CmpInst::Predicate IRInstructionData::getPredicate() const {
- assert(isa<CmpInst>(Inst) &&
- "Can only get a predicate from a compare instruction");
-
- if (RevisedPredicate)
- return *RevisedPredicate;
-
- return cast<CmpInst>(Inst)->getPredicate();
-}
-
-StringRef IRInstructionData::getCalleeName() const {
- assert(isa<CallInst>(Inst) &&
- "Can only get a name from a call instruction");
-
- assert(CalleeName && "CalleeName has not been set");
-
- return *CalleeName;
-}
-
-bool IRSimilarity::isClose(const IRInstructionData &A,
- const IRInstructionData &B) {
-
- if (!A.Legal || !B.Legal)
- return false;
-
- // Check if we are performing the same sort of operation on the same types
- // but not on the same values.
- if (!A.Inst->isSameOperationAs(B.Inst)) {
- // If there is a predicate, this means that either there is a swapped
- // predicate, or that the types are different, we want to make sure that
- // the predicates are equivalent via swapping.
- if (isa<CmpInst>(A.Inst) && isa<CmpInst>(B.Inst)) {
-
- if (A.getPredicate() != B.getPredicate())
- return false;
-
- // If the predicates are the same via swap, make sure that the types are
- // still the same.
- auto ZippedTypes = zip(A.OperVals, B.OperVals);
-
- return all_of(
- ZippedTypes, [](std::tuple<llvm::Value *, llvm::Value *> R) {
- return std::get<0>(R)->getType() == std::get<1>(R)->getType();
- });
- }
-
- return false;
- }
-
- // Since any GEP Instruction operands after the first operand cannot be
- // defined by a register, we must make sure that the operands after the first
- // are the same in the two instructions
- if (auto *GEP = dyn_cast<GetElementPtrInst>(A.Inst)) {
- auto *OtherGEP = cast<GetElementPtrInst>(B.Inst);
-
- // If the instructions do not have the same inbounds restrictions, we do
- // not consider them the same.
- if (GEP->isInBounds() != OtherGEP->isInBounds())
- return false;
-
- auto ZippedOperands = zip(GEP->indices(), OtherGEP->indices());
-
- // We increment here since we do not care about the first instruction,
- // we only care about the following operands since they must be the
- // exact same to be considered similar.
- return all_of(drop_begin(ZippedOperands),
- [](std::tuple<llvm::Use &, llvm::Use &> R) {
- return std::get<0>(R) == std::get<1>(R);
- });
- }
-
- // If the instructions are functions calls, we make sure that the function
- // name is the same. We already know that the types are since is
- // isSameOperationAs is true.
- if (isa<CallInst>(A.Inst) && isa<CallInst>(B.Inst)) {
- if (A.getCalleeName() != B.getCalleeName())
- return false;
- }
-
- if (isa<UncondBrInst, CondBrInst>(A.Inst) &&
- isa<UncondBrInst, CondBrInst>(B.Inst) &&
- A.RelativeBlockLocations.size() != B.RelativeBlockLocations.size())
- return false;
-
- return true;
-}
-
-// TODO: This is the same as the MachineOutliner, and should be consolidated
-// into the same interface.
-void IRInstructionMapper::convertToUnsignedVec(
- BasicBlock &BB, std::vector<IRInstructionData *> &InstrList,
- std::vector<unsigned> &IntegerMapping) {
- BasicBlock::iterator It = BB.begin();
-
- std::vector<unsigned> IntegerMappingForBB;
- std::vector<IRInstructionData *> InstrListForBB;
-
- for (BasicBlock::iterator Et = BB.end(); It != Et; ++It) {
- switch (InstClassifier.visit(*It)) {
- case InstrType::Legal:
- mapToLegalUnsigned(It, IntegerMappingForBB, InstrListForBB);
- break;
- case InstrType::Illegal:
- mapToIllegalUnsigned(It, IntegerMappingForBB, InstrListForBB);
- break;
- case InstrType::Invisible:
- AddedIllegalLastTime = false;
- break;
- }
- }
-
- if (AddedIllegalLastTime)
- mapToIllegalUnsigned(It, IntegerMappingForBB, InstrListForBB, true);
- for (IRInstructionData *ID : InstrListForBB)
- this->IDL->push_back(*ID);
- llvm::append_range(InstrList, InstrListForBB);
- llvm::append_range(IntegerMapping, IntegerMappingForBB);
-}
-
-// TODO: This is the same as the MachineOutliner, and should be consolidated
-// into the same interface.
-unsigned IRInstructionMapper::mapToLegalUnsigned(
- BasicBlock::iterator &It, std::vector<unsigned> &IntegerMappingForBB,
- std::vector<IRInstructionData *> &InstrListForBB) {
- // We added something legal, so we should unset the AddedLegalLastTime
- // flag.
- AddedIllegalLastTime = false;
-
- // If we have at least two adjacent legal instructions (which may have
- // invisible instructions in between), remember that.
- if (CanCombineWithPrevInstr)
- HaveLegalRange = true;
- CanCombineWithPrevInstr = true;
-
- // Get the integer for this instruction or give it the current
- // LegalInstrNumber.
- IRInstructionData *ID = allocateIRInstructionData(*It, true, *IDL);
- InstrListForBB.push_back(ID);
-
- if (isa<UncondBrInst, CondBrInst>(*It))
- ID->setBranchSuccessors(BasicBlockToInteger);
-
- if (isa<CallInst>(*It))
- ID->setCalleeName(EnableMatchCallsByName);
-
- if (isa<PHINode>(*It))
- ID->setPHIPredecessors(BasicBlockToInteger);
-
- // Add to the instruction list
- bool WasInserted;
- DenseMap<IRInstructionData *, unsigned, IRInstructionDataTraits>::iterator
- ResultIt;
- std::tie(ResultIt, WasInserted) =
- InstructionIntegerMap.insert(std::make_pair(ID, LegalInstrNumber));
- unsigned INumber = ResultIt->second;
-
- // There was an insertion.
- if (WasInserted)
- LegalInstrNumber++;
-
- IntegerMappingForBB.push_back(INumber);
-
- // Make sure we don't overflow or use any integers reserved by the DenseMap.
- assert(LegalInstrNumber < IllegalInstrNumber &&
- "Instruction mapping overflow!");
-
- return INumber;
-}
-
-IRInstructionData *
-IRInstructionMapper::allocateIRInstructionData(Instruction &I, bool Legality,
- IRInstructionDataList &IDL) {
- return new (InstDataAllocator->Allocate()) IRInstructionData(I, Legality, IDL);
-}
-
-IRInstructionData *
-IRInstructionMapper::allocateIRInstructionData(IRInstructionDataList &IDL) {
- return new (InstDataAllocator->Allocate()) IRInstructionData(IDL);
-}
-
-IRInstructionDataList *
-IRInstructionMapper::allocateIRInstructionDataList() {
- return new (IDLAllocator->Allocate()) IRInstructionDataList();
-}
-
-// TODO: This is the same as the MachineOutliner, and should be consolidated
-// into the same interface.
-unsigned IRInstructionMapper::mapToIllegalUnsigned(
- BasicBlock::iterator &It, std::vector<unsigned> &IntegerMappingForBB,
- std::vector<IRInstructionData *> &InstrListForBB, bool End) {
- // Can't combine an illegal instruction. Set the flag.
- CanCombineWithPrevInstr = false;
-
- // Only add one illegal number per range of legal numbers.
- if (AddedIllegalLastTime)
- return IllegalInstrNumber;
-
- IRInstructionData *ID = nullptr;
- if (!End)
- ID = allocateIRInstructionData(*It, false, *IDL);
- else
- ID = allocateIRInstructionData(*IDL);
- InstrListForBB.push_back(ID);
-
- // Remember that we added an illegal number last time.
- AddedIllegalLastTime = true;
- unsigned INumber = IllegalInstrNumber;
- IntegerMappingForBB.push_back(IllegalInstrNumber--);
-
- assert(LegalInstrNumber < IllegalInstrNumber &&
- "Instruction mapping overflow!");
-
- return INumber;
-}
-
-IRSimilarityCandidate::IRSimilarityCandidate(unsigned StartIdx, unsigned Len,
- IRInstructionData *FirstInstIt,
- IRInstructionData *LastInstIt)
- : StartIdx(StartIdx), Len(Len) {
-
- assert(FirstInstIt != nullptr && "Instruction is nullptr!");
- assert(LastInstIt != nullptr && "Instruction is nullptr!");
- assert(StartIdx + Len > StartIdx &&
- "Overflow for IRSimilarityCandidate range?");
- assert(Len - 1 == static_cast<unsigned>(std::distance(
- iterator(FirstInstIt), iterator(LastInstIt))) &&
- "Length of the first and last IRInstructionData do not match the "
- "given length");
-
- // We iterate over the given instructions, and map each unique value
- // to a unique number in the IRSimilarityCandidate ValueToNumber and
- // NumberToValue maps. A constant get its own value globally, the individual
- // uses of the constants are not considered to be unique.
- //
- // IR: Mapping Added:
- // %add1 = add i32 %a, c1 %add1 -> 3, %a -> 1, c1 -> 2
- // %add2 = add i32 %a, %1 %add2 -> 4
- // %add3 = add i32 c2, c1 %add3 -> 6, c2 -> 5
- //
- // when replace with global values, starting from 1, would be
- //
- // 3 = add i32 1, 2
- // 4 = add i32 1, 3
- // 6 = add i32 5, 2
- unsigned LocalValNumber = 1;
- IRInstructionDataList::iterator ID = iterator(*FirstInstIt);
- for (unsigned Loc = StartIdx; Loc < StartIdx + Len; Loc++, ID++) {
- // Map the operand values to an unsigned integer if it does not already
- // have an unsigned integer assigned to it.
- for (Value *Arg : ID->OperVals)
- if (ValueToNumber.try_emplace(Arg, LocalValNumber).second) {
- NumberToValue.try_emplace(LocalValNumber, Arg);
- LocalValNumber++;
- }
-
- // Mapping the instructions to an unsigned integer if it is not already
- // exist in the mapping.
- if (ValueToNumber.try_emplace(ID->Inst, LocalValNumber).second) {
- NumberToValue.try_emplace(LocalValNumber, ID->Inst);
- LocalValNumber++;
- }
- }
-
- // Setting the first and last instruction data pointers for the candidate. If
- // we got through the entire for loop without hitting an assert, we know
- // that both of these instructions are not nullptrs.
- FirstInst = FirstInstIt;
- LastInst = LastInstIt;
-
- // Add the basic blocks contained in the set into the global value numbering.
- DenseSet<BasicBlock *> BBSet;
- getBasicBlocks(BBSet);
- for (BasicBlock *BB : BBSet) {
- if (ValueToNumber.try_emplace(BB, LocalValNumber).second) {
- NumberToValue.try_emplace(LocalValNumber, BB);
- LocalValNumber++;
- }
- }
-}
-
-bool IRSimilarityCandidate::isSimilar(const IRSimilarityCandidate &A,
- const IRSimilarityCandidate &B) {
- if (A.getLength() != B.getLength())
- return false;
-
- auto InstrDataForBoth =
- zip(make_range(A.begin(), A.end()), make_range(B.begin(), B.end()));
-
- return all_of(InstrDataForBoth,
- [](std::tuple<IRInstructionData &, IRInstructionData &> R) {
- IRInstructionData &A = std::get<0>(R);
- IRInstructionData &B = std::get<1>(R);
- if (!A.Legal || !B.Legal)
- return false;
- return isClose(A, B);
- });
-}
-
-/// Determine if one or more of the assigned global value numbers for the
-/// operands in \p TargetValueNumbers is in the current mapping set for operand
-/// numbers in \p SourceOperands. The set of possible corresponding global
-/// value numbers are replaced with the most recent version of compatible
-/// values.
-///
-/// \param [in] SourceValueToNumberMapping - The mapping of a Value to global
-/// value number for the source IRInstructionCandidate.
-/// \param [in, out] CurrentSrcTgtNumberMapping - The current mapping of source
-/// IRSimilarityCandidate global value numbers to a set of possible numbers in
-/// the target.
-/// \param [in] SourceOperands - The operands in the original
-/// IRSimilarityCandidate in the current instruction.
-/// \param [in] TargetValueNumbers - The global value numbers of the operands in
-/// the corresponding Instruction in the other IRSimilarityCandidate.
-/// \returns true if there exists a possible mapping between the source
-/// Instruction operands and the target Instruction operands, and false if not.
-static bool checkNumberingAndReplaceCommutative(
- const DenseMap<Value *, unsigned> &SourceValueToNumberMapping,
- DenseMap<unsigned, DenseSet<unsigned>> &CurrentSrcTgtNumberMapping,
- ArrayRef<Value *> &SourceOperands,
- DenseSet<unsigned> &TargetValueNumbers){
-
- DenseMap<unsigned, DenseSet<unsigned>>::iterator ValueMappingIt;
-
- unsigned ArgVal;
- bool WasInserted;
-
- // Iterate over the operands in the source IRSimilarityCandidate to determine
- // whether there exists an operand in the other IRSimilarityCandidate that
- // creates a valid mapping of Value to Value between the
- // IRSimilarityCaniddates.
- for (Value *V : SourceOperands) {
- ArgVal = SourceValueToNumberMapping.find(V)->second;
-
- // Instead of finding a current mapping, we attempt to insert a set.
- std::tie(ValueMappingIt, WasInserted) = CurrentSrcTgtNumberMapping.insert(
- std::make_pair(ArgVal, TargetValueNumbers));
-
- // We need to iterate over the items in other IRSimilarityCandidate's
- // Instruction to determine whether there is a valid mapping of
- // Value to Value.
- DenseSet<unsigned> NewSet;
- for (unsigned &Curr : ValueMappingIt->second)
- // If we can find the value in the mapping, we add it to the new set.
- if (TargetValueNumbers.contains(Curr))
- NewSet.insert(Curr);
-
- // If we could not find a Value, return 0.
- if (NewSet.empty())
- return false;
-
- // Otherwise replace the old mapping with the newly constructed one.
- if (NewSet.size() != ValueMappingIt->second.size())
- ValueMappingIt->second.swap(NewSet);
-
- // We have reached no conclusions about the mapping, and cannot remove
- // any items from the other operands, so we move to check the next operand.
- if (ValueMappingIt->second.size() != 1)
- continue;
-
- unsigned ValToRemove = *ValueMappingIt->second.begin();
- // When there is only one item left in the mapping for and operand, remove
- // the value from the other operands. If it results in there being no
- // mapping, return false, it means the mapping is wrong
- for (Value *InnerV : SourceOperands) {
- if (V == InnerV)
- continue;
-
- unsigned InnerVal = SourceValueToNumberMapping.find(InnerV)->second;
- ValueMappingIt = CurrentSrcTgtNumberMapping.find(InnerVal);
- if (ValueMappingIt == CurrentSrcTgtNumberMapping.end())
- continue;
-
- ValueMappingIt->second.erase(ValToRemove);
- if (ValueMappingIt->second.empty())
- return false;
- }
- }
-
- return true;
-}
-
-/// Determine if operand number \p TargetArgVal is in the current mapping set
-/// for operand number \p SourceArgVal.
-///
-/// \param [in, out] CurrentSrcTgtNumberMapping current mapping of global
-/// value numbers from source IRSimilarityCandidate to target
-/// IRSimilarityCandidate.
-/// \param [in] SourceArgVal The global value number for an operand in the
-/// in the original candidate.
-/// \param [in] TargetArgVal The global value number for the corresponding
-/// operand in the other candidate.
-/// \returns True if there exists a mapping and false if not.
-bool checkNumberingAndReplace(
- DenseMap<unsigned, DenseSet<unsigned>> &CurrentSrcTgtNumberMapping,
- unsigned SourceArgVal, unsigned TargetArgVal) {
- // We are given two unsigned integers representing the global values of
- // the operands in different IRSimilarityCandidates and a current mapping
- // between the two.
- //
- // Source Operand GVN: 1
- // Target Operand GVN: 2
- // CurrentMapping: {1: {1, 2}}
- //
- // Since we have mapping, and the target operand is contained in the set, we
- // update it to:
- // CurrentMapping: {1: {2}}
- // and can return true. But, if the mapping was
- // CurrentMapping: {1: {3}}
- // we would return false.
-
- bool WasInserted;
- DenseMap<unsigned, DenseSet<unsigned>>::iterator Val;
-
- std::tie(Val, WasInserted) = CurrentSrcTgtNumberMapping.insert(
- std::make_pair(SourceArgVal, DenseSet<unsigned>({TargetArgVal})));
-
- // If we created a new mapping, then we are done.
- if (WasInserted)
- return true;
-
- // If there is more than one option in the mapping set, and the target value
- // is included in the mapping set replace that set with one that only includes
- // the target value, as it is the only valid mapping via the non commutative
- // instruction.
-
- DenseSet<unsigned> &TargetSet = Val->second;
- if (TargetSet.size() > 1 && TargetSet.contains(TargetArgVal)) {
- TargetSet.clear();
- TargetSet.insert(TargetArgVal);
- return true;
- }
-
- // Return true if we can find the value in the set.
- return TargetSet.contains(TargetArgVal);
-}
-
-bool IRSimilarityCandidate::compareNonCommutativeOperandMapping(
- OperandMapping A, OperandMapping B) {
- // Iterators to keep track of where we are in the operands for each
- // Instruction.
- ArrayRef<Value *>::iterator VItA = A.OperVals.begin();
- ArrayRef<Value *>::iterator VItB = B.OperVals.begin();
- unsigned OperandLength = A.OperVals.size();
-
- // For each operand, get the value numbering and ensure it is consistent.
- for (unsigned Idx = 0; Idx < OperandLength; Idx++, VItA++, VItB++) {
- unsigned OperValA = A.IRSC.ValueToNumber.find(*VItA)->second;
- unsigned OperValB = B.IRSC.ValueToNumber.find(*VItB)->second;
-
- // Attempt to add a set with only the target value. If there is no mapping
- // we can create it here.
- //
- // For an instruction like a subtraction:
- // IRSimilarityCandidateA: IRSimilarityCandidateB:
- // %resultA = sub %a, %b %resultB = sub %d, %e
- //
- // We map %a -> %d and %b -> %e.
- //
- // And check to see whether their mapping is consistent in
- // checkNumberingAndReplace.
-
- if (!checkNumberingAndReplace(A.ValueNumberMapping, OperValA, OperValB))
- return false;
-
- if (!checkNumberingAndReplace(B.ValueNumberMapping, OperValB, OperValA))
- return false;
- }
- return true;
-}
-
-bool IRSimilarityCandidate::compareCommutativeOperandMapping(
- OperandMapping A, OperandMapping B) {
- DenseSet<unsigned> ValueNumbersA;
- DenseSet<unsigned> ValueNumbersB;
-
- ArrayRef<Value *>::iterator VItA = A.OperVals.begin();
- ArrayRef<Value *>::iterator VItB = B.OperVals.begin();
- unsigned OperandLength = A.OperVals.size();
-
- // Find the value number sets for the operands.
- for (unsigned Idx = 0; Idx < OperandLength;
- Idx++, VItA++, VItB++) {
- ValueNumbersA.insert(A.IRSC.ValueToNumber.find(*VItA)->second);
- ValueNumbersB.insert(B.IRSC.ValueToNumber.find(*VItB)->second);
- }
-
- // Iterate over the operands in the first IRSimilarityCandidate and make sure
- // there exists a possible mapping with the operands in the second
- // IRSimilarityCandidate.
- if (!checkNumberingAndReplaceCommutative(A.IRSC.ValueToNumber,
- A.ValueNumberMapping, A.OperVals,
- ValueNumbersB))
- return false;
-
- // Iterate over the operands in the second IRSimilarityCandidate and make sure
- // there exists a possible mapping with the operands in the first
- // IRSimilarityCandidate.
- if (!checkNumberingAndReplaceCommutative(B.IRSC.ValueToNumber,
- B.ValueNumberMapping, B.OperVals,
- ValueNumbersA))
- return false;
-
- return true;
-}
-
-bool IRSimilarityCandidate::compareAssignmentMapping(
- const unsigned InstValA, const unsigned &InstValB,
- DenseMap<unsigned, DenseSet<unsigned>> &ValueNumberMappingA,
- DenseMap<unsigned, DenseSet<unsigned>> &ValueNumberMappingB) {
- DenseMap<unsigned, DenseSet<unsigned>>::iterator ValueMappingIt;
- bool WasInserted;
- std::tie(ValueMappingIt, WasInserted) = ValueNumberMappingA.insert(
- std::make_pair(InstValA, DenseSet<unsigned>({InstValB})));
- if (!WasInserted && !ValueMappingIt->second.contains(InstValB))
- return false;
- else if (ValueMappingIt->second.size() != 1) {
- // Snapshot the set before iterating: when InstValA maps to itself the
- // erase below removes InstValA from the very set being iterated, which
- // invalidates the range iterator under backward-shift deletion.
- SmallVector<unsigned> OtherVals(ValueMappingIt->second.begin(),
- ValueMappingIt->second.end());
- for (unsigned OtherVal : OtherVals) {
- if (OtherVal == InstValB)
- continue;
- auto OtherValIt = ValueNumberMappingA.find(OtherVal);
- if (OtherValIt == ValueNumberMappingA.end())
- continue;
- OtherValIt->second.erase(InstValA);
- }
- ValueNumberMappingA.erase(ValueMappingIt);
- std::tie(ValueMappingIt, WasInserted) = ValueNumberMappingA.insert(
- std::make_pair(InstValA, DenseSet<unsigned>({InstValB})));
- }
-
- return true;
-}
-
-bool IRSimilarityCandidate::checkRelativeLocations(RelativeLocMapping A,
- RelativeLocMapping B) {
- // Get the basic blocks the label refers to.
- BasicBlock *ABB = cast<BasicBlock>(A.OperVal);
- BasicBlock *BBB = cast<BasicBlock>(B.OperVal);
-
- // Get the basic blocks contained in each region.
- DenseSet<BasicBlock *> BasicBlockA;
- DenseSet<BasicBlock *> BasicBlockB;
- A.IRSC.getBasicBlocks(BasicBlockA);
- B.IRSC.getBasicBlocks(BasicBlockB);
-
- // Determine if the block is contained in the region.
- bool AContained = BasicBlockA.contains(ABB);
- bool BContained = BasicBlockB.contains(BBB);
-
- // Both blocks need to be contained in the region, or both need to be outside
- // the region.
- if (AContained != BContained)
- return false;
-
- // If both are contained, then we need to make sure that the relative
- // distance to the target blocks are the same.
- if (AContained)
- return A.RelativeLocation == B.RelativeLocation;
- return true;
-}
-
-bool IRSimilarityCandidate::compareStructure(const IRSimilarityCandidate &A,
- const IRSimilarityCandidate &B) {
- DenseMap<unsigned, DenseSet<unsigned>> MappingA;
- DenseMap<unsigned, DenseSet<unsigned>> MappingB;
- return IRSimilarityCandidate::compareStructure(A, B, MappingA, MappingB);
-}
-
-typedef detail::zippy<detail::zip_shortest, SmallVector<int, 4> &,
- SmallVector<int, 4> &, ArrayRef<Value *> &,
- ArrayRef<Value *> &>
- ZippedRelativeLocationsT;
-
-bool IRSimilarityCandidate::compareStructure(
- const IRSimilarityCandidate &A, const IRSimilarityCandidate &B,
- DenseMap<unsigned, DenseSet<unsigned>> &ValueNumberMappingA,
- DenseMap<unsigned, DenseSet<unsigned>> &ValueNumberMappingB) {
- if (A.getLength() != B.getLength())
- return false;
-
- if (A.ValueToNumber.size() != B.ValueToNumber.size())
- return false;
-
- iterator ItA = A.begin();
- iterator ItB = B.begin();
-
- // These ValueNumber Mapping sets create a create a mapping between the values
- // in one candidate to values in the other candidate. If we create a set with
- // one element, and that same element maps to the original element in the
- // candidate we have a good mapping.
-
- // Iterate over the instructions contained in each candidate
- unsigned SectionLength = A.getStartIdx() + A.getLength();
- for (unsigned Loc = A.getStartIdx(); Loc < SectionLength;
- ItA++, ItB++, Loc++) {
- // Make sure the instructions are similar to one another.
- if (!isClose(*ItA, *ItB))
- return false;
-
- Instruction *IA = ItA->Inst;
- Instruction *IB = ItB->Inst;
-
- if (!ItA->Legal || !ItB->Legal)
- return false;
-
- // Get the operand sets for the instructions.
- ArrayRef<Value *> OperValsA = ItA->OperVals;
- ArrayRef<Value *> OperValsB = ItB->OperVals;
-
- unsigned InstValA = A.ValueToNumber.find(IA)->second;
- unsigned InstValB = B.ValueToNumber.find(IB)->second;
-
- // Ensure that the mappings for the instructions exists.
- if (!compareAssignmentMapping(InstValA, InstValB, ValueNumberMappingA,
- ValueNumberMappingB))
- return false;
-
- if (!compareAssignmentMapping(InstValB, InstValA, ValueNumberMappingB,
- ValueNumberMappingA))
- return false;
-
- // We have different paths for commutative instructions and non-commutative
- // instructions since commutative instructions could allow multiple mappings
- // to certain values.
- if (IA->isCommutative() && !isa<FPMathOperator>(IA) &&
- !isa<IntrinsicInst>(IA)) {
- if (!compareCommutativeOperandMapping(
- {A, OperValsA, ValueNumberMappingA},
- {B, OperValsB, ValueNumberMappingB}))
- return false;
- continue;
- }
-
- // Handle the non-commutative cases.
- if (!compareNonCommutativeOperandMapping(
- {A, OperValsA, ValueNumberMappingA},
- {B, OperValsB, ValueNumberMappingB}))
- return false;
-
- // Here we check that between two corresponding instructions,
- // when referring to a basic block in the same region, the
- // relative locations are the same. And, that the instructions refer to
- // basic blocks outside the region in the same corresponding locations.
-
- // We are able to make the assumption about blocks outside of the region
- // since the target block labels are considered values and will follow the
- // same number matching that we defined for the other instructions in the
- // region. So, at this point, in each location we target a specific block
- // outside the region, we are targeting a corresponding block in each
- // analagous location in the region we are comparing to.
- if (!isa<UncondBrInst, CondBrInst, PHINode>(IA) ||
- IA->getOpcode() != IB->getOpcode())
- continue;
-
- SmallVector<int, 4> &RelBlockLocsA = ItA->RelativeBlockLocations;
- SmallVector<int, 4> &RelBlockLocsB = ItB->RelativeBlockLocations;
- ArrayRef<Value *> ABL = ItA->getBlockOperVals();
- ArrayRef<Value *> BBL = ItB->getBlockOperVals();
-
- // Check to make sure that the number of operands, and branching locations
- // between BranchInsts is the same.
- if (RelBlockLocsA.size() != RelBlockLocsB.size() &&
- ABL.size() != BBL.size())
- return false;
-
- assert(RelBlockLocsA.size() == ABL.size() &&
- "Block information vectors not the same size.");
- assert(RelBlockLocsB.size() == BBL.size() &&
- "Block information vectors not the same size.");
-
- ZippedRelativeLocationsT ZippedRelativeLocations =
- zip(RelBlockLocsA, RelBlockLocsB, ABL, BBL);
- if (any_of(ZippedRelativeLocations,
- [&A, &B](std::tuple<int, int, Value *, Value *> R) {
- return !checkRelativeLocations(
- {A, std::get<0>(R), std::get<2>(R)},
- {B, std::get<1>(R), std::get<3>(R)});
- }))
- return false;
- }
- return true;
-}
-
-bool IRSimilarityCandidate::overlap(const IRSimilarityCandidate &A,
- const IRSimilarityCandidate &B) {
- auto DoesOverlap = [](const IRSimilarityCandidate &X,
- const IRSimilarityCandidate &Y) {
- // Check:
- // XXXXXX X starts before Y ends
- // YYYYYYY Y starts after X starts
- return X.StartIdx <= Y.getEndIdx() && Y.StartIdx >= X.StartIdx;
- };
-
- return DoesOverlap(A, B) || DoesOverlap(B, A);
-}
-
-void IRSimilarityIdentifier::populateMapper(
- Module &M, std::vector<IRInstructionData *> &InstrList,
- std::vector<unsigned> &IntegerMapping) {
-
- std::vector<IRInstructionData *> InstrListForModule;
- std::vector<unsigned> IntegerMappingForModule;
- // Iterate over the functions in the module to map each Instruction in each
- // BasicBlock to an unsigned integer.
- Mapper.initializeForBBs(M);
-
- for (Function &F : M) {
-
- if (F.empty())
- continue;
-
- for (BasicBlock &BB : F) {
-
- // BB has potential to have similarity since it has a size greater than 2
- // and can therefore match other regions greater than 2. Map it to a list
- // of unsigned integers.
- Mapper.convertToUnsignedVec(BB, InstrListForModule,
- IntegerMappingForModule);
- }
-
- BasicBlock::iterator It = F.begin()->end();
- Mapper.mapToIllegalUnsigned(It, IntegerMappingForModule, InstrListForModule,
- true);
- if (InstrListForModule.size() > 0)
- Mapper.IDL->push_back(*InstrListForModule.back());
- }
-
- // Insert the InstrListForModule at the end of the overall InstrList so that
- // we can have a long InstrList for the entire set of Modules being analyzed.
- llvm::append_range(InstrList, InstrListForModule);
- // Do the same as above, but for IntegerMapping.
- llvm::append_range(IntegerMapping, IntegerMappingForModule);
-}
-
-void IRSimilarityIdentifier::populateMapper(
- ArrayRef<std::unique_ptr<Module>> &Modules,
- std::vector<IRInstructionData *> &InstrList,
- std::vector<unsigned> &IntegerMapping) {
-
- // Iterate over, and map the instructions in each module.
- for (const std::unique_ptr<Module> &M : Modules)
- populateMapper(*M, InstrList, IntegerMapping);
-}
-
-/// From a repeated subsequence, find all the different instances of the
-/// subsequence from the \p InstrList, and create an IRSimilarityCandidate from
-/// the IRInstructionData in subsequence.
-///
-/// \param [in] Mapper - The instruction mapper for basic correctness checks.
-/// \param [in] InstrList - The vector that holds the instruction data.
-/// \param [in] IntegerMapping - The vector that holds the mapped integers.
-/// \param [out] CandsForRepSubstring - The vector to store the generated
-/// IRSimilarityCandidates.
-static void createCandidatesFromSuffixTree(
- const IRInstructionMapper& Mapper, std::vector<IRInstructionData *> &InstrList,
- std::vector<unsigned> &IntegerMapping, SuffixTree::RepeatedSubstring &RS,
- std::vector<IRSimilarityCandidate> &CandsForRepSubstring) {
-
- unsigned StringLen = RS.Length;
- if (StringLen < 2)
- return;
-
- // Create an IRSimilarityCandidate for instance of this subsequence \p RS.
- for (const unsigned &StartIdx : RS.StartIndices) {
- unsigned EndIdx = StartIdx + StringLen - 1;
-
- // Check that this subsequence does not contain an illegal instruction.
- bool ContainsIllegal = false;
- for (unsigned CurrIdx = StartIdx; CurrIdx <= EndIdx; CurrIdx++) {
- unsigned Key = IntegerMapping[CurrIdx];
- if (Key > Mapper.IllegalInstrNumber) {
- ContainsIllegal = true;
- break;
- }
- }
-
- // If we have an illegal instruction, we should not create an
- // IRSimilarityCandidate for this region.
- if (ContainsIllegal)
- continue;
-
- // We are getting iterators to the instructions in this region of code
- // by advancing the start and end indices from the start of the
- // InstrList.
- std::vector<IRInstructionData *>::iterator StartIt = InstrList.begin();
- std::advance(StartIt, StartIdx);
- std::vector<IRInstructionData *>::iterator EndIt = InstrList.begin();
- std::advance(EndIt, EndIdx);
-
- CandsForRepSubstring.emplace_back(StartIdx, StringLen, *StartIt, *EndIt);
- }
-}
-
-void IRSimilarityCandidate::createCanonicalRelationFrom(
- IRSimilarityCandidate &SourceCand,
- DenseMap<unsigned, DenseSet<unsigned>> &ToSourceMapping,
- DenseMap<unsigned, DenseSet<unsigned>> &FromSourceMapping) {
- assert(SourceCand.CanonNumToNumber.size() != 0 &&
- "Base canonical relationship is empty!");
- assert(SourceCand.NumberToCanonNum.size() != 0 &&
- "Base canonical relationship is empty!");
-
- assert(CanonNumToNumber.size() == 0 && "Canonical Relationship is non-empty");
- assert(NumberToCanonNum.size() == 0 && "Canonical Relationship is non-empty");
-
- DenseSet<unsigned> UsedGVNs;
- // Iterate over the mappings provided from this candidate to SourceCand. We
- // are then able to map the GVN in this candidate to the same canonical number
- // given to the corresponding GVN in SourceCand.
- for (std::pair<unsigned, DenseSet<unsigned>> &GVNMapping : ToSourceMapping) {
- unsigned SourceGVN = GVNMapping.first;
-
- assert(GVNMapping.second.size() != 0 && "Possible GVNs is 0!");
-
- unsigned ResultGVN;
- // We need special handling if we have more than one potential value. This
- // means that there are at least two GVNs that could correspond to this GVN.
- // This could lead to potential swapping later on, so we make a decision
- // here to ensure a one-to-one mapping.
- if (GVNMapping.second.size() > 1) {
- bool Found = false;
- for (unsigned Val : GVNMapping.second) {
- // We make sure the target value number hasn't already been reserved.
- if (UsedGVNs.contains(Val))
- continue;
-
- // We make sure that the opposite mapping is still consistent.
- DenseMap<unsigned, DenseSet<unsigned>>::iterator It =
- FromSourceMapping.find(Val);
-
- if (!It->second.contains(SourceGVN))
- continue;
-
- // We pick the first item that satisfies these conditions.
- Found = true;
- ResultGVN = Val;
- break;
- }
-
- assert(Found && "Could not find matching value for source GVN");
- (void)Found;
-
- } else
- ResultGVN = *GVNMapping.second.begin();
-
- // Whatever GVN is found, we mark it as used.
- UsedGVNs.insert(ResultGVN);
-
- unsigned CanonNum = *SourceCand.getCanonicalNum(ResultGVN);
- CanonNumToNumber.insert(std::make_pair(CanonNum, SourceGVN));
- NumberToCanonNum.insert(std::make_pair(SourceGVN, CanonNum));
- }
-
- DenseSet<BasicBlock *> BBSet;
- getBasicBlocks(BBSet);
- // Find canonical numbers for the BasicBlocks in the current candidate.
- // This is done by finding the corresponding value for the first instruction
- // in the block in the current candidate, finding the matching value in the
- // source candidate. Then by finding the parent of this value, use the
- // canonical number of the block in the source candidate for the canonical
- // number in the current candidate.
- for (BasicBlock *BB : BBSet) {
- unsigned BBGVNForCurrCand = ValueToNumber.find(BB)->second;
-
- // We can skip the BasicBlock if the canonical numbering has already been
- // found in a separate instruction.
- if (NumberToCanonNum.contains(BBGVNForCurrCand))
- continue;
-
- // If the basic block is the starting block, then the shared instruction may
- // not be the first instruction in the block, it will be the first
- // instruction in the similarity region.
- Value *FirstOutlineInst =
- BB == getStartBB() ? frontInstruction() : &*BB->begin();
-
- unsigned FirstInstGVN = *getGVN(FirstOutlineInst);
- unsigned FirstInstCanonNum = *getCanonicalNum(FirstInstGVN);
- unsigned SourceGVN = *SourceCand.fromCanonicalNum(FirstInstCanonNum);
- Value *SourceV = *SourceCand.fromGVN(SourceGVN);
- BasicBlock *SourceBB = cast<Instruction>(SourceV)->getParent();
- unsigned SourceBBGVN = *SourceCand.getGVN(SourceBB);
- unsigned SourceCanonBBGVN = *SourceCand.getCanonicalNum(SourceBBGVN);
- CanonNumToNumber.insert(std::make_pair(SourceCanonBBGVN, BBGVNForCurrCand));
- NumberToCanonNum.insert(std::make_pair(BBGVNForCurrCand, SourceCanonBBGVN));
- }
-}
-
-void IRSimilarityCandidate::createCanonicalRelationFrom(
- IRSimilarityCandidate &SourceCand, IRSimilarityCandidate &SourceCandLarge,
- IRSimilarityCandidate &TargetCandLarge) {
- assert(!SourceCand.CanonNumToNumber.empty() &&
- "Canonical Relationship is non-empty");
- assert(!SourceCand.NumberToCanonNum.empty() &&
- "Canonical Relationship is non-empty");
-
- assert(!SourceCandLarge.CanonNumToNumber.empty() &&
- "Canonical Relationship is non-empty");
- assert(!SourceCandLarge.NumberToCanonNum.empty() &&
- "Canonical Relationship is non-empty");
-
- assert(!TargetCandLarge.CanonNumToNumber.empty() &&
- "Canonical Relationship is non-empty");
- assert(!TargetCandLarge.NumberToCanonNum.empty() &&
- "Canonical Relationship is non-empty");
-
- assert(CanonNumToNumber.empty() && "Canonical Relationship is non-empty");
- assert(NumberToCanonNum.empty() && "Canonical Relationship is non-empty");
-
- // We're going to use the larger candidates as a "bridge" to create the
- // canonical number for the target candidate since we have idetified two
- // candidates as subsequences of larger sequences, and therefore must be
- // structurally similar.
- for (std::pair<Value *, unsigned> &ValueNumPair : ValueToNumber) {
- Value *CurrVal = ValueNumPair.first;
- unsigned TargetCandGVN = ValueNumPair.second;
-
- // Find the numbering in the large candidate that surrounds the
- // current candidate.
- std::optional<unsigned> OLargeTargetGVN = TargetCandLarge.getGVN(CurrVal);
- assert(OLargeTargetGVN.has_value() && "GVN not found for Value");
-
- // Get the canonical numbering in the large target candidate.
- std::optional<unsigned> OTargetCandCanon =
- TargetCandLarge.getCanonicalNum(OLargeTargetGVN.value());
- assert(OTargetCandCanon.has_value() &&
- "Canononical Number not found for GVN");
-
- // Get the GVN in the large source candidate from the canonical numbering.
- std::optional<unsigned> OLargeSourceGVN =
- SourceCandLarge.fromCanonicalNum(OTargetCandCanon.value());
- assert(OLargeSourceGVN.has_value() &&
- "GVN Number not found for Canonical Number");
-
- // Get the Value from the GVN in the large source candidate.
- std::optional<Value *> OLargeSourceV =
- SourceCandLarge.fromGVN(OLargeSourceGVN.value());
- assert(OLargeSourceV.has_value() && "Value not found for GVN");
-
- // Get the GVN number for the Value in the source candidate.
- std::optional<unsigned> OSourceGVN =
- SourceCand.getGVN(OLargeSourceV.value());
- assert(OSourceGVN.has_value() && "GVN Number not found for Value");
-
- // Get the canonical numbering from the GVN/
- std::optional<unsigned> OSourceCanon =
- SourceCand.getCanonicalNum(OSourceGVN.value());
- assert(OSourceCanon.has_value() && "Canon Number not found for GVN");
-
- // Insert the canonical numbering and GVN pair into their respective
- // mappings.
- CanonNumToNumber.insert(
- std::make_pair(OSourceCanon.value(), TargetCandGVN));
- NumberToCanonNum.insert(
- std::make_pair(TargetCandGVN, OSourceCanon.value()));
- }
-}
-
-void IRSimilarityCandidate::createCanonicalMappingFor(
- IRSimilarityCandidate &CurrCand) {
- assert(CurrCand.CanonNumToNumber.size() == 0 &&
- "Canonical Relationship is non-empty");
- assert(CurrCand.NumberToCanonNum.size() == 0 &&
- "Canonical Relationship is non-empty");
-
- unsigned CanonNum = 0;
- // Iterate over the value numbers found, the order does not matter in this
- // case.
- for (std::pair<unsigned, Value *> &NumToVal : CurrCand.NumberToValue) {
- CurrCand.NumberToCanonNum.insert(std::make_pair(NumToVal.first, CanonNum));
- CurrCand.CanonNumToNumber.insert(std::make_pair(CanonNum, NumToVal.first));
- CanonNum++;
- }
-}
-
-/// Look for larger IRSimilarityCandidates From the previously matched
-/// IRSimilarityCandidates that fully contain \p CandA or \p CandB. If there is
-/// an overlap, return a pair of structurally similar, larger
-/// IRSimilarityCandidates.
-///
-/// \param [in] CandA - The first candidate we are trying to determine the
-/// structure of.
-/// \param [in] CandB - The second candidate we are trying to determine the
-/// structure of.
-/// \param [in] IndexToIncludedCand - Mapping of index of the an instruction in
-/// a circuit to the IRSimilarityCandidates that include this instruction.
-/// \param [in] CandToOverallGroup - Mapping of IRSimilarityCandidate to a
-/// number representing the structural group assigned to it.
-static std::optional<
- std::pair<IRSimilarityCandidate *, IRSimilarityCandidate *>>
-CheckLargerCands(
- IRSimilarityCandidate &CandA, IRSimilarityCandidate &CandB,
- DenseMap<unsigned, DenseSet<IRSimilarityCandidate *>> &IndexToIncludedCand,
- DenseMap<IRSimilarityCandidate *, unsigned> &CandToGroup) {
- DenseMap<unsigned, IRSimilarityCandidate *> IncludedGroupAndCandA;
- DenseMap<unsigned, IRSimilarityCandidate *> IncludedGroupAndCandB;
- DenseSet<unsigned> IncludedGroupsA;
- DenseSet<unsigned> IncludedGroupsB;
-
- // Find the overall similarity group numbers that fully contain the candidate,
- // and record the larger candidate for each group.
- auto IdxToCandidateIt = IndexToIncludedCand.find(CandA.getStartIdx());
- std::optional<std::pair<IRSimilarityCandidate *, IRSimilarityCandidate *>>
- Result;
-
- unsigned CandAStart = CandA.getStartIdx();
- unsigned CandAEnd = CandA.getEndIdx();
- unsigned CandBStart = CandB.getStartIdx();
- unsigned CandBEnd = CandB.getEndIdx();
- if (IdxToCandidateIt == IndexToIncludedCand.end())
- return Result;
- for (IRSimilarityCandidate *MatchedCand : IdxToCandidateIt->second) {
- if (MatchedCand->getStartIdx() > CandAStart ||
- (MatchedCand->getEndIdx() < CandAEnd))
- continue;
- unsigned GroupNum = CandToGroup.find(MatchedCand)->second;
- IncludedGroupAndCandA.insert(std::make_pair(GroupNum, MatchedCand));
- IncludedGroupsA.insert(GroupNum);
- }
-
- // Find the overall similarity group numbers that fully contain the next
- // candidate, and record the larger candidate for each group.
- IdxToCandidateIt = IndexToIncludedCand.find(CandBStart);
- if (IdxToCandidateIt == IndexToIncludedCand.end())
- return Result;
- for (IRSimilarityCandidate *MatchedCand : IdxToCandidateIt->second) {
- if (MatchedCand->getStartIdx() > CandBStart ||
- MatchedCand->getEndIdx() < CandBEnd)
- continue;
- unsigned GroupNum = CandToGroup.find(MatchedCand)->second;
- IncludedGroupAndCandB.insert(std::make_pair(GroupNum, MatchedCand));
- IncludedGroupsB.insert(GroupNum);
- }
-
- // Find the intersection between the two groups, these are the groups where
- // the larger candidates exist.
- set_intersect(IncludedGroupsA, IncludedGroupsB);
-
- // If there is no intersection between the sets, then we cannot determine
- // whether or not there is a match.
- if (IncludedGroupsA.empty())
- return Result;
-
- // Create a pair that contains the larger candidates.
- auto ItA = IncludedGroupAndCandA.find(*IncludedGroupsA.begin());
- auto ItB = IncludedGroupAndCandB.find(*IncludedGroupsA.begin());
- Result = std::make_pair(ItA->second, ItB->second);
- return Result;
-}
-
-/// From the list of IRSimilarityCandidates, perform a comparison between each
-/// IRSimilarityCandidate to determine if there are overlapping
-/// IRInstructionData, or if they do not have the same structure.
-///
-/// \param [in] CandsForRepSubstring - The vector containing the
-/// IRSimilarityCandidates.
-/// \param [out] StructuralGroups - the mapping of unsigned integers to vector
-/// of IRSimilarityCandidates where each of the IRSimilarityCandidates in the
-/// vector are structurally similar to one another.
-/// \param [in] IndexToIncludedCand - Mapping of index of the an instruction in
-/// a circuit to the IRSimilarityCandidates that include this instruction.
-/// \param [in] CandToOverallGroup - Mapping of IRSimilarityCandidate to a
-/// number representing the structural group assigned to it.
-static void findCandidateStructures(
- std::vector<IRSimilarityCandidate> &CandsForRepSubstring,
- DenseMap<unsigned, SimilarityGroup> &StructuralGroups,
- DenseMap<unsigned, DenseSet<IRSimilarityCandidate *>> &IndexToIncludedCand,
- DenseMap<IRSimilarityCandidate *, unsigned> &CandToOverallGroup
- ) {
- std::vector<IRSimilarityCandidate>::iterator CandIt, CandEndIt, InnerCandIt,
- InnerCandEndIt;
-
- // IRSimilarityCandidates each have a structure for operand use. It is
- // possible that two instances of the same subsequences have different
- // structure. Each type of structure found is assigned a number. This
- // DenseMap maps an IRSimilarityCandidate to which type of similarity
- // discovered it fits within.
- DenseMap<IRSimilarityCandidate *, unsigned> CandToGroup;
-
- // Find the compatibility from each candidate to the others to determine
- // which candidates overlap and which have the same structure by mapping
- // each structure to a different group.
- bool SameStructure;
- bool Inserted;
- unsigned CurrentGroupNum = 0;
- unsigned OuterGroupNum;
- DenseMap<IRSimilarityCandidate *, unsigned>::iterator CandToGroupIt;
- DenseMap<IRSimilarityCandidate *, unsigned>::iterator CandToGroupItInner;
- DenseMap<unsigned, SimilarityGroup>::iterator CurrentGroupPair;
-
- // Iterate over the candidates to determine its structural and overlapping
- // compatibility with other instructions
- DenseMap<unsigned, DenseSet<unsigned>> ValueNumberMappingA;
- DenseMap<unsigned, DenseSet<unsigned>> ValueNumberMappingB;
- for (CandIt = CandsForRepSubstring.begin(),
- CandEndIt = CandsForRepSubstring.end();
- CandIt != CandEndIt; CandIt++) {
-
- // Determine if it has an assigned structural group already.
- // If not, we assign it one, and add it to our mapping.
- std::tie(CandToGroupIt, Inserted) =
- CandToGroup.try_emplace(&*CandIt, CurrentGroupNum);
- if (Inserted)
- ++CurrentGroupNum;
-
- // Get the structural group number from the iterator.
- OuterGroupNum = CandToGroupIt->second;
-
- // Check if we already have a list of IRSimilarityCandidates for the current
- // structural group. Create one if one does not exist.
- CurrentGroupPair = StructuralGroups.find(OuterGroupNum);
- if (CurrentGroupPair == StructuralGroups.end()) {
- IRSimilarityCandidate::createCanonicalMappingFor(*CandIt);
- std::tie(CurrentGroupPair, Inserted) = StructuralGroups.insert(
- std::make_pair(OuterGroupNum, SimilarityGroup({*CandIt})));
- }
-
- // Iterate over the IRSimilarityCandidates following the current
- // IRSimilarityCandidate in the list to determine whether the two
- // IRSimilarityCandidates are compatible. This is so we do not repeat pairs
- // of IRSimilarityCandidates.
- for (InnerCandIt = std::next(CandIt),
- InnerCandEndIt = CandsForRepSubstring.end();
- InnerCandIt != InnerCandEndIt; InnerCandIt++) {
-
- // We check if the inner item has a group already, if it does, we skip it.
- CandToGroupItInner = CandToGroup.find(&*InnerCandIt);
- if (CandToGroupItInner != CandToGroup.end())
- continue;
-
- // Check if we have found structural similarity between two candidates
- // that fully contains the first and second candidates.
- std::optional<std::pair<IRSimilarityCandidate *, IRSimilarityCandidate *>>
- LargerPair = CheckLargerCands(
- *CandIt, *InnerCandIt, IndexToIncludedCand, CandToOverallGroup);
-
- // If a pair was found, it means that we can assume that these smaller
- // substrings are also structurally similar. Use the larger candidates to
- // determine the canonical mapping between the two sections.
- if (LargerPair.has_value()) {
- SameStructure = true;
- InnerCandIt->createCanonicalRelationFrom(
- *CandIt, *LargerPair.value().first, *LargerPair.value().second);
- CandToGroup.insert(std::make_pair(&*InnerCandIt, OuterGroupNum));
- CurrentGroupPair->second.push_back(*InnerCandIt);
- continue;
- }
-
- // Otherwise we determine if they have the same structure and add it to
- // vector if they match.
- ValueNumberMappingA.clear();
- ValueNumberMappingB.clear();
- SameStructure = IRSimilarityCandidate::compareStructure(
- *CandIt, *InnerCandIt, ValueNumberMappingA, ValueNumberMappingB);
- if (!SameStructure)
- continue;
-
- InnerCandIt->createCanonicalRelationFrom(*CandIt, ValueNumberMappingA,
- ValueNumberMappingB);
- CandToGroup.insert(std::make_pair(&*InnerCandIt, OuterGroupNum));
- CurrentGroupPair->second.push_back(*InnerCandIt);
- }
- }
-}
-
-void IRSimilarityIdentifier::findCandidates(
- std::vector<IRInstructionData *> &InstrList,
- std::vector<unsigned> &IntegerMapping) {
- SuffixTree ST(IntegerMapping);
-
- std::vector<IRSimilarityCandidate> CandsForRepSubstring;
- std::vector<SimilarityGroup> NewCandidateGroups;
-
- DenseMap<unsigned, SimilarityGroup> StructuralGroups;
- DenseMap<unsigned, DenseSet<IRSimilarityCandidate *>> IndexToIncludedCand;
- DenseMap<IRSimilarityCandidate *, unsigned> CandToGroup;
-
- // Iterate over the subsequences found by the Suffix Tree to create
- // IRSimilarityCandidates for each repeated subsequence and determine which
- // instances are structurally similar to one another.
-
- // Sort the suffix tree from longest substring to shortest.
- std::vector<SuffixTree::RepeatedSubstring> RSes;
- for (SuffixTree::RepeatedSubstring &RS : ST)
- RSes.push_back(RS);
-
- llvm::stable_sort(RSes, [](const SuffixTree::RepeatedSubstring &LHS,
- const SuffixTree::RepeatedSubstring &RHS) {
- return LHS.Length > RHS.Length;
- });
- for (SuffixTree::RepeatedSubstring &RS : RSes) {
- createCandidatesFromSuffixTree(Mapper, InstrList, IntegerMapping, RS,
- CandsForRepSubstring);
-
- if (CandsForRepSubstring.size() < 2)
- continue;
-
- findCandidateStructures(CandsForRepSubstring, StructuralGroups,
- IndexToIncludedCand, CandToGroup);
- for (std::pair<unsigned, SimilarityGroup> &Group : StructuralGroups) {
- // We only add the group if it contains more than one
- // IRSimilarityCandidate. If there is only one, that means there is no
- // other repeated subsequence with the same structure.
- if (Group.second.size() > 1) {
- SimilarityCandidates->push_back(Group.second);
- // Iterate over each candidate in the group, and add an entry for each
- // instruction included with a mapping to a set of
- // IRSimilarityCandidates that include that instruction.
- for (IRSimilarityCandidate &IRCand : SimilarityCandidates->back()) {
- for (unsigned Idx = IRCand.getStartIdx(), Edx = IRCand.getEndIdx();
- Idx <= Edx; ++Idx)
- IndexToIncludedCand[Idx].insert(&IRCand);
- // Add mapping of candidate to the overall similarity group number.
- CandToGroup.insert(
- std::make_pair(&IRCand, SimilarityCandidates->size() - 1));
- }
- }
- }
-
- CandsForRepSubstring.clear();
- StructuralGroups.clear();
- NewCandidateGroups.clear();
- }
-}
-
-SimilarityGroupList &IRSimilarityIdentifier::findSimilarity(
- ArrayRef<std::unique_ptr<Module>> Modules) {
- resetSimilarityCandidates();
-
- std::vector<IRInstructionData *> InstrList;
- std::vector<unsigned> IntegerMapping;
- Mapper.InstClassifier.EnableBranches = this->EnableBranches;
- Mapper.InstClassifier.EnableIndirectCalls = EnableIndirectCalls;
- Mapper.EnableMatchCallsByName = EnableMatchingCallsByName;
- Mapper.InstClassifier.EnableIntrinsics = EnableIntrinsics;
- Mapper.InstClassifier.EnableMustTailCalls = EnableMustTailCalls;
-
- populateMapper(Modules, InstrList, IntegerMapping);
- findCandidates(InstrList, IntegerMapping);
-
- return *SimilarityCandidates;
-}
-
-SimilarityGroupList &IRSimilarityIdentifier::findSimilarity(Module &M) {
- resetSimilarityCandidates();
- Mapper.InstClassifier.EnableBranches = this->EnableBranches;
- Mapper.InstClassifier.EnableIndirectCalls = EnableIndirectCalls;
- Mapper.EnableMatchCallsByName = EnableMatchingCallsByName;
- Mapper.InstClassifier.EnableIntrinsics = EnableIntrinsics;
- Mapper.InstClassifier.EnableMustTailCalls = EnableMustTailCalls;
-
- std::vector<IRInstructionData *> InstrList;
- std::vector<unsigned> IntegerMapping;
-
- populateMapper(M, InstrList, IntegerMapping);
- findCandidates(InstrList, IntegerMapping);
-
- return *SimilarityCandidates;
-}
-
-INITIALIZE_PASS(IRSimilarityIdentifierWrapperPass, "ir-similarity-identifier",
- "ir-similarity-identifier", false, true)
-
-IRSimilarityIdentifierWrapperPass::IRSimilarityIdentifierWrapperPass()
- : ModulePass(ID) {}
-
-bool IRSimilarityIdentifierWrapperPass::doInitialization(Module &M) {
- IRSI.reset(new IRSimilarityIdentifier(!DisableBranches, !DisableIndirectCalls,
- MatchCallsByName, !DisableIntrinsics,
- false));
- return false;
-}
-
-bool IRSimilarityIdentifierWrapperPass::doFinalization(Module &M) {
- IRSI.reset();
- return false;
-}
-
-bool IRSimilarityIdentifierWrapperPass::runOnModule(Module &M) {
- IRSI->findSimilarity(M);
- return false;
-}
-
-AnalysisKey IRSimilarityAnalysis::Key;
-IRSimilarityIdentifier IRSimilarityAnalysis::run(Module &M,
- ModuleAnalysisManager &) {
- auto IRSI = IRSimilarityIdentifier(!DisableBranches, !DisableIndirectCalls,
- MatchCallsByName, !DisableIntrinsics,
- false);
- IRSI.findSimilarity(M);
- return IRSI;
-}
-
-PreservedAnalyses
-IRSimilarityAnalysisPrinterPass::run(Module &M, ModuleAnalysisManager &AM) {
- IRSimilarityIdentifier &IRSI = AM.getResult<IRSimilarityAnalysis>(M);
- std::optional<SimilarityGroupList> &SimilarityCandidatesOpt =
- IRSI.getSimilarity();
-
- for (std::vector<IRSimilarityCandidate> &CandVec : *SimilarityCandidatesOpt) {
- OS << CandVec.size() << " candidates of length "
- << CandVec.begin()->getLength() << ". Found in: \n";
- for (IRSimilarityCandidate &Cand : CandVec) {
- OS << " Function: " << Cand.front()->Inst->getFunction()->getName().str()
- << ", Basic Block: ";
- if (Cand.front()->Inst->getParent()->getName().str() == "")
- OS << "(unnamed)";
- else
- OS << Cand.front()->Inst->getParent()->getName().str();
- OS << "\n Start Instruction: ";
- Cand.frontInstruction()->print(OS);
- OS << "\n End Instruction: ";
- Cand.backInstruction()->print(OS);
- OS << "\n";
- }
- }
-
- return PreservedAnalyses::all();
-}
-
-char IRSimilarityIdentifierWrapperPass::ID = 0;
diff --git a/llvm/lib/Passes/PassBuilder.cpp b/llvm/lib/Passes/PassBuilder.cpp
index b8b5507447fd4..f758469dd8ebb 100644
--- a/llvm/lib/Passes/PassBuilder.cpp
+++ b/llvm/lib/Passes/PassBuilder.cpp
@@ -240,7 +240,6 @@
#include "llvm/Transforms/IPO/GlobalOpt.h"
#include "llvm/Transforms/IPO/GlobalSplit.h"
#include "llvm/Transforms/IPO/HotColdSplitting.h"
-#include "llvm/Transforms/IPO/IROutliner.h"
#include "llvm/Transforms/IPO/InferFunctionAttrs.h"
#include "llvm/Transforms/IPO/Instrumentor.h"
#include "llvm/Transforms/IPO/Internalize.h"
diff --git a/llvm/lib/Passes/PassBuilderPipelines.cpp b/llvm/lib/Passes/PassBuilderPipelines.cpp
index d62828c78bfe4..b8c5b1eab2f97 100644
--- a/llvm/lib/Passes/PassBuilderPipelines.cpp
+++ b/llvm/lib/Passes/PassBuilderPipelines.cpp
@@ -62,7 +62,6 @@
#include "llvm/Transforms/IPO/GlobalOpt.h"
#include "llvm/Transforms/IPO/GlobalSplit.h"
#include "llvm/Transforms/IPO/HotColdSplitting.h"
-#include "llvm/Transforms/IPO/IROutliner.h"
#include "llvm/Transforms/IPO/InferFunctionAttrs.h"
#include "llvm/Transforms/IPO/Inliner.h"
#include "llvm/Transforms/IPO/Instrumentor.h"
@@ -243,10 +242,6 @@ static cl::opt<bool>
EnableHotColdSplit("hot-cold-split",
cl::desc("Enable hot-cold splitting pass"));
-static cl::opt<bool> EnableIROutliner("ir-outliner", cl::init(false),
- cl::Hidden,
- cl::desc("Enable ir outliner pass"));
-
static cl::opt<bool>
DisablePreInliner("disable-preinline", cl::init(false), cl::Hidden,
cl::desc("Disable pre-instrumentation inliner"));
@@ -1701,13 +1696,6 @@ PassBuilder::buildModuleOptimizationPipeline(OptimizationLevel Level,
if (EnableHotColdSplit && !isLTOPreLink(LTOPhase))
MPM.addPass(HotColdSplittingPass());
- // Search the code for similar regions of code. If enough similar regions can
- // be found where extracting the regions into their own function will decrease
- // the size of the program, we extract the regions, a deduplicate the
- // structurally similar regions.
- if (EnableIROutliner)
- MPM.addPass(IROutlinerPass());
-
// Now we need to do some global optimization transforms.
// FIXME: It would seem like these should come first in the optimization
// pipeline and maybe be the bottom of the canonicalization pipeline? Weird
diff --git a/llvm/lib/Passes/PassRegistry.def b/llvm/lib/Passes/PassRegistry.def
index cba01aab49963..0955bfdb3246c 100644
--- a/llvm/lib/Passes/PassRegistry.def
+++ b/llvm/lib/Passes/PassRegistry.def
@@ -27,7 +27,6 @@ MODULE_ANALYSIS("dxil-resource-type", DXILResourceTypeAnalysis())
MODULE_ANALYSIS("dxil-resource-bindings", DXILResourceBindingAnalysis())
MODULE_ANALYSIS("inline-advisor", InlineAdvisorAnalysis())
MODULE_ANALYSIS("ir2vec-vocab", IR2VecVocabAnalysis())
-MODULE_ANALYSIS("ir-similarity", IRSimilarityAnalysis())
MODULE_ANALYSIS("last-run-tracking", LastRunTrackingAnalysis())
MODULE_ANALYSIS("lcg", LazyCallGraphAnalysis())
MODULE_ANALYSIS("libcall-lowering-info", LibcallLoweringModuleAnalysis())
@@ -108,7 +107,6 @@ MODULE_PASS("ctx-instr-lower", PGOCtxProfLoweringPass())
MODULE_PASS("print<ctx-prof-analysis>", CtxProfAnalysisPrinterPass(errs()))
MODULE_PASS("invalidate<all>", InvalidateAllAnalysesPass())
MODULE_PASS("instrumentor", InstrumentorPass())
-MODULE_PASS("iroutliner", IROutlinerPass())
MODULE_PASS("jmc-instrumenter", JMCInstrumenterPass())
MODULE_PASS("lower-emutls", LowerEmuTLSPass())
MODULE_PASS("lower-global-dtors", LowerGlobalDtorsPass())
@@ -144,7 +142,6 @@ MODULE_PASS("pre-isel-intrinsic-lowering", PreISelIntrinsicLoweringPass(TM))
MODULE_PASS("print", PrintModulePass(errs()))
MODULE_PASS("print-callgraph", CallGraphPrinterPass(errs()))
MODULE_PASS("print-callgraph-sccs", CallGraphSCCsPrinterPass(errs()))
-MODULE_PASS("print-ir-similarity", IRSimilarityAnalysisPrinterPass(errs()))
MODULE_PASS("print-lcg", LazyCallGraphPrinterPass(errs()))
MODULE_PASS("print-lcg-dot", LazyCallGraphDOTPrinterPass(errs()))
MODULE_PASS("print-must-be-executed-contexts",
diff --git a/llvm/lib/Transforms/IPO/CMakeLists.txt b/llvm/lib/Transforms/IPO/CMakeLists.txt
index a986b9485f563..23c610f1c15e6 100644
--- a/llvm/lib/Transforms/IPO/CMakeLists.txt
+++ b/llvm/lib/Transforms/IPO/CMakeLists.txt
@@ -24,7 +24,6 @@ add_llvm_component_library(LLVMipo
GlobalSplit.cpp
HotColdSplitting.cpp
IPO.cpp
- IROutliner.cpp
InferFunctionAttrs.cpp
Inliner.cpp
Instrumentor.cpp
diff --git a/llvm/lib/Transforms/IPO/IROutliner.cpp b/llvm/lib/Transforms/IPO/IROutliner.cpp
deleted file mode 100644
index 0e780d41c93ed..0000000000000
--- a/llvm/lib/Transforms/IPO/IROutliner.cpp
+++ /dev/null
@@ -1,2975 +0,0 @@
-//===- IROutliner.cpp -- Outline Similar Regions ----------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache 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
-// Implementation for the IROutliner which is used by the IROutliner Pass.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Transforms/IPO/IROutliner.h"
-#include "llvm/Analysis/IRSimilarityIdentifier.h"
-#include "llvm/Analysis/OptimizationRemarkEmitter.h"
-#include "llvm/Analysis/TargetTransformInfo.h"
-#include "llvm/IR/Attributes.h"
-#include "llvm/IR/DIBuilder.h"
-#include "llvm/IR/DebugInfo.h"
-#include "llvm/IR/DebugInfoMetadata.h"
-#include "llvm/IR/Dominators.h"
-#include "llvm/IR/Mangler.h"
-#include "llvm/IR/PassManager.h"
-#include "llvm/Support/CommandLine.h"
-#include "llvm/Transforms/IPO.h"
-#include "llvm/Transforms/Utils/ValueMapper.h"
-#include <optional>
-#include <vector>
-
-#define DEBUG_TYPE "iroutliner"
-
-using namespace llvm;
-using namespace IRSimilarity;
-
-// A command flag to be used for debugging to exclude branches from similarity
-// matching and outlining.
-namespace llvm {
-extern cl::opt<bool> DisableBranches;
-
-// A command flag to be used for debugging to indirect calls from similarity
-// matching and outlining.
-extern cl::opt<bool> DisableIndirectCalls;
-
-// A command flag to be used for debugging to exclude intrinsics from similarity
-// matching and outlining.
-extern cl::opt<bool> DisableIntrinsics;
-
-} // namespace llvm
-
-// Set to true if the user wants the ir outliner to run on linkonceodr linkage
-// functions. This is false by default because the linker can dedupe linkonceodr
-// functions. Since the outliner is confined to a single module (modulo LTO),
-// this is off by default. It should, however, be the default behavior in
-// LTO.
-static cl::opt<bool> EnableLinkOnceODRIROutlining(
- "enable-linkonceodr-ir-outlining", cl::Hidden,
- cl::desc("Enable the IR outliner on linkonceodr functions"),
- cl::init(false));
-
-// This is a debug option to test small pieces of code to ensure that outlining
-// works correctly.
-static cl::opt<bool> NoCostModel(
- "ir-outlining-no-cost", cl::init(false), cl::ReallyHidden,
- cl::desc("Debug option to outline greedily, without restriction that "
- "calculated benefit outweighs cost"));
-
-/// The OutlinableGroup holds all the overarching information for outlining
-/// a set of regions that are structurally similar to one another, such as the
-/// types of the overall function, the output blocks, the sets of stores needed
-/// and a list of the different regions. This information is used in the
-/// deduplication of extracted regions with the same structure.
-struct OutlinableGroup {
- /// The sections that could be outlined
- std::vector<OutlinableRegion *> Regions;
-
- /// The argument types for the function created as the overall function to
- /// replace the extracted function for each region.
- std::vector<Type *> ArgumentTypes;
- /// The FunctionType for the overall function.
- FunctionType *OutlinedFunctionType = nullptr;
- /// The Function for the collective overall function.
- Function *OutlinedFunction = nullptr;
-
- /// Flag for whether we should not consider this group of OutlinableRegions
- /// for extraction.
- bool IgnoreGroup = false;
-
- /// The return blocks for the overall function.
- DenseMap<Value *, BasicBlock *> EndBBs;
-
- /// The PHIBlocks with their corresponding return block based on the return
- /// value as the key.
- DenseMap<Value *, BasicBlock *> PHIBlocks;
-
- /// A set containing the different GVN store sets needed. Each array contains
- /// a sorted list of the different values that need to be stored into output
- /// registers.
- DenseSet<ArrayRef<unsigned>> OutputGVNCombinations;
-
- /// Flag for whether the \ref ArgumentTypes have been defined after the
- /// extraction of the first region.
- bool InputTypesSet = false;
-
- /// The number of input values in \ref ArgumentTypes. Anything after this
- /// index in ArgumentTypes is an output argument.
- unsigned NumAggregateInputs = 0;
-
- /// The mapping of the canonical numbering of the values in outlined sections
- /// to specific arguments.
- DenseMap<unsigned, unsigned> CanonicalNumberToAggArg;
-
- /// The number of branches in the region target a basic block that is outside
- /// of the region.
- unsigned BranchesToOutside = 0;
-
- /// Tracker counting backwards from the highest unsigned value possible to
- /// avoid conflicting with the GVNs of assigned values. We start at -3 since
- /// -2 and -1 are assigned by the DenseMap.
- unsigned PHINodeGVNTracker = -3;
-
- DenseMap<unsigned,
- std::pair<std::pair<unsigned, unsigned>, SmallVector<unsigned, 2>>>
- PHINodeGVNToGVNs;
- DenseMap<hash_code, unsigned> GVNsToPHINodeGVN;
-
- /// The number of instructions that will be outlined by extracting \ref
- /// Regions.
- InstructionCost Benefit = 0;
- /// The number of added instructions needed for the outlining of the \ref
- /// Regions.
- InstructionCost Cost = 0;
-
- /// The argument that needs to be marked with the swifterr attribute. If not
- /// needed, there is no value.
- std::optional<unsigned> SwiftErrorArgument;
-
- /// For the \ref Regions, we look at every Value. If it is a constant,
- /// we check whether it is the same in Region.
- ///
- /// \param [in,out] NotSame contains the global value numbers where the
- /// constant is not always the same, and must be passed in as an argument.
- void findSameConstants(DenseSet<unsigned> &NotSame);
-
- /// For the regions, look at each set of GVN stores needed and account for
- /// each combination. Add an argument to the argument types if there is
- /// more than one combination.
- ///
- /// \param [in] M - The module we are outlining from.
- void collectGVNStoreSets(Module &M);
-};
-
-/// Move the contents of \p SourceBB to before the last instruction of \p
-/// TargetBB.
-/// \param SourceBB - the BasicBlock to pull Instructions from.
-/// \param TargetBB - the BasicBlock to put Instruction into.
-static void moveBBContents(BasicBlock &SourceBB, BasicBlock &TargetBB) {
- TargetBB.splice(TargetBB.end(), &SourceBB);
-}
-
-/// A function to sort the keys of \p Map, which must be a mapping of constant
-/// values to basic blocks and return it in \p SortedKeys
-///
-/// \param SortedKeys - The vector the keys will be return in and sorted.
-/// \param Map - The DenseMap containing keys to sort.
-static void getSortedConstantKeys(std::vector<Value *> &SortedKeys,
- DenseMap<Value *, BasicBlock *> &Map) {
- for (auto &VtoBB : Map)
- SortedKeys.push_back(VtoBB.first);
-
- // Here we expect to have either 1 value that is void (nullptr) or multiple
- // values that are all constant integers.
- if (SortedKeys.size() == 1) {
- assert(!SortedKeys[0] && "Expected a single void value.");
- return;
- }
-
- stable_sort(SortedKeys, [](const Value *LHS, const Value *RHS) {
- assert(LHS && RHS && "Expected non void values.");
- const ConstantInt *LHSC = cast<ConstantInt>(LHS);
- const ConstantInt *RHSC = cast<ConstantInt>(RHS);
-
- return LHSC->getLimitedValue() < RHSC->getLimitedValue();
- });
-}
-
-Value *OutlinableRegion::findCorrespondingValueIn(const OutlinableRegion &Other,
- Value *V) {
- std::optional<unsigned> GVN = Candidate->getGVN(V);
- assert(GVN && "No GVN for incoming value");
- std::optional<unsigned> CanonNum = Candidate->getCanonicalNum(*GVN);
- std::optional<unsigned> FirstGVN =
- Other.Candidate->fromCanonicalNum(*CanonNum);
- std::optional<Value *> FoundValueOpt = Other.Candidate->fromGVN(*FirstGVN);
- return FoundValueOpt.value_or(nullptr);
-}
-
-BasicBlock *
-OutlinableRegion::findCorrespondingBlockIn(const OutlinableRegion &Other,
- BasicBlock *BB) {
- Instruction *FirstNonPHI = &*BB->getFirstNonPHIOrDbg();
- assert(FirstNonPHI && "block is empty?");
- Value *CorrespondingVal = findCorrespondingValueIn(Other, FirstNonPHI);
- if (!CorrespondingVal)
- return nullptr;
- BasicBlock *CorrespondingBlock =
- cast<Instruction>(CorrespondingVal)->getParent();
- return CorrespondingBlock;
-}
-
-/// Rewrite the BranchInsts in the incoming blocks to \p PHIBlock that are found
-/// in \p Included to branch to BasicBlock \p Replace if they currently branch
-/// to the BasicBlock \p Find. This is used to fix up the incoming basic blocks
-/// when PHINodes are included in outlined regions.
-///
-/// \param PHIBlock - The BasicBlock containing the PHINodes that need to be
-/// checked.
-/// \param Find - The successor block to be replaced.
-/// \param Replace - The new succesor block to branch to.
-/// \param Included - The set of blocks about to be outlined.
-static void replaceTargetsFromPHINode(BasicBlock *PHIBlock, BasicBlock *Find,
- BasicBlock *Replace,
- DenseSet<BasicBlock *> &Included) {
- for (PHINode &PN : PHIBlock->phis())
- for (BasicBlock *Incoming : PN.blocks())
- // Check if the incoming block is included in the set of blocks being
- // outlined.
- if (Included.contains(Incoming))
- Incoming->getTerminator()->replaceSuccessorWith(Find, Replace);
-}
-
-
-void OutlinableRegion::splitCandidate() {
- assert(!CandidateSplit && "Candidate already split!");
-
- Instruction *BackInst = Candidate->backInstruction();
-
- Instruction *EndInst = nullptr;
- // Check whether the last instruction is a terminator, if it is, we do
- // not split on the following instruction. We leave the block as it is. We
- // also check that this is not the last instruction in the Module, otherwise
- // the check for whether the current following instruction matches the
- // previously recorded instruction will be incorrect.
- if (!BackInst->isTerminator() ||
- BackInst->getParent() != &BackInst->getFunction()->back()) {
- EndInst = Candidate->end()->Inst;
- assert(EndInst && "Expected an end instruction?");
- }
-
- // We check if the current instruction following the last instruction in the
- // region is the same as the recorded instruction following the last
- // instruction. If they do not match, there could be problems in rewriting
- // the program after outlining, so we ignore it.
- if (!BackInst->isTerminator() && EndInst != BackInst->getNextNode())
- return;
-
- Instruction *StartInst = (*Candidate->begin()).Inst;
- assert(StartInst && "Expected a start instruction?");
- StartBB = StartInst->getParent();
- PrevBB = StartBB;
-
- DenseSet<BasicBlock *> BBSet;
- Candidate->getBasicBlocks(BBSet);
-
- // We iterate over the instructions in the region, if we find a PHINode, we
- // check if there are predecessors outside of the region, if there are,
- // we ignore this region since we are unable to handle the severing of the
- // phi node right now.
-
- // TODO: Handle extraneous inputs for PHINodes through variable number of
- // inputs, similar to how outputs are handled.
- BasicBlock::iterator It = StartInst->getIterator();
- EndBB = BackInst->getParent();
- BasicBlock *IBlock;
- BasicBlock *PHIPredBlock = nullptr;
- bool EndBBTermAndBackInstDifferent = EndBB->getTerminator() != BackInst;
- while (PHINode *PN = dyn_cast<PHINode>(&*It)) {
- unsigned NumPredsOutsideRegion = 0;
- for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) {
- if (!BBSet.contains(PN->getIncomingBlock(i))) {
- PHIPredBlock = PN->getIncomingBlock(i);
- ++NumPredsOutsideRegion;
- continue;
- }
-
- // We must consider the case there the incoming block to the PHINode is
- // the same as the final block of the OutlinableRegion. If this is the
- // case, the branch from this block must also be outlined to be valid.
- IBlock = PN->getIncomingBlock(i);
- if (IBlock == EndBB && EndBBTermAndBackInstDifferent) {
- PHIPredBlock = PN->getIncomingBlock(i);
- ++NumPredsOutsideRegion;
- }
- }
-
- if (NumPredsOutsideRegion > 1)
- return;
-
- It++;
- }
-
- // If the region starts with a PHINode, but is not the initial instruction of
- // the BasicBlock, we ignore this region for now.
- if (isa<PHINode>(StartInst) && StartInst != &*StartBB->begin())
- return;
-
- // If the region ends with a PHINode, but does not contain all of the phi node
- // instructions of the region, we ignore it for now.
- if (isa<PHINode>(BackInst) &&
- BackInst != &*std::prev(EndBB->getFirstInsertionPt()))
- return;
-
- // The basic block gets split like so:
- // block: block:
- // inst1 inst1
- // inst2 inst2
- // region1 br block_to_outline
- // region2 block_to_outline:
- // region3 -> region1
- // region4 region2
- // inst3 region3
- // inst4 region4
- // br block_after_outline
- // block_after_outline:
- // inst3
- // inst4
-
- std::string OriginalName = PrevBB->getName().str();
-
- StartBB = PrevBB->splitBasicBlock(StartInst, OriginalName + "_to_outline");
- PrevBB->replaceSuccessorsPhiUsesWith(PrevBB, StartBB);
- // If there was a PHINode with an incoming block outside the region,
- // make sure is correctly updated in the newly split block.
- if (PHIPredBlock)
- PrevBB->replaceSuccessorsPhiUsesWith(PHIPredBlock, PrevBB);
-
- CandidateSplit = true;
- if (!BackInst->isTerminator()) {
- EndBB = EndInst->getParent();
- FollowBB = EndBB->splitBasicBlock(EndInst, OriginalName + "_after_outline");
- EndBB->replaceSuccessorsPhiUsesWith(EndBB, FollowBB);
- FollowBB->replaceSuccessorsPhiUsesWith(PrevBB, FollowBB);
- } else {
- EndBB = BackInst->getParent();
- EndsInBranch = true;
- FollowBB = nullptr;
- }
-
- // Refind the basic block set.
- BBSet.clear();
- Candidate->getBasicBlocks(BBSet);
- // For the phi nodes in the new starting basic block of the region, we
- // reassign the targets of the basic blocks branching instructions.
- replaceTargetsFromPHINode(StartBB, PrevBB, StartBB, BBSet);
- if (FollowBB)
- replaceTargetsFromPHINode(FollowBB, EndBB, FollowBB, BBSet);
-}
-
-void OutlinableRegion::reattachCandidate() {
- assert(CandidateSplit && "Candidate is not split!");
-
- // The basic block gets reattached like so:
- // block: block:
- // inst1 inst1
- // inst2 inst2
- // br block_to_outline region1
- // block_to_outline: -> region2
- // region1 region3
- // region2 region4
- // region3 inst3
- // region4 inst4
- // br block_after_outline
- // block_after_outline:
- // inst3
- // inst4
- assert(StartBB != nullptr && "StartBB for Candidate is not defined!");
-
- assert(PrevBB->getTerminator() && "Terminator removed from PrevBB!");
- // Make sure PHINode references to the block we are merging into are
- // updated to be incoming blocks from the predecessor to the current block.
-
- // NOTE: If this is updated such that the outlined block can have more than
- // one incoming block to a PHINode, this logic will have to updated
- // to handle multiple precessors instead.
-
- // We only need to update this if the outlined section contains a PHINode, if
- // it does not, then the incoming block was never changed in the first place.
- // On the other hand, if PrevBB has no predecessors, it means that all
- // incoming blocks to the first block are contained in the region, and there
- // will be nothing to update.
- Instruction *StartInst = (*Candidate->begin()).Inst;
- if (isa<PHINode>(StartInst) && !PrevBB->hasNPredecessors(0)) {
- assert(!PrevBB->hasNPredecessorsOrMore(2) &&
- "PrevBB has more than one predecessor. Should be 0 or 1.");
- BasicBlock *BeforePrevBB = PrevBB->getSinglePredecessor();
- PrevBB->replaceSuccessorsPhiUsesWith(PrevBB, BeforePrevBB);
- }
- PrevBB->getTerminator()->eraseFromParent();
-
- // If we reattaching after outlining, we iterate over the phi nodes to
- // the initial block, and reassign the branch instructions of the incoming
- // blocks to the block we are remerging into.
- if (!ExtractedFunction) {
- DenseSet<BasicBlock *> BBSet;
- Candidate->getBasicBlocks(BBSet);
-
- replaceTargetsFromPHINode(StartBB, StartBB, PrevBB, BBSet);
- if (!EndsInBranch)
- replaceTargetsFromPHINode(FollowBB, FollowBB, EndBB, BBSet);
- }
-
- moveBBContents(*StartBB, *PrevBB);
-
- BasicBlock *PlacementBB = PrevBB;
- if (StartBB != EndBB)
- PlacementBB = EndBB;
- if (!EndsInBranch && PlacementBB->getUniqueSuccessor() != nullptr) {
- assert(FollowBB != nullptr && "FollowBB for Candidate is not defined!");
- assert(PlacementBB->getTerminator() && "Terminator removed from EndBB!");
- PlacementBB->getTerminator()->eraseFromParent();
- moveBBContents(*FollowBB, *PlacementBB);
- PlacementBB->replaceSuccessorsPhiUsesWith(FollowBB, PlacementBB);
- FollowBB->eraseFromParent();
- }
-
- PrevBB->replaceSuccessorsPhiUsesWith(StartBB, PrevBB);
- StartBB->eraseFromParent();
-
- // Make sure to save changes back to the StartBB.
- StartBB = PrevBB;
- EndBB = nullptr;
- PrevBB = nullptr;
- FollowBB = nullptr;
-
- CandidateSplit = false;
-}
-
-/// Find whether \p V matches the Constants previously found for the \p GVN.
-///
-/// \param V - The value to check for consistency.
-/// \param GVN - The global value number assigned to \p V.
-/// \param GVNToConstant - The mapping of global value number to Constants.
-/// \returns true if the Value matches the Constant mapped to by V and false if
-/// it \p V is a Constant but does not match.
-/// \returns std::nullopt if \p V is not a Constant.
-static std::optional<bool>
-constantMatches(Value *V, unsigned GVN,
- DenseMap<unsigned, Constant *> &GVNToConstant) {
- // See if we have a constants
- Constant *CST = dyn_cast<Constant>(V);
- if (!CST)
- return std::nullopt;
-
- // Holds a mapping from a global value number to a Constant.
- DenseMap<unsigned, Constant *>::iterator GVNToConstantIt;
- bool Inserted;
-
-
- // If we have a constant, try to make a new entry in the GVNToConstant.
- std::tie(GVNToConstantIt, Inserted) =
- GVNToConstant.insert(std::make_pair(GVN, CST));
- // If it was found and is not equal, it is not the same. We do not
- // handle this case yet, and exit early.
- if (Inserted || (GVNToConstantIt->second == CST))
- return true;
-
- return false;
-}
-
-InstructionCost OutlinableRegion::getBenefit(TargetTransformInfo &TTI) {
- InstructionCost Benefit = 0;
-
- // Estimate the benefit of outlining a specific sections of the program. We
- // delegate mostly this task to the TargetTransformInfo so that if the target
- // has specific changes, we can have a more accurate estimate.
-
- // However, getInstructionCost delegates the code size calculation for
- // arithmetic instructions to getArithmeticInstrCost in
- // include/Analysis/TargetTransformImpl.h, where it always estimates that the
- // code size for a division and remainder instruction to be equal to 4, and
- // everything else to 1. This is not an accurate representation of the
- // division instruction for targets that have a native division instruction.
- // To be overly conservative, we only add 1 to the number of instructions for
- // each division instruction.
- for (IRInstructionData &ID : *Candidate) {
- Instruction *I = ID.Inst;
- switch (I->getOpcode()) {
- case Instruction::FDiv:
- case Instruction::FRem:
- case Instruction::SDiv:
- case Instruction::SRem:
- case Instruction::UDiv:
- case Instruction::URem:
- Benefit += 1;
- break;
- default:
- Benefit += TTI.getInstructionCost(I, TargetTransformInfo::TCK_CodeSize);
- break;
- }
- }
-
- return Benefit;
-}
-
-/// Check the \p OutputMappings structure for value \p Input, if it exists
-/// it has been used as an output for outlining, and has been renamed, and we
-/// return the new value, otherwise, we return the same value.
-///
-/// \param OutputMappings [in] - The mapping of values to their renamed value
-/// after being used as an output for an outlined region.
-/// \param Input [in] - The value to find the remapped value of, if it exists.
-/// \return The remapped value if it has been renamed, and the same value if has
-/// not.
-static Value *findOutputMapping(const DenseMap<Value *, Value *> OutputMappings,
- Value *Input) {
- auto OutputMapping = OutputMappings.find(Input);
- if (OutputMapping != OutputMappings.end())
- return OutputMapping->second;
- return Input;
-}
-
-/// Find whether \p Region matches the global value numbering to Constant
-/// mapping found so far.
-///
-/// \param Region - The OutlinableRegion we are checking for constants
-/// \param GVNToConstant - The mapping of global value number to Constants.
-/// \param NotSame - The set of global value numbers that do not have the same
-/// constant in each region.
-/// \returns true if all Constants are the same in every use of a Constant in \p
-/// Region and false if not
-static bool
-collectRegionsConstants(OutlinableRegion &Region,
- DenseMap<unsigned, Constant *> &GVNToConstant,
- DenseSet<unsigned> &NotSame) {
- bool ConstantsTheSame = true;
-
- IRSimilarityCandidate &C = *Region.Candidate;
- for (IRInstructionData &ID : C) {
-
- // Iterate over the operands in an instruction. If the global value number,
- // assigned by the IRSimilarityCandidate, has been seen before, we check if
- // the number has been found to be not the same value in each instance.
- for (Value *V : ID.OperVals) {
- std::optional<unsigned> GVNOpt = C.getGVN(V);
- assert(GVNOpt && "Expected a GVN for operand?");
- unsigned GVN = *GVNOpt;
-
- // Check if this global value has been found to not be the same already.
- if (NotSame.contains(GVN)) {
- if (isa<Constant>(V))
- ConstantsTheSame = false;
- continue;
- }
-
- // If it has been the same so far, we check the value for if the
- // associated Constant value match the previous instances of the same
- // global value number. If the global value does not map to a Constant,
- // it is considered to not be the same value.
- std::optional<bool> ConstantMatches =
- constantMatches(V, GVN, GVNToConstant);
- if (ConstantMatches) {
- if (*ConstantMatches)
- continue;
- else
- ConstantsTheSame = false;
- }
-
- // While this value is a register, it might not have been previously,
- // make sure we don't already have a constant mapped to this global value
- // number.
- if (GVNToConstant.contains(GVN))
- ConstantsTheSame = false;
-
- NotSame.insert(GVN);
- }
- }
-
- return ConstantsTheSame;
-}
-
-void OutlinableGroup::findSameConstants(DenseSet<unsigned> &NotSame) {
- DenseMap<unsigned, Constant *> GVNToConstant;
-
- for (OutlinableRegion *Region : Regions)
- collectRegionsConstants(*Region, GVNToConstant, NotSame);
-}
-
-void OutlinableGroup::collectGVNStoreSets(Module &M) {
- for (OutlinableRegion *OS : Regions)
- OutputGVNCombinations.insert(OS->GVNStores);
-
- // We are adding an extracted argument to decide between which output path
- // to use in the basic block. It is used in a switch statement and only
- // needs to be an integer.
- if (OutputGVNCombinations.size() > 1)
- ArgumentTypes.push_back(Type::getInt32Ty(M.getContext()));
-}
-
-/// Get the subprogram if it exists for one of the outlined regions.
-///
-/// \param [in] Group - The set of regions to find a subprogram for.
-/// \returns the subprogram if it exists, or nullptr.
-static DISubprogram *getSubprogramOrNull(OutlinableGroup &Group) {
- for (OutlinableRegion *OS : Group.Regions)
- if (Function *F = OS->Call->getFunction())
- if (DISubprogram *SP = F->getSubprogram())
- return SP;
-
- return nullptr;
-}
-
-Function *IROutliner::createFunction(Module &M, OutlinableGroup &Group,
- unsigned FunctionNameSuffix) {
- assert(!Group.OutlinedFunction && "Function is already defined!");
-
- Type *RetTy = Type::getVoidTy(M.getContext());
- // All extracted functions _should_ have the same return type at this point
- // since the similarity identifier ensures that all branches outside of the
- // region occur in the same place.
-
- // NOTE: Should we ever move to the model that uses a switch at every point
- // needed, meaning that we could branch within the region or out, it is
- // possible that we will need to switch to using the most general case all of
- // the time.
- for (OutlinableRegion *R : Group.Regions) {
- Type *ExtractedFuncType = R->ExtractedFunction->getReturnType();
- if ((RetTy->isVoidTy() && !ExtractedFuncType->isVoidTy()) ||
- (RetTy->isIntegerTy(1) && ExtractedFuncType->isIntegerTy(16)))
- RetTy = ExtractedFuncType;
- }
-
- Group.OutlinedFunctionType = FunctionType::get(
- RetTy, Group.ArgumentTypes, false);
-
- // These functions will only be called from within the same module, so
- // we can set an internal linkage.
- Group.OutlinedFunction = Function::Create(
- Group.OutlinedFunctionType, GlobalValue::InternalLinkage,
- "outlined_ir_func_" + std::to_string(FunctionNameSuffix), M);
-
- // Transfer the swifterr attribute to the correct function parameter.
- if (Group.SwiftErrorArgument)
- Group.OutlinedFunction->addParamAttr(*Group.SwiftErrorArgument,
- Attribute::SwiftError);
-
- Group.OutlinedFunction->addFnAttr(Attribute::OptimizeForSize);
- Group.OutlinedFunction->addFnAttr(Attribute::MinSize);
-
- // If there's a DISubprogram associated with this outlined function, then
- // emit debug info for the outlined function.
- if (DISubprogram *SP = getSubprogramOrNull(Group)) {
- Function *F = Group.OutlinedFunction;
- // We have a DISubprogram. Get its DICompileUnit.
- DICompileUnit *CU = SP->getUnit();
- DIBuilder DB(M, true, CU);
- DIFile *Unit = SP->getFile();
- Mangler Mg;
- // Get the mangled name of the function for the linkage name.
- std::string Dummy;
- llvm::raw_string_ostream MangledNameStream(Dummy);
- Mg.getNameWithPrefix(MangledNameStream, F, false);
-
- DISubprogram *OutlinedSP = DB.createFunction(
- Unit /* Context */, F->getName(), Dummy, Unit /* File */,
- 0 /* Line 0 is reserved for compiler-generated code. */,
- DB.createSubroutineType(DB.getOrCreateTypeArray({})), /* void type */
- 0, /* Line 0 is reserved for compiler-generated code. */
- DINode::DIFlags::FlagArtificial /* Compiler-generated code. */,
- /* Outlined code is optimized code by definition. */
- DISubprogram::SPFlagDefinition | DISubprogram::SPFlagOptimized);
-
- // Attach subprogram to the function.
- F->setSubprogram(OutlinedSP);
- // We're done with the DIBuilder.
- DB.finalize();
- }
-
- return Group.OutlinedFunction;
-}
-
-/// Move each BasicBlock in \p Old to \p New.
-///
-/// \param [in] Old - The function to move the basic blocks from.
-/// \param [in] New - The function to move the basic blocks to.
-/// \param [out] NewEnds - The return blocks of the new overall function.
-static void moveFunctionData(Function &Old, Function &New,
- DenseMap<Value *, BasicBlock *> &NewEnds) {
- for (BasicBlock &CurrBB : llvm::make_early_inc_range(Old)) {
- CurrBB.removeFromParent();
- CurrBB.insertInto(&New);
- Instruction *I = CurrBB.getTerminator();
-
- // For each block we find a return instruction is, it is a potential exit
- // path for the function. We keep track of each block based on the return
- // value here.
- if (ReturnInst *RI = dyn_cast<ReturnInst>(I))
- NewEnds.insert(std::make_pair(RI->getReturnValue(), &CurrBB));
-
- 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 DbgVariableRecords
- // here, collect intrinsics for removal later.
- Val.dropDbgRecords();
-
- // We must handle the scoping of called functions differently than
- // other outlined instructions.
- if (!isa<CallInst>(&Val)) {
- // Remove the debug information for outlined functions.
- Val.setDebugLoc(DebugLoc::getDropped());
-
- // Loop info metadata may contain line locations. Update them to have no
- // value in the new subprogram since the outlined code could be from
- // several locations.
- auto updateLoopInfoLoc = [&New](Metadata *MD) -> Metadata * {
- if (DISubprogram *SP = New.getSubprogram())
- if (auto *Loc = dyn_cast_or_null<DILocation>(MD))
- return DILocation::get(New.getContext(), Loc->getLine(),
- Loc->getColumn(), SP, nullptr);
- return MD;
- };
- updateLoopMetadataDebugLocations(Val, updateLoopInfoLoc);
- continue;
- }
-
- // Edit the scope of called functions inside of outlined functions.
- if (DISubprogram *SP = New.getSubprogram()) {
- DILocation *DI = DILocation::get(New.getContext(), 0, 0, SP);
- Val.setDebugLoc(DI);
- }
- }
- }
-}
-
-/// Find the constants that will need to be lifted into arguments
-/// as they are not the same in each instance of the region.
-///
-/// \param [in] C - The IRSimilarityCandidate containing the region we are
-/// analyzing.
-/// \param [in] NotSame - The set of global value numbers that do not have a
-/// single Constant across all OutlinableRegions similar to \p C.
-/// \param [out] Inputs - The list containing the global value numbers of the
-/// arguments needed for the region of code.
-static void findConstants(IRSimilarityCandidate &C, DenseSet<unsigned> &NotSame,
- std::vector<unsigned> &Inputs) {
- DenseSet<unsigned> Seen;
- // Iterate over the instructions, and find what constants will need to be
- // extracted into arguments.
- for (IRInstructionDataList::iterator IDIt = C.begin(), EndIDIt = C.end();
- IDIt != EndIDIt; IDIt++) {
- for (Value *V : (*IDIt).OperVals) {
- // Since these are stored before any outlining, they will be in the
- // global value numbering.
- unsigned GVN = *C.getGVN(V);
- if (isa<Constant>(V))
- if (NotSame.contains(GVN) && Seen.insert(GVN).second)
- Inputs.push_back(GVN);
- }
- }
-}
-
-/// Find the GVN for the inputs that have been found by the CodeExtractor.
-///
-/// \param [in] C - The IRSimilarityCandidate containing the region we are
-/// analyzing.
-/// \param [in] CurrentInputs - The set of inputs found by the
-/// CodeExtractor.
-/// \param [in] OutputMappings - The mapping of values that have been replaced
-/// by a new output value.
-/// \param [out] EndInputNumbers - The global value numbers for the extracted
-/// arguments.
-static void mapInputsToGVNs(IRSimilarityCandidate &C,
- SetVector<Value *> &CurrentInputs,
- const DenseMap<Value *, Value *> &OutputMappings,
- std::vector<unsigned> &EndInputNumbers) {
- // Get the Global Value Number for each input. We check if the Value has been
- // replaced by a different value at output, and use the original value before
- // replacement.
- for (Value *Input : CurrentInputs) {
- assert(Input && "Have a nullptr as an input");
- auto It = OutputMappings.find(Input);
- if (It != OutputMappings.end())
- Input = It->second;
- assert(C.getGVN(Input) && "Could not find a numbering for the given input");
- EndInputNumbers.push_back(*C.getGVN(Input));
- }
-}
-
-/// Find the original value for the \p ArgInput values if any one of them was
-/// replaced during a previous extraction.
-///
-/// \param [in] ArgInputs - The inputs to be extracted by the code extractor.
-/// \param [in] OutputMappings - The mapping of values that have been replaced
-/// by a new output value.
-/// \param [out] RemappedArgInputs - The remapped values according to
-/// \p OutputMappings that will be extracted.
-static void
-remapExtractedInputs(const ArrayRef<Value *> ArgInputs,
- const DenseMap<Value *, Value *> &OutputMappings,
- SetVector<Value *> &RemappedArgInputs) {
- // Get the global value number for each input that will be extracted as an
- // argument by the code extractor, remapping if needed for reloaded values.
- for (Value *Input : ArgInputs) {
- auto It = OutputMappings.find(Input);
- if (It != OutputMappings.end())
- Input = It->second;
- RemappedArgInputs.insert(Input);
- }
-}
-
-/// Find the input GVNs and the output values for a region of Instructions.
-/// Using the code extractor, we collect the inputs to the extracted function.
-///
-/// The \p Region can be identified as needing to be ignored in this function.
-/// It should be checked whether it should be ignored after a call to this
-/// function.
-///
-/// \param [in,out] Region - The region of code to be analyzed.
-/// \param [out] InputGVNs - The global value numbers for the extracted
-/// arguments.
-/// \param [in] NotSame - The global value numbers in the region that do not
-/// have the same constant value in the regions structurally similar to
-/// \p Region.
-/// \param [in] OutputMappings - The mapping of values that have been replaced
-/// by a new output value after extraction.
-/// \param [out] ArgInputs - The values of the inputs to the extracted function.
-/// \param [out] Outputs - The set of values extracted by the CodeExtractor
-/// as outputs.
-static void getCodeExtractorArguments(
- OutlinableRegion &Region, std::vector<unsigned> &InputGVNs,
- DenseSet<unsigned> &NotSame, DenseMap<Value *, Value *> &OutputMappings,
- SetVector<Value *> &ArgInputs, SetVector<Value *> &Outputs) {
- IRSimilarityCandidate &C = *Region.Candidate;
-
- // OverallInputs are the inputs to the region found by the CodeExtractor,
- // SinkCands and HoistCands are used by the CodeExtractor to find sunken
- // allocas of values whose lifetimes are contained completely within the
- // outlined region. PremappedInputs are the arguments found by the
- // CodeExtractor, removing conditions such as sunken allocas, but that
- // may need to be remapped due to the extracted output values replacing
- // the original values. We use DummyOutputs for this first run of finding
- // inputs and outputs since the outputs could change during findAllocas,
- // the correct set of extracted outputs will be in the final Outputs ValueSet.
- SetVector<Value *> OverallInputs, PremappedInputs, SinkCands, HoistCands,
- DummyOutputs;
-
- // Use the code extractor to get the inputs and outputs, without sunken
- // allocas or removing llvm.assumes.
- CodeExtractor *CE = Region.CE;
- CE->findInputsOutputs(OverallInputs, DummyOutputs, SinkCands);
- assert(Region.StartBB && "Region must have a start BasicBlock!");
- Function *OrigF = Region.StartBB->getParent();
- CodeExtractorAnalysisCache CEAC(*OrigF);
- BasicBlock *Dummy = nullptr;
-
- // The region may be ineligible due to VarArgs in the parent function. In this
- // case we ignore the region.
- if (!CE->isEligible()) {
- Region.IgnoreRegion = true;
- return;
- }
-
- // Find if any values are going to be sunk into the function when extracted
- CE->findAllocas(CEAC, SinkCands, HoistCands, Dummy);
- CE->findInputsOutputs(PremappedInputs, Outputs, SinkCands);
-
- // TODO: Support regions with sunken allocas: values whose lifetimes are
- // contained completely within the outlined region. These are not guaranteed
- // to be the same in every region, so we must elevate them all to arguments
- // when they appear. If these values are not equal, it means there is some
- // Input in OverallInputs that was removed for ArgInputs.
- if (OverallInputs.size() != PremappedInputs.size()) {
- Region.IgnoreRegion = true;
- return;
- }
-
- findConstants(C, NotSame, InputGVNs);
-
- mapInputsToGVNs(C, OverallInputs, OutputMappings, InputGVNs);
-
- remapExtractedInputs(PremappedInputs.getArrayRef(), OutputMappings,
- ArgInputs);
-
- // Sort the GVNs, since we now have constants included in the \ref InputGVNs
- // we need to make sure they are in a deterministic order.
- stable_sort(InputGVNs);
-}
-
-/// Look over the inputs and map each input argument to an argument in the
-/// overall function for the OutlinableRegions. This creates a way to replace
-/// the arguments of the extracted function with the arguments of the new
-/// overall function.
-///
-/// \param [in,out] Region - The region of code to be analyzed.
-/// \param [in] InputGVNs - The global value numbering of the input values
-/// collected.
-/// \param [in] ArgInputs - The values of the arguments to the extracted
-/// function.
-static void
-findExtractedInputToOverallInputMapping(OutlinableRegion &Region,
- std::vector<unsigned> &InputGVNs,
- SetVector<Value *> &ArgInputs) {
-
- IRSimilarityCandidate &C = *Region.Candidate;
- OutlinableGroup &Group = *Region.Parent;
-
- // This counts the argument number in the overall function.
- unsigned TypeIndex = 0;
-
- // This counts the argument number in the extracted function.
- unsigned OriginalIndex = 0;
-
- // Find the mapping of the extracted arguments to the arguments for the
- // overall function. Since there may be extra arguments in the overall
- // function to account for the extracted constants, we have two different
- // counters as we find extracted arguments, and as we come across overall
- // arguments.
-
- // Additionally, in our first pass, for the first extracted function,
- // we find argument locations for the canonical value numbering. This
- // numbering overrides any discovered location for the extracted code.
- for (unsigned InputVal : InputGVNs) {
- std::optional<unsigned> CanonicalNumberOpt = C.getCanonicalNum(InputVal);
- assert(CanonicalNumberOpt && "Canonical number not found?");
- unsigned CanonicalNumber = *CanonicalNumberOpt;
-
- std::optional<Value *> InputOpt = C.fromGVN(InputVal);
- assert(InputOpt && "Global value number not found?");
- Value *Input = *InputOpt;
-
- auto AggArgIt = Group.CanonicalNumberToAggArg.find(CanonicalNumber);
-
- if (!Group.InputTypesSet) {
- Group.ArgumentTypes.push_back(Input->getType());
- // If the input value has a swifterr attribute, make sure to mark the
- // argument in the overall function.
- if (Input->isSwiftError()) {
- assert(
- !Group.SwiftErrorArgument &&
- "Argument already marked with swifterr for this OutlinableGroup!");
- Group.SwiftErrorArgument = TypeIndex;
- }
- }
-
- // Check if we have a constant. If we do add it to the overall argument
- // number to Constant map for the region, and continue to the next input.
- if (Constant *CST = dyn_cast<Constant>(Input)) {
- if (AggArgIt != Group.CanonicalNumberToAggArg.end())
- Region.AggArgToConstant.insert(std::make_pair(AggArgIt->second, CST));
- else {
- Group.CanonicalNumberToAggArg.insert(
- std::make_pair(CanonicalNumber, TypeIndex));
- Region.AggArgToConstant.insert(std::make_pair(TypeIndex, CST));
- }
- TypeIndex++;
- continue;
- }
-
- // It is not a constant, we create the mapping from extracted argument list
- // to the overall argument list, using the canonical location, if it exists.
- assert(ArgInputs.count(Input) && "Input cannot be found!");
-
- if (AggArgIt != Group.CanonicalNumberToAggArg.end()) {
- if (OriginalIndex != AggArgIt->second)
- Region.ChangedArgOrder = true;
- Region.ExtractedArgToAgg.insert(
- std::make_pair(OriginalIndex, AggArgIt->second));
- Region.AggArgToExtracted.insert(
- std::make_pair(AggArgIt->second, OriginalIndex));
- } else {
- Group.CanonicalNumberToAggArg.insert(
- std::make_pair(CanonicalNumber, TypeIndex));
- Region.ExtractedArgToAgg.insert(std::make_pair(OriginalIndex, TypeIndex));
- Region.AggArgToExtracted.insert(std::make_pair(TypeIndex, OriginalIndex));
- }
- OriginalIndex++;
- TypeIndex++;
- }
-
- // If the function type definitions for the OutlinableGroup holding the region
- // have not been set, set the length of the inputs here. We should have the
- // same inputs for all of the different regions contained in the
- // OutlinableGroup since they are all structurally similar to one another.
- if (!Group.InputTypesSet) {
- Group.NumAggregateInputs = TypeIndex;
- Group.InputTypesSet = true;
- }
-
- Region.NumExtractedInputs = OriginalIndex;
-}
-
-/// Check if the \p V has any uses outside of the region other than \p PN.
-///
-/// \param V [in] - The value to check.
-/// \param PHILoc [in] - The location in the PHINode of \p V.
-/// \param PN [in] - The PHINode using \p V.
-/// \param Exits [in] - The potential blocks we exit to from the outlined
-/// region.
-/// \param BlocksInRegion [in] - The basic blocks contained in the region.
-/// \returns true if \p V has any use soutside its region other than \p PN.
-static bool outputHasNonPHI(Value *V, unsigned PHILoc, PHINode &PN,
- SmallPtrSet<BasicBlock *, 1> &Exits,
- DenseSet<BasicBlock *> &BlocksInRegion) {
- // We check to see if the value is used by the PHINode from some other
- // predecessor not included in the region. If it is, we make sure
- // to keep it as an output.
- if (any_of(llvm::seq<unsigned>(0, PN.getNumIncomingValues()),
- [PHILoc, &PN, V, &BlocksInRegion](unsigned Idx) {
- return (Idx != PHILoc && V == PN.getIncomingValue(Idx) &&
- !BlocksInRegion.contains(PN.getIncomingBlock(Idx)));
- }))
- return true;
-
- // Check if the value is used by any other instructions outside the region.
- return any_of(V->users(), [&Exits, &BlocksInRegion](User *U) {
- Instruction *I = dyn_cast<Instruction>(U);
- if (!I)
- return false;
-
- // If the use of the item is inside the region, we skip it. Uses
- // inside the region give us useful information about how the item could be
- // used as an output.
- BasicBlock *Parent = I->getParent();
- if (BlocksInRegion.contains(Parent))
- return false;
-
- // If it's not a PHINode then we definitely know the use matters. This
- // output value will not completely combined with another item in a PHINode
- // as it is directly reference by another non-phi instruction
- if (!isa<PHINode>(I))
- return true;
-
- // If we have a PHINode outside one of the exit locations, then it
- // can be considered an outside use as well. If there is a PHINode
- // contained in the Exit where this values use matters, it will be
- // caught when we analyze that PHINode.
- if (!Exits.contains(Parent))
- return true;
-
- return false;
- });
-}
-
-/// Test whether \p CurrentExitFromRegion contains any PhiNodes that should be
-/// considered outputs. A PHINodes is an output when more than one incoming
-/// value has been marked by the CodeExtractor as an output.
-///
-/// \param CurrentExitFromRegion [in] - The block to analyze.
-/// \param PotentialExitsFromRegion [in] - The potential exit blocks from the
-/// region.
-/// \param RegionBlocks [in] - The basic blocks in the region.
-/// \param Outputs [in, out] - The existing outputs for the region, we may add
-/// PHINodes to this as we find that they replace output values.
-/// \param OutputsReplacedByPHINode [out] - A set containing outputs that are
-/// totally replaced by a PHINode.
-/// \param OutputsWithNonPhiUses [out] - A set containing outputs that are used
-/// in PHINodes, but have other uses, and should still be considered outputs.
-static void analyzeExitPHIsForOutputUses(
- BasicBlock *CurrentExitFromRegion,
- SmallPtrSet<BasicBlock *, 1> &PotentialExitsFromRegion,
- DenseSet<BasicBlock *> &RegionBlocks, SetVector<Value *> &Outputs,
- DenseSet<Value *> &OutputsReplacedByPHINode,
- DenseSet<Value *> &OutputsWithNonPhiUses) {
- for (PHINode &PN : CurrentExitFromRegion->phis()) {
- // Find all incoming values from the outlining region.
- SmallVector<unsigned, 2> IncomingVals;
- for (unsigned I = 0, E = PN.getNumIncomingValues(); I < E; ++I)
- if (RegionBlocks.contains(PN.getIncomingBlock(I)))
- IncomingVals.push_back(I);
-
- // Do not process PHI if there are no predecessors from region.
- unsigned NumIncomingVals = IncomingVals.size();
- if (NumIncomingVals == 0)
- continue;
-
- // If there is one predecessor, we mark it as a value that needs to be kept
- // as an output.
- if (NumIncomingVals == 1) {
- Value *V = PN.getIncomingValue(*IncomingVals.begin());
- OutputsWithNonPhiUses.insert(V);
- OutputsReplacedByPHINode.erase(V);
- continue;
- }
-
- // This PHINode will be used as an output value, so we add it to our list.
- Outputs.insert(&PN);
-
- // Not all of the incoming values should be ignored as other inputs and
- // outputs may have uses in outlined region. If they have other uses
- // outside of the single PHINode we should not skip over it.
- for (unsigned Idx : IncomingVals) {
- Value *V = PN.getIncomingValue(Idx);
- if (!isa<Constant>(V) &&
- outputHasNonPHI(V, Idx, PN, PotentialExitsFromRegion, RegionBlocks)) {
- OutputsWithNonPhiUses.insert(V);
- OutputsReplacedByPHINode.erase(V);
- continue;
- }
- if (!OutputsWithNonPhiUses.contains(V))
- OutputsReplacedByPHINode.insert(V);
- }
- }
-}
-
-// Represents the type for the unsigned number denoting the output number for
-// phi node, along with the canonical number for the exit block.
-using ArgLocWithBBCanon = std::pair<unsigned, unsigned>;
-// The list of canonical numbers for the incoming values to a PHINode.
-using CanonList = SmallVector<unsigned, 2>;
-// The pair type representing the set of canonical values being combined in the
-// PHINode, along with the location data for the PHINode.
-using PHINodeData = std::pair<ArgLocWithBBCanon, CanonList>;
-
-/// Encode \p PND as an integer for easy lookup based on the argument location,
-/// the parent BasicBlock canonical numbering, and the canonical numbering of
-/// the values stored in the PHINode.
-///
-/// \param PND - The data to hash.
-/// \returns The hash code of \p PND.
-static hash_code encodePHINodeData(PHINodeData &PND) {
- return llvm::hash_combine(llvm::hash_value(PND.first.first),
- llvm::hash_value(PND.first.second),
- llvm::hash_combine_range(PND.second));
-}
-
-/// Create a special GVN for PHINodes that will be used outside of
-/// the region. We create a hash code based on the Canonical number of the
-/// parent BasicBlock, the canonical numbering of the values stored in the
-/// PHINode and the aggregate argument location. This is used to find whether
-/// this PHINode type has been given a canonical numbering already. If not, we
-/// assign it a value and store it for later use. The value is returned to
-/// identify different output schemes for the set of regions.
-///
-/// \param Region - The region that \p PN is an output for.
-/// \param PN - The PHINode we are analyzing.
-/// \param Blocks - The blocks for the region we are analyzing.
-/// \param AggArgIdx - The argument \p PN will be stored into.
-/// \returns An optional holding the assigned canonical number, or std::nullopt
-/// if there is some attribute of the PHINode blocking it from being used.
-static std::optional<unsigned> getGVNForPHINode(OutlinableRegion &Region,
- PHINode *PN,
- DenseSet<BasicBlock *> &Blocks,
- unsigned AggArgIdx) {
- OutlinableGroup &Group = *Region.Parent;
- IRSimilarityCandidate &Cand = *Region.Candidate;
- BasicBlock *PHIBB = PN->getParent();
- CanonList PHIGVNs;
- Value *Incoming;
- BasicBlock *IncomingBlock;
- for (unsigned Idx = 0, EIdx = PN->getNumIncomingValues(); Idx < EIdx; Idx++) {
- Incoming = PN->getIncomingValue(Idx);
- IncomingBlock = PN->getIncomingBlock(Idx);
- // If the incoming block isn't in the region, we don't have to worry about
- // this incoming value.
- if (!Blocks.contains(IncomingBlock))
- continue;
-
- // If we cannot find a GVN, and the incoming block is included in the region
- // this means that the input to the PHINode is not included in the region we
- // are trying to analyze, meaning, that if it was outlined, we would be
- // adding an extra input. We ignore this case for now, and so ignore the
- // region.
- std::optional<unsigned> OGVN = Cand.getGVN(Incoming);
- if (!OGVN) {
- Region.IgnoreRegion = true;
- return std::nullopt;
- }
-
- // Collect the canonical numbers of the values in the PHINode.
- unsigned GVN = *OGVN;
- OGVN = Cand.getCanonicalNum(GVN);
- assert(OGVN && "No GVN found for incoming value?");
- PHIGVNs.push_back(*OGVN);
-
- // Find the incoming block and use the canonical numbering as well to define
- // the hash for the PHINode.
- OGVN = Cand.getGVN(IncomingBlock);
-
- // If there is no number for the incoming block, it is because we have
- // split the candidate basic blocks. So we use the previous block that it
- // was split from to find the valid global value numbering for the PHINode.
- if (!OGVN) {
- assert(Cand.getStartBB() == IncomingBlock &&
- "Unknown basic block used in exit path PHINode.");
-
- BasicBlock *PrevBlock = nullptr;
- // Iterate over the predecessors to the incoming block of the
- // PHINode, when we find a block that is not contained in the region
- // we know that this is the first block that we split from, and should
- // have a valid global value numbering.
- for (BasicBlock *Pred : predecessors(IncomingBlock))
- if (!Blocks.contains(Pred)) {
- PrevBlock = Pred;
- break;
- }
- assert(PrevBlock && "Expected a predecessor not in the reigon!");
- OGVN = Cand.getGVN(PrevBlock);
- }
- GVN = *OGVN;
- OGVN = Cand.getCanonicalNum(GVN);
- assert(OGVN && "No GVN found for incoming block?");
- PHIGVNs.push_back(*OGVN);
- }
-
- // Now that we have the GVNs for the incoming values, we are going to combine
- // them with the GVN of the incoming bock, and the output location of the
- // PHINode to generate a hash value representing this instance of the PHINode.
- DenseMap<hash_code, unsigned>::iterator GVNToPHIIt;
- DenseMap<unsigned, PHINodeData>::iterator PHIToGVNIt;
- std::optional<unsigned> BBGVN = Cand.getGVN(PHIBB);
- assert(BBGVN && "Could not find GVN for the incoming block!");
-
- BBGVN = Cand.getCanonicalNum(*BBGVN);
- assert(BBGVN && "Could not find canonical number for the incoming block!");
- // Create a pair of the exit block canonical value, and the aggregate
- // argument location, connected to the canonical numbers stored in the
- // PHINode.
- PHINodeData TemporaryPair =
- std::make_pair(std::make_pair(*BBGVN, AggArgIdx), PHIGVNs);
- hash_code PHINodeDataHash = encodePHINodeData(TemporaryPair);
-
- // Look for and create a new entry in our connection between canonical
- // numbers for PHINodes, and the set of objects we just created.
- GVNToPHIIt = Group.GVNsToPHINodeGVN.find(PHINodeDataHash);
- if (GVNToPHIIt == Group.GVNsToPHINodeGVN.end()) {
- bool Inserted = false;
- std::tie(PHIToGVNIt, Inserted) = Group.PHINodeGVNToGVNs.insert(
- std::make_pair(Group.PHINodeGVNTracker, TemporaryPair));
- std::tie(GVNToPHIIt, Inserted) = Group.GVNsToPHINodeGVN.insert(
- std::make_pair(PHINodeDataHash, Group.PHINodeGVNTracker--));
- }
-
- return GVNToPHIIt->second;
-}
-
-/// Create a mapping of the output arguments for the \p Region to the output
-/// arguments of the overall outlined function.
-///
-/// \param [in,out] Region - The region of code to be analyzed.
-/// \param [in] Outputs - The values found by the code extractor.
-static void
-findExtractedOutputToOverallOutputMapping(Module &M, OutlinableRegion &Region,
- SetVector<Value *> &Outputs) {
- OutlinableGroup &Group = *Region.Parent;
- IRSimilarityCandidate &C = *Region.Candidate;
-
- SmallVector<BasicBlock *> BE;
- DenseSet<BasicBlock *> BlocksInRegion;
- C.getBasicBlocks(BlocksInRegion, BE);
-
- // Find the exits to the region.
- SmallPtrSet<BasicBlock *, 1> Exits;
- for (BasicBlock *Block : BE)
- for (BasicBlock *Succ : successors(Block))
- if (!BlocksInRegion.contains(Succ))
- Exits.insert(Succ);
-
- // After determining which blocks exit to PHINodes, we add these PHINodes to
- // the set of outputs to be processed. We also check the incoming values of
- // the PHINodes for whether they should no longer be considered outputs.
- DenseSet<Value *> OutputsReplacedByPHINode;
- DenseSet<Value *> OutputsWithNonPhiUses;
- for (BasicBlock *ExitBB : Exits)
- analyzeExitPHIsForOutputUses(ExitBB, Exits, BlocksInRegion, Outputs,
- OutputsReplacedByPHINode,
- OutputsWithNonPhiUses);
-
- // This counts the argument number in the extracted function.
- unsigned OriginalIndex = Region.NumExtractedInputs;
-
- // This counts the argument number in the overall function.
- unsigned TypeIndex = Group.NumAggregateInputs;
- bool TypeFound;
- DenseSet<unsigned> AggArgsUsed;
-
- // Iterate over the output types and identify if there is an aggregate pointer
- // type whose base type matches the current output type. If there is, we mark
- // that we will use this output register for this value. If not we add another
- // type to the overall argument type list. We also store the GVNs used for
- // stores to identify which values will need to be moved into an special
- // block that holds the stores to the output registers.
- for (Value *Output : Outputs) {
- TypeFound = false;
- // We can do this since it is a result value, and will have a number
- // that is necessarily the same. BUT if in the future, the instructions
- // do not have to be in same order, but are functionally the same, we will
- // have to use a different scheme, as one-to-one correspondence is not
- // guaranteed.
- unsigned ArgumentSize = Group.ArgumentTypes.size();
-
- // If the output is combined in a PHINode, we make sure to skip over it.
- if (OutputsReplacedByPHINode.contains(Output))
- continue;
-
- unsigned AggArgIdx = 0;
- for (unsigned Jdx = TypeIndex; Jdx < ArgumentSize; Jdx++) {
- if (!isa<PointerType>(Group.ArgumentTypes[Jdx]))
- continue;
-
- if (!AggArgsUsed.insert(Jdx).second)
- continue;
-
- TypeFound = true;
- Region.ExtractedArgToAgg.insert(std::make_pair(OriginalIndex, Jdx));
- Region.AggArgToExtracted.insert(std::make_pair(Jdx, OriginalIndex));
- AggArgIdx = Jdx;
- break;
- }
-
- // We were unable to find an unused type in the output type set that matches
- // the output, so we add a pointer type to the argument types of the overall
- // function to handle this output and create a mapping to it.
- if (!TypeFound) {
- Group.ArgumentTypes.push_back(PointerType::get(Output->getContext(),
- M.getDataLayout().getAllocaAddrSpace()));
- // Mark the new pointer type as the last value in the aggregate argument
- // list.
- unsigned ArgTypeIdx = Group.ArgumentTypes.size() - 1;
- AggArgsUsed.insert(ArgTypeIdx);
- Region.ExtractedArgToAgg.insert(
- std::make_pair(OriginalIndex, ArgTypeIdx));
- Region.AggArgToExtracted.insert(
- std::make_pair(ArgTypeIdx, OriginalIndex));
- AggArgIdx = ArgTypeIdx;
- }
-
- // TODO: Adapt to the extra input from the PHINode.
- PHINode *PN = dyn_cast<PHINode>(Output);
-
- std::optional<unsigned> GVN;
- if (PN && !BlocksInRegion.contains(PN->getParent())) {
- // Values outside the region can be combined into PHINode when we
- // have multiple exits. We collect both of these into a list to identify
- // which values are being used in the PHINode. Each list identifies a
- // different PHINode, and a different output. We store the PHINode as it's
- // own canonical value. These canonical values are also dependent on the
- // output argument it is saved to.
-
- // If two PHINodes have the same canonical values, but different aggregate
- // argument locations, then they will have distinct Canonical Values.
- GVN = getGVNForPHINode(Region, PN, BlocksInRegion, AggArgIdx);
- if (!GVN)
- return;
- } else {
- // If we do not have a PHINode we use the global value numbering for the
- // output value, to find the canonical number to add to the set of stored
- // values.
- GVN = C.getGVN(Output);
- GVN = C.getCanonicalNum(*GVN);
- }
-
- // Each region has a potentially unique set of outputs. We save which
- // values are output in a list of canonical values so we can differentiate
- // among the different store schemes.
- Region.GVNStores.push_back(*GVN);
-
- OriginalIndex++;
- TypeIndex++;
- }
-
- // We sort the stored values to make sure that we are not affected by analysis
- // order when determining what combination of items were stored.
- stable_sort(Region.GVNStores);
-}
-
-void IROutliner::findAddInputsOutputs(Module &M, OutlinableRegion &Region,
- DenseSet<unsigned> &NotSame) {
- std::vector<unsigned> Inputs;
- SetVector<Value *> ArgInputs, Outputs;
-
- getCodeExtractorArguments(Region, Inputs, NotSame, OutputMappings, ArgInputs,
- Outputs);
-
- if (Region.IgnoreRegion)
- return;
-
- // Map the inputs found by the CodeExtractor to the arguments found for
- // the overall function.
- findExtractedInputToOverallInputMapping(Region, Inputs, ArgInputs);
-
- // Map the outputs found by the CodeExtractor to the arguments found for
- // the overall function.
- findExtractedOutputToOverallOutputMapping(M, Region, Outputs);
-}
-
-/// Replace the extracted function in the Region with a call to the overall
-/// function constructed from the deduplicated similar regions, replacing and
-/// remapping the values passed to the extracted function as arguments to the
-/// new arguments of the overall function.
-///
-/// \param [in] M - The module to outline from.
-/// \param [in] Region - The regions of extracted code to be replaced with a new
-/// function.
-/// \returns a call instruction with the replaced function.
-CallInst *replaceCalledFunction(Module &M, OutlinableRegion &Region) {
- std::vector<Value *> NewCallArgs;
- DenseMap<unsigned, unsigned>::iterator ArgPair;
-
- OutlinableGroup &Group = *Region.Parent;
- CallInst *Call = Region.Call;
- assert(Call && "Call to replace is nullptr?");
- Function *AggFunc = Group.OutlinedFunction;
- assert(AggFunc && "Function to replace with is nullptr?");
-
- // If the arguments are the same size, there are not values that need to be
- // made into an argument, the argument ordering has not been change, or
- // different output registers to handle. We can simply replace the called
- // function in this case.
- if (!Region.ChangedArgOrder && AggFunc->arg_size() == Call->arg_size()) {
- LLVM_DEBUG(dbgs() << "Replace call to " << *Call << " with call to "
- << *AggFunc << " with same number of arguments\n");
- Call->setCalledFunction(AggFunc);
- return Call;
- }
-
- // We have a different number of arguments than the new function, so
- // we need to use our previously mappings off extracted argument to overall
- // function argument, and constants to overall function argument to create the
- // new argument list.
- for (unsigned AggArgIdx = 0; AggArgIdx < AggFunc->arg_size(); AggArgIdx++) {
-
- if (AggArgIdx == AggFunc->arg_size() - 1 &&
- Group.OutputGVNCombinations.size() > 1) {
- // If we are on the last argument, and we need to differentiate between
- // output blocks, add an integer to the argument list to determine
- // what block to take
- LLVM_DEBUG(dbgs() << "Set switch block argument to "
- << Region.OutputBlockNum << "\n");
- NewCallArgs.push_back(ConstantInt::get(Type::getInt32Ty(M.getContext()),
- Region.OutputBlockNum));
- continue;
- }
-
- ArgPair = Region.AggArgToExtracted.find(AggArgIdx);
- if (ArgPair != Region.AggArgToExtracted.end()) {
- Value *ArgumentValue = Call->getArgOperand(ArgPair->second);
- // If we found the mapping from the extracted function to the overall
- // function, we simply add it to the argument list. We use the same
- // value, it just needs to honor the new order of arguments.
- LLVM_DEBUG(dbgs() << "Setting argument " << AggArgIdx << " to value "
- << *ArgumentValue << "\n");
- NewCallArgs.push_back(ArgumentValue);
- continue;
- }
-
- // If it is a constant, we simply add it to the argument list as a value.
- if (auto It = Region.AggArgToConstant.find(AggArgIdx);
- It != Region.AggArgToConstant.end()) {
- Constant *CST = It->second;
- LLVM_DEBUG(dbgs() << "Setting argument " << AggArgIdx << " to value "
- << *CST << "\n");
- NewCallArgs.push_back(CST);
- continue;
- }
-
- // Add a nullptr value if the argument is not found in the extracted
- // function. If we cannot find a value, it means it is not in use
- // for the region, so we should not pass anything to it.
- LLVM_DEBUG(dbgs() << "Setting argument " << AggArgIdx << " to nullptr\n");
- NewCallArgs.push_back(ConstantPointerNull::get(
- static_cast<PointerType *>(AggFunc->getArg(AggArgIdx)->getType())));
- }
-
- LLVM_DEBUG(dbgs() << "Replace call to " << *Call << " with call to "
- << *AggFunc << " with new set of arguments\n");
- // Create the new call instruction and erase the old one.
- Call = CallInst::Create(AggFunc->getFunctionType(), AggFunc, NewCallArgs, "",
- Call->getIterator());
-
- // It is possible that the call to the outlined function is either the first
- // instruction is in the new block, the last instruction, or both. If either
- // of these is the case, we need to make sure that we replace the instruction
- // in the IRInstructionData struct with the new call.
- CallInst *OldCall = Region.Call;
- if (Region.NewFront->Inst == OldCall)
- Region.NewFront->Inst = Call;
- if (Region.NewBack->Inst == OldCall)
- Region.NewBack->Inst = Call;
-
- // Transfer any debug information.
- Call->setDebugLoc(Region.Call->getDebugLoc());
- // Since our output may determine which branch we go to, we make sure to
- // propagate this new call value through the module.
- OldCall->replaceAllUsesWith(Call);
-
- // Remove the old instruction.
- OldCall->eraseFromParent();
- Region.Call = Call;
-
- // Make sure that the argument in the new function has the SwiftError
- // argument.
- if (Group.SwiftErrorArgument)
- Call->addParamAttr(*Group.SwiftErrorArgument, Attribute::SwiftError);
-
- return Call;
-}
-
-/// Find or create a BasicBlock in the outlined function containing PhiBlocks
-/// for \p RetVal.
-///
-/// \param Group - The OutlinableGroup containing the information about the
-/// overall outlined function.
-/// \param RetVal - The return value or exit option that we are currently
-/// evaluating.
-/// \returns The found or newly created BasicBlock to contain the needed
-/// PHINodes to be used as outputs.
-static BasicBlock *findOrCreatePHIBlock(OutlinableGroup &Group, Value *RetVal) {
- // Find if a PHIBlock exists for this return value already. If it is
- // the first time we are analyzing this, we will not, so we record it.
- auto [PhiBlockForRetVal, Inserted] = Group.PHIBlocks.try_emplace(RetVal);
- if (!Inserted)
- return PhiBlockForRetVal->second;
-
- auto ReturnBlockForRetVal = Group.EndBBs.find(RetVal);
- assert(ReturnBlockForRetVal != Group.EndBBs.end() &&
- "Could not find output value!");
- BasicBlock *ReturnBB = ReturnBlockForRetVal->second;
-
- // If we did not find a block, we create one, and insert it into the
- // overall function and record it.
- BasicBlock *PHIBlock = BasicBlock::Create(ReturnBB->getContext(), "phi_block",
- ReturnBB->getParent());
- PhiBlockForRetVal->second = PHIBlock;
-
- // We replace all branches to the return block in the newly created outlined
- // function to point to the new PHIBlock.
- ReturnBB->replaceAllUsesWith(PHIBlock);
-
- UncondBrInst::Create(ReturnBB, PHIBlock);
-
- return PhiBlockForRetVal->second;
-}
-
-/// For the function call now representing the \p Region, find the passed value
-/// to that call that represents Argument \p A at the call location if the
-/// call has already been replaced with a call to the overall, aggregate
-/// function.
-///
-/// \param A - The Argument to get the passed value for.
-/// \param Region - The extracted Region corresponding to the outlined function.
-/// \returns The Value representing \p A at the call site.
-static Value *
-getPassedArgumentInAlreadyOutlinedFunction(const Argument *A,
- const OutlinableRegion &Region) {
- // If we don't need to adjust the argument number at all (since the call
- // has already been replaced by a call to the overall outlined function)
- // we can just get the specified argument.
- return Region.Call->getArgOperand(A->getArgNo());
-}
-
-/// For the function call now representing the \p Region, find the passed value
-/// to that call that represents Argument \p A at the call location if the
-/// call has only been replaced by the call to the aggregate function.
-///
-/// \param A - The Argument to get the passed value for.
-/// \param Region - The extracted Region corresponding to the outlined function.
-/// \returns The Value representing \p A at the call site.
-static Value *
-getPassedArgumentAndAdjustArgumentLocation(const Argument *A,
- const OutlinableRegion &Region) {
- unsigned ArgNum = A->getArgNo();
-
- // If it is a constant, we can look at our mapping from when we created
- // the outputs to figure out what the constant value is.
- if (auto It = Region.AggArgToConstant.find(ArgNum);
- It != Region.AggArgToConstant.end())
- return It->second;
-
- // If it is not a constant, and we are not looking at the overall function, we
- // need to adjust which argument we are looking at.
- ArgNum = Region.AggArgToExtracted.find(ArgNum)->second;
- return Region.Call->getArgOperand(ArgNum);
-}
-
-/// Find the canonical numbering for the incoming Values into the PHINode \p PN.
-///
-/// \param PN [in] - The PHINode that we are finding the canonical numbers for.
-/// \param Region [in] - The OutlinableRegion containing \p PN.
-/// \param OutputMappings [in] - The mapping of output values from outlined
-/// region to their original values.
-/// \param CanonNums [out] - The canonical numbering for the incoming values to
-/// \p PN paired with their incoming block.
-/// \param ReplacedWithOutlinedCall - A flag to use the extracted function call
-/// of \p Region rather than the overall function's call.
-static void findCanonNumsForPHI(
- PHINode *PN, OutlinableRegion &Region,
- const DenseMap<Value *, Value *> &OutputMappings,
- SmallVector<std::pair<unsigned, BasicBlock *>> &CanonNums,
- bool ReplacedWithOutlinedCall = true) {
- // Iterate over the incoming values.
- for (unsigned Idx = 0, EIdx = PN->getNumIncomingValues(); Idx < EIdx; Idx++) {
- Value *IVal = PN->getIncomingValue(Idx);
- BasicBlock *IBlock = PN->getIncomingBlock(Idx);
- // If we have an argument as incoming value, we need to grab the passed
- // value from the call itself.
- if (Argument *A = dyn_cast<Argument>(IVal)) {
- if (ReplacedWithOutlinedCall)
- IVal = getPassedArgumentInAlreadyOutlinedFunction(A, Region);
- else
- IVal = getPassedArgumentAndAdjustArgumentLocation(A, Region);
- }
-
- // Get the original value if it has been replaced by an output value.
- IVal = findOutputMapping(OutputMappings, IVal);
-
- // Find and add the canonical number for the incoming value.
- std::optional<unsigned> GVN = Region.Candidate->getGVN(IVal);
- assert(GVN && "No GVN for incoming value");
- std::optional<unsigned> CanonNum = Region.Candidate->getCanonicalNum(*GVN);
- assert(CanonNum && "No Canonical Number for GVN");
- CanonNums.push_back(std::make_pair(*CanonNum, IBlock));
- }
-}
-
-/// Find, or add PHINode \p PN to the combined PHINode Block \p OverallPHIBlock
-/// in order to condense the number of instructions added to the outlined
-/// function.
-///
-/// \param PN [in] - The PHINode that we are finding the canonical numbers for.
-/// \param Region [in] - The OutlinableRegion containing \p PN.
-/// \param OverallPhiBlock [in] - The overall PHIBlock we are trying to find
-/// \p PN in.
-/// \param OutputMappings [in] - The mapping of output values from outlined
-/// region to their original values.
-/// \param UsedPHIs [in, out] - The PHINodes in the block that have already been
-/// matched.
-/// \return the newly found or created PHINode in \p OverallPhiBlock.
-static PHINode*
-findOrCreatePHIInBlock(PHINode &PN, OutlinableRegion &Region,
- BasicBlock *OverallPhiBlock,
- const DenseMap<Value *, Value *> &OutputMappings,
- DenseSet<PHINode *> &UsedPHIs) {
- OutlinableGroup &Group = *Region.Parent;
-
-
- // A list of the canonical numbering assigned to each incoming value, paired
- // with the incoming block for the PHINode passed into this function.
- SmallVector<std::pair<unsigned, BasicBlock *>> PNCanonNums;
-
- // We have to use the extracted function since we have merged this region into
- // the overall function yet. We make sure to reassign the argument numbering
- // since it is possible that the argument ordering is different between the
- // functions.
- findCanonNumsForPHI(&PN, Region, OutputMappings, PNCanonNums,
- /* ReplacedWithOutlinedCall = */ false);
-
- OutlinableRegion *FirstRegion = Group.Regions[0];
-
- // A list of the canonical numbering assigned to each incoming value, paired
- // with the incoming block for the PHINode that we are currently comparing
- // the passed PHINode to.
- SmallVector<std::pair<unsigned, BasicBlock *>> CurrentCanonNums;
-
- // Find the Canonical Numbering for each PHINode, if it matches, we replace
- // the uses of the PHINode we are searching for, with the found PHINode.
- for (PHINode &CurrPN : OverallPhiBlock->phis()) {
- // If this PHINode has already been matched to another PHINode to be merged,
- // we skip it.
- if (UsedPHIs.contains(&CurrPN))
- continue;
-
- CurrentCanonNums.clear();
- findCanonNumsForPHI(&CurrPN, *FirstRegion, OutputMappings, CurrentCanonNums,
- /* ReplacedWithOutlinedCall = */ true);
-
- // If the list of incoming values is not the same length, then they cannot
- // match since there is not an analogue for each incoming value.
- if (PNCanonNums.size() != CurrentCanonNums.size())
- continue;
-
- bool FoundMatch = true;
-
- // We compare the canonical value for each incoming value in the passed
- // in PHINode to one already present in the outlined region. If the
- // incoming values do not match, then the PHINodes do not match.
-
- // We also check to make sure that the incoming block matches as well by
- // finding the corresponding incoming block in the combined outlined region
- // for the current outlined region.
- for (unsigned Idx = 0, Edx = PNCanonNums.size(); Idx < Edx; ++Idx) {
- std::pair<unsigned, BasicBlock *> ToCompareTo = CurrentCanonNums[Idx];
- std::pair<unsigned, BasicBlock *> ToAdd = PNCanonNums[Idx];
- if (ToCompareTo.first != ToAdd.first) {
- FoundMatch = false;
- break;
- }
-
- BasicBlock *CorrespondingBlock =
- Region.findCorrespondingBlockIn(*FirstRegion, ToAdd.second);
- assert(CorrespondingBlock && "Found block is nullptr");
- if (CorrespondingBlock != ToCompareTo.second) {
- FoundMatch = false;
- break;
- }
- }
-
- // If all incoming values and branches matched, then we can merge
- // into the found PHINode.
- if (FoundMatch) {
- UsedPHIs.insert(&CurrPN);
- return &CurrPN;
- }
- }
-
- // If we've made it here, it means we weren't able to replace the PHINode, so
- // we must insert it ourselves.
- PHINode *NewPN = cast<PHINode>(PN.clone());
- NewPN->insertBefore(OverallPhiBlock->begin());
- for (unsigned Idx = 0, Edx = NewPN->getNumIncomingValues(); Idx < Edx;
- Idx++) {
- Value *IncomingVal = NewPN->getIncomingValue(Idx);
- BasicBlock *IncomingBlock = NewPN->getIncomingBlock(Idx);
-
- // Find corresponding basic block in the overall function for the incoming
- // block.
- BasicBlock *BlockToUse =
- Region.findCorrespondingBlockIn(*FirstRegion, IncomingBlock);
- NewPN->setIncomingBlock(Idx, BlockToUse);
-
- // If we have an argument we make sure we replace using the argument from
- // the correct function.
- if (Argument *A = dyn_cast<Argument>(IncomingVal)) {
- Value *Val = Group.OutlinedFunction->getArg(A->getArgNo());
- NewPN->setIncomingValue(Idx, Val);
- continue;
- }
-
- // Find the corresponding value in the overall function.
- IncomingVal = findOutputMapping(OutputMappings, IncomingVal);
- Value *Val = Region.findCorrespondingValueIn(*FirstRegion, IncomingVal);
- assert(Val && "Value is nullptr?");
- auto RemappedIt = FirstRegion->RemappedArguments.find(Val);
- if (RemappedIt != FirstRegion->RemappedArguments.end())
- Val = RemappedIt->second;
- NewPN->setIncomingValue(Idx, Val);
- }
- return NewPN;
-}
-
-// Within an extracted function, replace the argument uses of the extracted
-// region with the arguments of the function for an OutlinableGroup.
-//
-/// \param [in] Region - The region of extracted code to be changed.
-/// \param [in,out] OutputBBs - The BasicBlock for the output stores for this
-/// region.
-/// \param [in] FirstFunction - A flag to indicate whether we are using this
-/// function to define the overall outlined function for all the regions, or
-/// if we are operating on one of the following regions.
-static void
-replaceArgumentUses(OutlinableRegion &Region,
- DenseMap<Value *, BasicBlock *> &OutputBBs,
- const DenseMap<Value *, Value *> &OutputMappings,
- bool FirstFunction = false) {
- OutlinableGroup &Group = *Region.Parent;
- assert(Region.ExtractedFunction && "Region has no extracted function?");
-
- Function *DominatingFunction = Region.ExtractedFunction;
- if (FirstFunction)
- DominatingFunction = Group.OutlinedFunction;
- DominatorTree DT(*DominatingFunction);
- DenseSet<PHINode *> UsedPHIs;
-
- for (unsigned ArgIdx = 0; ArgIdx < Region.ExtractedFunction->arg_size();
- ArgIdx++) {
- assert(Region.ExtractedArgToAgg.contains(ArgIdx) &&
- "No mapping from extracted to outlined?");
- unsigned AggArgIdx = Region.ExtractedArgToAgg.find(ArgIdx)->second;
- Argument *AggArg = Group.OutlinedFunction->getArg(AggArgIdx);
- Argument *Arg = Region.ExtractedFunction->getArg(ArgIdx);
- // The argument is an input, so we can simply replace it with the overall
- // argument value
- if (ArgIdx < Region.NumExtractedInputs) {
- LLVM_DEBUG(dbgs() << "Replacing uses of input " << *Arg << " in function "
- << *Region.ExtractedFunction << " with " << *AggArg
- << " in function " << *Group.OutlinedFunction << "\n");
- Arg->replaceAllUsesWith(AggArg);
- Value *V = Region.Call->getArgOperand(ArgIdx);
- Region.RemappedArguments.insert(std::make_pair(V, AggArg));
- continue;
- }
-
- // If we are replacing an output, we place the store value in its own
- // block inside the overall function before replacing the use of the output
- // in the function.
- assert(Arg->hasOneUse() && "Output argument can only have one use");
- User *InstAsUser = Arg->user_back();
- assert(InstAsUser && "User is nullptr!");
-
- Instruction *I = cast<Instruction>(InstAsUser);
- BasicBlock *BB = I->getParent();
- SmallVector<BasicBlock *, 4> Descendants;
- DT.getDescendants(BB, Descendants);
- bool EdgeAdded = false;
- if (Descendants.size() == 0) {
- EdgeAdded = true;
- DT.insertEdge(&DominatingFunction->getEntryBlock(), BB);
- DT.getDescendants(BB, Descendants);
- }
-
- // Iterate over the following blocks, looking for return instructions,
- // if we find one, find the corresponding output block for the return value
- // and move our store instruction there.
- for (BasicBlock *DescendBB : Descendants) {
- ReturnInst *RI = dyn_cast<ReturnInst>(DescendBB->getTerminator());
- if (!RI)
- continue;
- Value *RetVal = RI->getReturnValue();
- auto VBBIt = OutputBBs.find(RetVal);
- assert(VBBIt != OutputBBs.end() && "Could not find output value!");
-
- // If this is storing a PHINode, we must make sure it is included in the
- // overall function.
- StoreInst *SI = cast<StoreInst>(I);
-
- Value *ValueOperand = SI->getValueOperand();
-
- StoreInst *NewI = cast<StoreInst>(I->clone());
- NewI->setDebugLoc(DebugLoc::getDropped());
- BasicBlock *OutputBB = VBBIt->second;
- NewI->insertInto(OutputBB, OutputBB->end());
- LLVM_DEBUG(dbgs() << "Move store for instruction " << *I << " to "
- << *OutputBB << "\n");
-
- // If this is storing a PHINode, we must make sure it is included in the
- // overall function.
- if (!isa<PHINode>(ValueOperand) ||
- Region.Candidate->getGVN(ValueOperand).has_value()) {
- if (FirstFunction)
- continue;
- Value *CorrVal =
- Region.findCorrespondingValueIn(*Group.Regions[0], ValueOperand);
- assert(CorrVal && "Value is nullptr?");
- NewI->setOperand(0, CorrVal);
- continue;
- }
- PHINode *PN = cast<PHINode>(SI->getValueOperand());
- // If it has a value, it was not split by the code extractor, which
- // is what we are looking for.
- if (Region.Candidate->getGVN(PN))
- continue;
-
- // We record the parent block for the PHINode in the Region so that
- // we can exclude it from checks later on.
- Region.PHIBlocks.insert(std::make_pair(RetVal, PN->getParent()));
-
- // If this is the first function, we do not need to worry about mergiing
- // this with any other block in the overall outlined function, so we can
- // just continue.
- if (FirstFunction) {
- BasicBlock *PHIBlock = PN->getParent();
- Group.PHIBlocks.insert(std::make_pair(RetVal, PHIBlock));
- continue;
- }
-
- // We look for the aggregate block that contains the PHINodes leading into
- // this exit path. If we can't find one, we create one.
- BasicBlock *OverallPhiBlock = findOrCreatePHIBlock(Group, RetVal);
-
- // For our PHINode, we find the combined canonical numbering, and
- // attempt to find a matching PHINode in the overall PHIBlock. If we
- // cannot, we copy the PHINode and move it into this new block.
- PHINode *NewPN = findOrCreatePHIInBlock(*PN, Region, OverallPhiBlock,
- OutputMappings, UsedPHIs);
- NewI->setOperand(0, NewPN);
- }
-
- // If we added an edge for basic blocks without a predecessor, we remove it
- // here.
- if (EdgeAdded)
- DT.deleteEdge(&DominatingFunction->getEntryBlock(), BB);
- I->eraseFromParent();
-
- LLVM_DEBUG(dbgs() << "Replacing uses of output " << *Arg << " in function "
- << *Region.ExtractedFunction << " with " << *AggArg
- << " in function " << *Group.OutlinedFunction << "\n");
- Arg->replaceAllUsesWith(AggArg);
- }
-}
-
-/// Within an extracted function, replace the constants that need to be lifted
-/// into arguments with the actual argument.
-///
-/// \param Region [in] - The region of extracted code to be changed.
-void replaceConstants(OutlinableRegion &Region) {
- OutlinableGroup &Group = *Region.Parent;
- Function *OutlinedFunction = Group.OutlinedFunction;
- ValueToValueMapTy VMap;
-
- // Iterate over the constants that need to be elevated into arguments
- for (std::pair<unsigned, Constant *> &Const : Region.AggArgToConstant) {
- unsigned AggArgIdx = Const.first;
- assert(OutlinedFunction && "Overall Function is not defined?");
- Constant *CST = Const.second;
- Argument *Arg = Group.OutlinedFunction->getArg(AggArgIdx);
- // Identify the argument it will be elevated to, and replace instances of
- // that constant in the function.
- VMap[CST] = Arg;
- LLVM_DEBUG(dbgs() << "Replacing uses of constant " << *CST
- << " in function " << *OutlinedFunction << " with "
- << *Arg << '\n');
- }
-
- RemapFunction(*OutlinedFunction, VMap,
- RF_NoModuleLevelChanges | RF_IgnoreMissingLocals);
-}
-
-/// It is possible that there is a basic block that already performs the same
-/// stores. This returns a duplicate block, if it exists
-///
-/// \param OutputBBs [in] the blocks we are looking for a duplicate of.
-/// \param OutputStoreBBs [in] The existing output blocks.
-/// \returns an optional value with the number output block if there is a match.
-std::optional<unsigned> findDuplicateOutputBlock(
- DenseMap<Value *, BasicBlock *> &OutputBBs,
- std::vector<DenseMap<Value *, BasicBlock *>> &OutputStoreBBs) {
-
- bool Mismatch = false;
- unsigned MatchingNum = 0;
- // We compare the new set output blocks to the other sets of output blocks.
- // If they are the same number, and have identical instructions, they are
- // considered to be the same.
- for (DenseMap<Value *, BasicBlock *> &CompBBs : OutputStoreBBs) {
- Mismatch = false;
- for (std::pair<Value *, BasicBlock *> &VToB : CompBBs) {
- auto OutputBBIt = OutputBBs.find(VToB.first);
- if (OutputBBIt == OutputBBs.end()) {
- Mismatch = true;
- break;
- }
-
- BasicBlock *CompBB = VToB.second;
- BasicBlock *OutputBB = OutputBBIt->second;
- if (CompBB->size() - 1 != OutputBB->size()) {
- Mismatch = true;
- break;
- }
-
- BasicBlock::iterator NIt = OutputBB->begin();
- for (Instruction &I : *CompBB) {
- if (isa<UncondBrInst, CondBrInst>(&I))
- continue;
-
- if (!I.isIdenticalTo(&(*NIt))) {
- Mismatch = true;
- break;
- }
-
- NIt++;
- }
- }
-
- if (!Mismatch)
- return MatchingNum;
-
- MatchingNum++;
- }
-
- return std::nullopt;
-}
-
-/// Remove empty output blocks from the outlined region.
-///
-/// \param BlocksToPrune - Mapping of return values output blocks for the \p
-/// Region.
-/// \param Region - The OutlinableRegion we are analyzing.
-static bool
-analyzeAndPruneOutputBlocks(DenseMap<Value *, BasicBlock *> &BlocksToPrune,
- OutlinableRegion &Region) {
- bool AllRemoved = true;
- Value *RetValueForBB;
- BasicBlock *NewBB;
- SmallVector<Value *, 4> ToRemove;
- // Iterate over the output blocks created in the outlined section.
- for (std::pair<Value *, BasicBlock *> &VtoBB : BlocksToPrune) {
- RetValueForBB = VtoBB.first;
- NewBB = VtoBB.second;
-
- // If there are no instructions, we remove it from the module, and also
- // mark the value for removal from the return value to output block mapping.
- if (NewBB->size() == 0) {
- NewBB->eraseFromParent();
- ToRemove.push_back(RetValueForBB);
- continue;
- }
-
- // Mark that we could not remove all the blocks since they were not all
- // empty.
- AllRemoved = false;
- }
-
- // Remove the return value from the mapping.
- for (Value *V : ToRemove)
- BlocksToPrune.erase(V);
-
- // Mark the region as having the no output scheme.
- if (AllRemoved)
- Region.OutputBlockNum = -1;
-
- return AllRemoved;
-}
-
-/// For the outlined section, move needed the StoreInsts for the output
-/// registers into their own block. Then, determine if there is a duplicate
-/// output block already created.
-///
-/// \param [in] OG - The OutlinableGroup of regions to be outlined.
-/// \param [in] Region - The OutlinableRegion that is being analyzed.
-/// \param [in,out] OutputBBs - the blocks that stores for this region will be
-/// placed in.
-/// \param [in] EndBBs - the final blocks of the extracted function.
-/// \param [in] OutputMappings - OutputMappings the mapping of values that have
-/// been replaced by a new output value.
-/// \param [in,out] OutputStoreBBs - The existing output blocks.
-static void alignOutputBlockWithAggFunc(
- OutlinableGroup &OG, OutlinableRegion &Region,
- DenseMap<Value *, BasicBlock *> &OutputBBs,
- DenseMap<Value *, BasicBlock *> &EndBBs,
- const DenseMap<Value *, Value *> &OutputMappings,
- std::vector<DenseMap<Value *, BasicBlock *>> &OutputStoreBBs) {
- // If none of the output blocks have any instructions, this means that we do
- // not have to determine if it matches any of the other output schemes, and we
- // don't have to do anything else.
- if (analyzeAndPruneOutputBlocks(OutputBBs, Region))
- return;
-
- // Determine is there is a duplicate set of blocks.
- std::optional<unsigned> MatchingBB =
- findDuplicateOutputBlock(OutputBBs, OutputStoreBBs);
-
- // If there is, we remove the new output blocks. If it does not,
- // we add it to our list of sets of output blocks.
- if (MatchingBB) {
- LLVM_DEBUG(dbgs() << "Set output block for region in function"
- << Region.ExtractedFunction << " to " << *MatchingBB);
-
- Region.OutputBlockNum = *MatchingBB;
- for (std::pair<Value *, BasicBlock *> &VtoBB : OutputBBs)
- VtoBB.second->eraseFromParent();
- return;
- }
-
- Region.OutputBlockNum = OutputStoreBBs.size();
-
- Value *RetValueForBB;
- BasicBlock *NewBB;
- OutputStoreBBs.push_back(DenseMap<Value *, BasicBlock *>());
- for (std::pair<Value *, BasicBlock *> &VtoBB : OutputBBs) {
- RetValueForBB = VtoBB.first;
- NewBB = VtoBB.second;
- auto VBBIt = EndBBs.find(RetValueForBB);
- LLVM_DEBUG(dbgs() << "Create output block for region in"
- << Region.ExtractedFunction << " to "
- << *NewBB);
- UncondBrInst::Create(VBBIt->second, NewBB);
- OutputStoreBBs.back().insert(std::make_pair(RetValueForBB, NewBB));
- }
-}
-
-/// Takes in a mapping, \p OldMap of ConstantValues to BasicBlocks, sorts keys,
-/// before creating a basic block for each \p NewMap, and inserting into the new
-/// block. Each BasicBlock is named with the scheme "<basename>_<key_idx>".
-///
-/// \param OldMap [in] - The mapping to base the new mapping off of.
-/// \param NewMap [out] - The output mapping using the keys of \p OldMap.
-/// \param ParentFunc [in] - The function to put the new basic block in.
-/// \param BaseName [in] - The start of the BasicBlock names to be appended to
-/// by an index value.
-static void createAndInsertBasicBlocks(DenseMap<Value *, BasicBlock *> &OldMap,
- DenseMap<Value *, BasicBlock *> &NewMap,
- Function *ParentFunc, Twine BaseName) {
- unsigned Idx = 0;
- std::vector<Value *> SortedKeys;
-
- getSortedConstantKeys(SortedKeys, OldMap);
-
- for (Value *RetVal : SortedKeys) {
- BasicBlock *NewBB = BasicBlock::Create(
- ParentFunc->getContext(), Twine(BaseName) + Twine("_") + Twine(Idx++),
- ParentFunc);
- NewMap.insert(std::make_pair(RetVal, NewBB));
- }
-}
-
-/// Create the switch statement for outlined function to differentiate between
-/// all the output blocks.
-///
-/// For the outlined section, determine if an outlined block already exists that
-/// matches the needed stores for the extracted section.
-/// \param [in] M - The module we are outlining from.
-/// \param [in] OG - The group of regions to be outlined.
-/// \param [in] EndBBs - The final blocks of the extracted function.
-/// \param [in,out] OutputStoreBBs - The existing output blocks.
-void createSwitchStatement(
- Module &M, OutlinableGroup &OG, DenseMap<Value *, BasicBlock *> &EndBBs,
- std::vector<DenseMap<Value *, BasicBlock *>> &OutputStoreBBs) {
- // We only need the switch statement if there is more than one store
- // combination, or there is more than one set of output blocks. The first
- // will occur when we store different sets of values for two different
- // regions. The second will occur when we have two outputs that are combined
- // in a PHINode outside of the region in one outlined instance, and are used
- // seaparately in another. This will create the same set of OutputGVNs, but
- // will generate two different output schemes.
- if (OG.OutputGVNCombinations.size() > 1) {
- Function *AggFunc = OG.OutlinedFunction;
- // Create a final block for each different return block.
- DenseMap<Value *, BasicBlock *> ReturnBBs;
- createAndInsertBasicBlocks(OG.EndBBs, ReturnBBs, AggFunc, "final_block");
-
- for (std::pair<Value *, BasicBlock *> &RetBlockPair : ReturnBBs) {
- std::pair<Value *, BasicBlock *> &OutputBlock =
- *OG.EndBBs.find(RetBlockPair.first);
- BasicBlock *ReturnBlock = RetBlockPair.second;
- BasicBlock *EndBB = OutputBlock.second;
- Instruction *Term = EndBB->getTerminator();
- // Move the return value to the final block instead of the original exit
- // stub.
- Term->moveBefore(*ReturnBlock, ReturnBlock->end());
- // Put the switch statement in the old end basic block for the function
- // with a fall through to the new return block.
- LLVM_DEBUG(dbgs() << "Create switch statement in " << *AggFunc << " for "
- << OutputStoreBBs.size() << "\n");
- SwitchInst *SwitchI =
- SwitchInst::Create(AggFunc->getArg(AggFunc->arg_size() - 1),
- ReturnBlock, OutputStoreBBs.size(), EndBB);
-
- unsigned Idx = 0;
- for (DenseMap<Value *, BasicBlock *> &OutputStoreBB : OutputStoreBBs) {
- auto OSBBIt = OutputStoreBB.find(OutputBlock.first);
-
- if (OSBBIt == OutputStoreBB.end())
- continue;
-
- BasicBlock *BB = OSBBIt->second;
- SwitchI->addCase(
- ConstantInt::get(Type::getInt32Ty(M.getContext()), Idx), BB);
- Term = BB->getTerminator();
- Term->setSuccessor(0, ReturnBlock);
- Idx++;
- }
- }
- return;
- }
-
- assert(OutputStoreBBs.size() < 2 && "Different store sets not handled!");
-
- // If there needs to be stores, move them from the output blocks to their
- // corresponding ending block. We do not check that the OutputGVNCombinations
- // is equal to 1 here since that could just been the case where there are 0
- // outputs. Instead, we check whether there is more than one set of output
- // blocks since this is the only case where we would have to move the
- // stores, and erase the extraneous blocks.
- if (OutputStoreBBs.size() == 1) {
- LLVM_DEBUG(dbgs() << "Move store instructions to the end block in "
- << *OG.OutlinedFunction << "\n");
- DenseMap<Value *, BasicBlock *> OutputBlocks = OutputStoreBBs[0];
- for (std::pair<Value *, BasicBlock *> &VBPair : OutputBlocks) {
- auto EndBBIt = EndBBs.find(VBPair.first);
- assert(EndBBIt != EndBBs.end() && "Could not find end block");
- BasicBlock *EndBB = EndBBIt->second;
- BasicBlock *OutputBB = VBPair.second;
- Instruction *Term = OutputBB->getTerminator();
- Term->eraseFromParent();
- Term = EndBB->getTerminator();
- moveBBContents(*OutputBB, *EndBB);
- Term->moveBefore(*EndBB, EndBB->end());
- OutputBB->eraseFromParent();
- }
- }
-}
-
-void IROutliner::fillOverallFunction(
- Module &M, OutlinableGroup &CurrentGroup,
- std::vector<DenseMap<Value *, BasicBlock *>> &OutputStoreBBs,
- std::vector<Function *> &FuncsToRemove) {
- OutlinableRegion *CurrentOS = CurrentGroup.Regions[0];
-
- TargetTransformInfo &TTI = getTTI(*CurrentOS->StartBB->getParent());
-
- // Move first extracted function's instructions into new function.
- LLVM_DEBUG(dbgs() << "Move instructions from "
- << *CurrentOS->ExtractedFunction << " to instruction "
- << *CurrentGroup.OutlinedFunction << "\n");
- moveFunctionData(*CurrentOS->ExtractedFunction,
- *CurrentGroup.OutlinedFunction, CurrentGroup.EndBBs);
-
- // Transfer the attributes from the function to the new function.
- for (Attribute A :
- CurrentOS->ExtractedFunction->getAttributes().getFnAttrs()) {
- if (!TTI.shouldCopyAttributeWhenOutliningFrom(CurrentOS->ExtractedFunction,
- A))
- continue;
-
- CurrentGroup.OutlinedFunction->addFnAttr(A);
- }
-
- // Create a new set of output blocks for the first extracted function.
- DenseMap<Value *, BasicBlock *> NewBBs;
- createAndInsertBasicBlocks(CurrentGroup.EndBBs, NewBBs,
- CurrentGroup.OutlinedFunction, "output_block_0");
- CurrentOS->OutputBlockNum = 0;
-
- replaceArgumentUses(*CurrentOS, NewBBs, OutputMappings, true);
- replaceConstants(*CurrentOS);
-
- // We first identify if any output blocks are empty, if they are we remove
- // them. We then create a branch instruction to the basic block to the return
- // block for the function for each non empty output block.
- if (!analyzeAndPruneOutputBlocks(NewBBs, *CurrentOS)) {
- OutputStoreBBs.push_back(DenseMap<Value *, BasicBlock *>());
- for (std::pair<Value *, BasicBlock *> &VToBB : NewBBs) {
- auto VBBIt = CurrentGroup.EndBBs.find(VToBB.first);
- BasicBlock *EndBB = VBBIt->second;
- UncondBrInst::Create(EndBB, VToBB.second);
- OutputStoreBBs.back().insert(VToBB);
- }
- }
-
- // Replace the call to the extracted function with the outlined function.
- CurrentOS->Call = replaceCalledFunction(M, *CurrentOS);
-
- // We only delete the extracted functions at the end since we may need to
- // reference instructions contained in them for mapping purposes.
- FuncsToRemove.push_back(CurrentOS->ExtractedFunction);
-}
-
-void IROutliner::deduplicateExtractedSections(
- Module &M, OutlinableGroup &CurrentGroup,
- std::vector<Function *> &FuncsToRemove, unsigned &OutlinedFunctionNum) {
- createFunction(M, CurrentGroup, OutlinedFunctionNum);
-
- std::vector<DenseMap<Value *, BasicBlock *>> OutputStoreBBs;
-
- OutlinableRegion *CurrentOS;
-
- fillOverallFunction(M, CurrentGroup, OutputStoreBBs, FuncsToRemove);
-
- for (unsigned Idx = 1; Idx < CurrentGroup.Regions.size(); Idx++) {
- CurrentOS = CurrentGroup.Regions[Idx];
- AttributeFuncs::mergeAttributesForOutlining(*CurrentGroup.OutlinedFunction,
- *CurrentOS->ExtractedFunction);
-
- // Create a set of BasicBlocks, one for each return block, to hold the
- // needed store instructions.
- DenseMap<Value *, BasicBlock *> NewBBs;
- createAndInsertBasicBlocks(CurrentGroup.EndBBs, NewBBs,
- CurrentGroup.OutlinedFunction,
- "output_block_" + Twine(Idx));
- replaceArgumentUses(*CurrentOS, NewBBs, OutputMappings);
- alignOutputBlockWithAggFunc(CurrentGroup, *CurrentOS, NewBBs,
- CurrentGroup.EndBBs, OutputMappings,
- OutputStoreBBs);
-
- CurrentOS->Call = replaceCalledFunction(M, *CurrentOS);
- FuncsToRemove.push_back(CurrentOS->ExtractedFunction);
- }
-
- // Create a switch statement to handle the different output schemes.
- createSwitchStatement(M, CurrentGroup, CurrentGroup.EndBBs, OutputStoreBBs);
-
- OutlinedFunctionNum++;
-}
-
-/// Checks that the next instruction in the InstructionDataList matches the
-/// next instruction in the module. If they do not, there could be the
-/// possibility that extra code has been inserted, and we must ignore it.
-///
-/// \param ID - The IRInstructionData to check the next instruction of.
-/// \returns true if the InstructionDataList and actual instruction match.
-static bool nextIRInstructionDataMatchesNextInst(IRInstructionData &ID) {
- // We check if there is a discrepancy between the InstructionDataList
- // and the actual next instruction in the module. If there is, it means
- // that an extra instruction was added, likely by the CodeExtractor.
-
- // Since we do not have any similarity data about this particular
- // instruction, we cannot confidently outline it, and must discard this
- // candidate.
- IRInstructionDataList::iterator NextIDIt = std::next(ID.getIterator());
- Instruction *NextIDLInst = NextIDIt->Inst;
- Instruction *NextModuleInst = nullptr;
- if (!ID.Inst->isTerminator())
- NextModuleInst = ID.Inst->getNextNode();
- else if (NextIDLInst != nullptr)
- NextModuleInst = &*NextIDIt->Inst->getParent()->begin();
-
- if (NextIDLInst && NextIDLInst != NextModuleInst)
- return false;
-
- return true;
-}
-
-bool IROutliner::isCompatibleWithAlreadyOutlinedCode(
- const OutlinableRegion &Region) {
- IRSimilarityCandidate *IRSC = Region.Candidate;
- unsigned StartIdx = IRSC->getStartIdx();
- unsigned EndIdx = IRSC->getEndIdx();
-
- // A check to make sure that we are not about to attempt to outline something
- // that has already been outlined.
- for (unsigned Idx = StartIdx; Idx <= EndIdx; Idx++)
- if (Outlined.contains(Idx))
- return false;
-
- // We check if the recorded instruction matches the actual next instruction,
- // if it does not, we fix it in the InstructionDataList.
- if (!Region.Candidate->backInstruction()->isTerminator()) {
- Instruction *NewEndInst =
- Region.Candidate->backInstruction()->getNextNode();
- assert(NewEndInst && "Next instruction is a nullptr?");
- if (Region.Candidate->end()->Inst != NewEndInst) {
- IRInstructionDataList *IDL = Region.Candidate->front()->IDL;
- IRInstructionData *NewEndIRID = new (InstDataAllocator.Allocate())
- IRInstructionData(*NewEndInst,
- InstructionClassifier.visit(*NewEndInst), *IDL);
-
- // Insert the first IRInstructionData of the new region after the
- // last IRInstructionData of the IRSimilarityCandidate.
- IDL->insert(Region.Candidate->end(), *NewEndIRID);
- }
- }
-
- return none_of(*IRSC, [this](IRInstructionData &ID) {
- if (!nextIRInstructionDataMatchesNextInst(ID))
- return true;
-
- return !this->InstructionClassifier.visit(ID.Inst);
- });
-}
-
-void IROutliner::pruneIncompatibleRegions(
- std::vector<IRSimilarityCandidate> &CandidateVec,
- OutlinableGroup &CurrentGroup) {
- bool PreviouslyOutlined;
-
- // Sort from beginning to end, so the IRSimilarityCandidates are in order.
- stable_sort(CandidateVec, [](const IRSimilarityCandidate &LHS,
- const IRSimilarityCandidate &RHS) {
- return LHS.getStartIdx() < RHS.getStartIdx();
- });
-
- IRSimilarityCandidate &FirstCandidate = CandidateVec[0];
- // Since outlining a call and a branch instruction will be the same as only
- // outlinining a call instruction, we ignore it as a space saving.
- if (FirstCandidate.getLength() == 2) {
- if (isa<CallInst>(FirstCandidate.front()->Inst) &&
- isa<UncondBrInst, CondBrInst>(FirstCandidate.back()->Inst))
- return;
- }
-
- unsigned CurrentEndIdx = 0;
- for (IRSimilarityCandidate &IRSC : CandidateVec) {
- PreviouslyOutlined = false;
- unsigned StartIdx = IRSC.getStartIdx();
- unsigned EndIdx = IRSC.getEndIdx();
- const Function &FnForCurrCand = *IRSC.getFunction();
-
- for (unsigned Idx = StartIdx; Idx <= EndIdx; Idx++)
- if (Outlined.contains(Idx)) {
- PreviouslyOutlined = true;
- break;
- }
-
- if (PreviouslyOutlined)
- continue;
-
- // Check over the instructions, and if the basic block has its address
- // taken for use somewhere else, we do not outline that block.
- bool BBHasAddressTaken = any_of(IRSC, [](IRInstructionData &ID){
- return ID.Inst->getParent()->hasAddressTaken();
- });
-
- if (BBHasAddressTaken)
- continue;
-
- if (FnForCurrCand.hasOptNone())
- continue;
-
- if (FnForCurrCand.hasFnAttribute(Attribute::NoOutline)) {
- LLVM_DEBUG({
- dbgs() << "... Skipping function with nooutline attribute: "
- << FnForCurrCand.getName() << "\n";
- });
- continue;
- }
-
- if (IRSC.front()->Inst->getFunction()->hasLinkOnceODRLinkage() &&
- !OutlineFromLinkODRs)
- continue;
-
- // Greedily prune out any regions that will overlap with already chosen
- // regions.
- if (CurrentEndIdx != 0 && StartIdx <= CurrentEndIdx)
- continue;
-
- bool BadInst = any_of(IRSC, [this](IRInstructionData &ID) {
- if (!nextIRInstructionDataMatchesNextInst(ID))
- return true;
-
- return !this->InstructionClassifier.visit(ID.Inst);
- });
-
- if (BadInst)
- continue;
-
- OutlinableRegion *OS = new (RegionAllocator.Allocate())
- OutlinableRegion(IRSC, CurrentGroup);
- CurrentGroup.Regions.push_back(OS);
-
- CurrentEndIdx = EndIdx;
- }
-}
-
-InstructionCost
-IROutliner::findBenefitFromAllRegions(OutlinableGroup &CurrentGroup) {
- InstructionCost RegionBenefit = 0;
- for (OutlinableRegion *Region : CurrentGroup.Regions) {
- TargetTransformInfo &TTI = getTTI(*Region->StartBB->getParent());
- // We add the number of instructions in the region to the benefit as an
- // estimate as to how much will be removed.
- RegionBenefit += Region->getBenefit(TTI);
- LLVM_DEBUG(dbgs() << "Adding: " << RegionBenefit
- << " saved instructions to overfall benefit.\n");
- }
-
- return RegionBenefit;
-}
-
-/// For the \p OutputCanon number passed in find the value represented by this
-/// canonical number. If it is from a PHINode, we pick the first incoming
-/// value and return that Value instead.
-///
-/// \param Region - The OutlinableRegion to get the Value from.
-/// \param OutputCanon - The canonical number to find the Value from.
-/// \returns The Value represented by a canonical number \p OutputCanon in \p
-/// Region.
-static Value *findOutputValueInRegion(OutlinableRegion &Region,
- unsigned OutputCanon) {
- OutlinableGroup &CurrentGroup = *Region.Parent;
- // If the value is greater than the value in the tracker, we have a
- // PHINode and will instead use one of the incoming values to find the
- // type.
- if (OutputCanon > CurrentGroup.PHINodeGVNTracker) {
- auto It = CurrentGroup.PHINodeGVNToGVNs.find(OutputCanon);
- assert(It != CurrentGroup.PHINodeGVNToGVNs.end() &&
- "Could not find GVN set for PHINode number!");
- assert(It->second.second.size() > 0 && "PHINode does not have any values!");
- OutputCanon = *It->second.second.begin();
- }
- std::optional<unsigned> OGVN =
- Region.Candidate->fromCanonicalNum(OutputCanon);
- assert(OGVN && "Could not find GVN for Canonical Number?");
- std::optional<Value *> OV = Region.Candidate->fromGVN(*OGVN);
- assert(OV && "Could not find value for GVN?");
- return *OV;
-}
-
-InstructionCost
-IROutliner::findCostOutputReloads(OutlinableGroup &CurrentGroup) {
- InstructionCost OverallCost = 0;
- for (OutlinableRegion *Region : CurrentGroup.Regions) {
- TargetTransformInfo &TTI = getTTI(*Region->StartBB->getParent());
-
- // Each output incurs a load after the call, so we add that to the cost.
- for (unsigned OutputCanon : Region->GVNStores) {
- Value *V = findOutputValueInRegion(*Region, OutputCanon);
- InstructionCost LoadCost =
- TTI.getMemoryOpCost(Instruction::Load, V->getType(), Align(1), 0,
- TargetTransformInfo::TCK_CodeSize);
-
- LLVM_DEBUG(dbgs() << "Adding: " << LoadCost
- << " instructions to cost for output of type "
- << *V->getType() << "\n");
- OverallCost += LoadCost;
- }
- }
-
- return OverallCost;
-}
-
-/// Find the extra instructions needed to handle any output values for the
-/// region.
-///
-/// \param [in] M - The Module to outline from.
-/// \param [in] CurrentGroup - The collection of OutlinableRegions to analyze.
-/// \param [in] TTI - The TargetTransformInfo used to collect information for
-/// new instruction costs.
-/// \returns the additional cost to handle the outputs.
-static InstructionCost findCostForOutputBlocks(Module &M,
- OutlinableGroup &CurrentGroup,
- TargetTransformInfo &TTI) {
- InstructionCost OutputCost = 0;
- unsigned NumOutputBranches = 0;
-
- OutlinableRegion &FirstRegion = *CurrentGroup.Regions[0];
- IRSimilarityCandidate &Candidate = *CurrentGroup.Regions[0]->Candidate;
- DenseSet<BasicBlock *> CandidateBlocks;
- Candidate.getBasicBlocks(CandidateBlocks);
-
- // Count the number of different output branches that point to blocks outside
- // of the region.
- DenseSet<BasicBlock *> FoundBlocks;
- for (IRInstructionData &ID : Candidate) {
- if (!isa<UncondBrInst, CondBrInst>(ID.Inst))
- continue;
-
- for (Value *V : ID.OperVals) {
- BasicBlock *BB = static_cast<BasicBlock *>(V);
- if (!CandidateBlocks.contains(BB) && FoundBlocks.insert(BB).second)
- NumOutputBranches++;
- }
- }
-
- CurrentGroup.BranchesToOutside = NumOutputBranches;
-
- for (const ArrayRef<unsigned> &OutputUse :
- CurrentGroup.OutputGVNCombinations) {
- for (unsigned OutputCanon : OutputUse) {
- Value *V = findOutputValueInRegion(FirstRegion, OutputCanon);
- InstructionCost StoreCost =
- TTI.getMemoryOpCost(Instruction::Load, V->getType(), Align(1), 0,
- TargetTransformInfo::TCK_CodeSize);
-
- // An instruction cost is added for each store set that needs to occur for
- // various output combinations inside the function, plus a branch to
- // return to the exit block.
- LLVM_DEBUG(dbgs() << "Adding: " << StoreCost
- << " instructions to cost for output of type "
- << *V->getType() << "\n");
- OutputCost += StoreCost * NumOutputBranches;
- }
-
- InstructionCost BranchCost = TTI.getCFInstrCost(
- Instruction::UncondBr, TargetTransformInfo::TCK_CodeSize);
- LLVM_DEBUG(dbgs() << "Adding " << BranchCost << " to the current cost for"
- << " a branch instruction\n");
- OutputCost += BranchCost * NumOutputBranches;
- }
-
- // If there is more than one output scheme, we must have a comparison and
- // branch for each different item in the switch statement.
- if (CurrentGroup.OutputGVNCombinations.size() > 1) {
- InstructionCost ComparisonCost = TTI.getCmpSelInstrCost(
- Instruction::ICmp, Type::getInt32Ty(M.getContext()),
- Type::getInt32Ty(M.getContext()), CmpInst::BAD_ICMP_PREDICATE,
- TargetTransformInfo::TCK_CodeSize);
- InstructionCost BranchCost = TTI.getCFInstrCost(
- Instruction::CondBr, TargetTransformInfo::TCK_CodeSize);
-
- unsigned DifferentBlocks = CurrentGroup.OutputGVNCombinations.size();
- InstructionCost TotalCost = ComparisonCost * BranchCost * DifferentBlocks;
-
- LLVM_DEBUG(dbgs() << "Adding: " << TotalCost
- << " instructions for each switch case for each different"
- << " output path in a function\n");
- OutputCost += TotalCost * NumOutputBranches;
- }
-
- return OutputCost;
-}
-
-void IROutliner::findCostBenefit(Module &M, OutlinableGroup &CurrentGroup) {
- InstructionCost RegionBenefit = findBenefitFromAllRegions(CurrentGroup);
- CurrentGroup.Benefit += RegionBenefit;
- LLVM_DEBUG(dbgs() << "Current Benefit: " << CurrentGroup.Benefit << "\n");
-
- InstructionCost OutputReloadCost = findCostOutputReloads(CurrentGroup);
- CurrentGroup.Cost += OutputReloadCost;
- LLVM_DEBUG(dbgs() << "Current Cost: " << CurrentGroup.Cost << "\n");
-
- InstructionCost AverageRegionBenefit =
- RegionBenefit / CurrentGroup.Regions.size();
- unsigned OverallArgumentNum = CurrentGroup.ArgumentTypes.size();
- unsigned NumRegions = CurrentGroup.Regions.size();
- TargetTransformInfo &TTI =
- getTTI(*CurrentGroup.Regions[0]->Candidate->getFunction());
-
- // We add one region to the cost once, to account for the instructions added
- // inside of the newly created function.
- LLVM_DEBUG(dbgs() << "Adding: " << AverageRegionBenefit
- << " instructions to cost for body of new function.\n");
- CurrentGroup.Cost += AverageRegionBenefit;
- LLVM_DEBUG(dbgs() << "Current Cost: " << CurrentGroup.Cost << "\n");
-
- // For each argument, we must add an instruction for loading the argument
- // out of the register and into a value inside of the newly outlined function.
- LLVM_DEBUG(dbgs() << "Adding: " << OverallArgumentNum
- << " instructions to cost for each argument in the new"
- << " function.\n");
- CurrentGroup.Cost +=
- OverallArgumentNum * TargetTransformInfo::TCC_Basic;
- LLVM_DEBUG(dbgs() << "Current Cost: " << CurrentGroup.Cost << "\n");
-
- // Each argument needs to either be loaded into a register or onto the stack.
- // Some arguments will only be loaded into the stack once the argument
- // registers are filled.
- LLVM_DEBUG(dbgs() << "Adding: " << OverallArgumentNum
- << " instructions to cost for each argument in the new"
- << " function " << NumRegions << " times for the "
- << "needed argument handling at the call site.\n");
- CurrentGroup.Cost +=
- 2 * OverallArgumentNum * TargetTransformInfo::TCC_Basic * NumRegions;
- LLVM_DEBUG(dbgs() << "Current Cost: " << CurrentGroup.Cost << "\n");
-
- CurrentGroup.Cost += findCostForOutputBlocks(M, CurrentGroup, TTI);
- LLVM_DEBUG(dbgs() << "Current Cost: " << CurrentGroup.Cost << "\n");
-}
-
-void IROutliner::updateOutputMapping(OutlinableRegion &Region,
- ArrayRef<Value *> Outputs,
- LoadInst *LI) {
- // For and load instructions following the call
- Value *Operand = LI->getPointerOperand();
- std::optional<unsigned> OutputIdx;
- // Find if the operand it is an output register.
- for (unsigned ArgIdx = Region.NumExtractedInputs;
- ArgIdx < Region.Call->arg_size(); ArgIdx++) {
- if (Operand == Region.Call->getArgOperand(ArgIdx)) {
- OutputIdx = ArgIdx - Region.NumExtractedInputs;
- break;
- }
- }
-
- // If we found an output register, place a mapping of the new value
- // to the original in the mapping.
- if (!OutputIdx)
- return;
-
- auto It = OutputMappings.find(Outputs[*OutputIdx]);
- if (It == OutputMappings.end()) {
- LLVM_DEBUG(dbgs() << "Mapping extracted output " << *LI << " to "
- << *Outputs[*OutputIdx] << "\n");
- OutputMappings.insert(std::make_pair(LI, Outputs[*OutputIdx]));
- } else {
- Value *Orig = It->second;
- LLVM_DEBUG(dbgs() << "Mapping extracted output " << *Orig << " to "
- << *Outputs[*OutputIdx] << "\n");
- OutputMappings.insert(std::make_pair(LI, Orig));
- }
-}
-
-bool IROutliner::extractSection(OutlinableRegion &Region) {
- SetVector<Value *> ArgInputs, Outputs;
- assert(Region.StartBB && "StartBB for the OutlinableRegion is nullptr!");
- BasicBlock *InitialStart = Region.StartBB;
- Function *OrigF = Region.StartBB->getParent();
- CodeExtractorAnalysisCache CEAC(*OrigF);
- Region.ExtractedFunction =
- Region.CE->extractCodeRegion(CEAC, ArgInputs, Outputs);
-
- // If the extraction was successful, find the BasicBlock, and reassign the
- // OutlinableRegion blocks
- if (!Region.ExtractedFunction) {
- LLVM_DEBUG(dbgs() << "CodeExtractor failed to outline " << Region.StartBB
- << "\n");
- Region.reattachCandidate();
- return false;
- }
-
- // Get the block containing the called branch, and reassign the blocks as
- // necessary. If the original block still exists, it is because we ended on
- // a branch instruction, and so we move the contents into the block before
- // and assign the previous block correctly.
- User *InstAsUser = Region.ExtractedFunction->user_back();
- BasicBlock *RewrittenBB = cast<Instruction>(InstAsUser)->getParent();
- Region.PrevBB = RewrittenBB->getSinglePredecessor();
- assert(Region.PrevBB && "PrevBB is nullptr?");
- if (Region.PrevBB == InitialStart) {
- BasicBlock *NewPrev = InitialStart->getSinglePredecessor();
- Instruction *BI = NewPrev->getTerminator();
- BI->eraseFromParent();
- moveBBContents(*InitialStart, *NewPrev);
- Region.PrevBB = NewPrev;
- InitialStart->eraseFromParent();
- }
-
- Region.StartBB = RewrittenBB;
- Region.EndBB = RewrittenBB;
-
- // The sequences of outlinable regions has now changed. We must fix the
- // IRInstructionDataList for consistency. Although they may not be illegal
- // instructions, they should not be compared with anything else as they
- // should not be outlined in this round. So marking these as illegal is
- // allowed.
- IRInstructionDataList *IDL = Region.Candidate->front()->IDL;
- Instruction *BeginRewritten = &*RewrittenBB->begin();
- Instruction *EndRewritten = &*RewrittenBB->begin();
- Region.NewFront = new (InstDataAllocator.Allocate()) IRInstructionData(
- *BeginRewritten, InstructionClassifier.visit(*BeginRewritten), *IDL);
- Region.NewBack = new (InstDataAllocator.Allocate()) IRInstructionData(
- *EndRewritten, InstructionClassifier.visit(*EndRewritten), *IDL);
-
- // Insert the first IRInstructionData of the new region in front of the
- // first IRInstructionData of the IRSimilarityCandidate.
- IDL->insert(Region.Candidate->begin(), *Region.NewFront);
- // Insert the first IRInstructionData of the new region after the
- // last IRInstructionData of the IRSimilarityCandidate.
- IDL->insert(Region.Candidate->end(), *Region.NewBack);
- // Remove the IRInstructionData from the IRSimilarityCandidate.
- IDL->erase(Region.Candidate->begin(), std::prev(Region.Candidate->end()));
-
- assert(RewrittenBB != nullptr &&
- "Could not find a predecessor after extraction!");
-
- // Iterate over the new set of instructions to find the new call
- // instruction.
- for (Instruction &I : *RewrittenBB)
- if (CallInst *CI = dyn_cast<CallInst>(&I)) {
- if (Region.ExtractedFunction == CI->getCalledFunction())
- Region.Call = CI;
- } else if (LoadInst *LI = dyn_cast<LoadInst>(&I))
- updateOutputMapping(Region, Outputs.getArrayRef(), LI);
- Region.reattachCandidate();
- return true;
-}
-
-unsigned IROutliner::doOutline(Module &M) {
- // Find the possible similarity sections.
- InstructionClassifier.EnableBranches = !DisableBranches;
- InstructionClassifier.EnableIndirectCalls = !DisableIndirectCalls;
- InstructionClassifier.EnableIntrinsics = !DisableIntrinsics;
-
- IRSimilarityIdentifier &Identifier = getIRSI(M);
- SimilarityGroupList &SimilarityCandidates = *Identifier.getSimilarity();
-
- // Sort them by size of extracted sections
- unsigned OutlinedFunctionNum = 0;
- // If we only have one SimilarityGroup in SimilarityCandidates, we do not have
- // to sort them by the potential number of instructions to be outlined
- if (SimilarityCandidates.size() > 1)
- llvm::stable_sort(SimilarityCandidates,
- [](const std::vector<IRSimilarityCandidate> &LHS,
- const std::vector<IRSimilarityCandidate> &RHS) {
- return LHS[0].getLength() * LHS.size() >
- RHS[0].getLength() * RHS.size();
- });
- // Creating OutlinableGroups for each SimilarityCandidate to be used in
- // each of the following for loops to avoid making an allocator.
- std::vector<OutlinableGroup> PotentialGroups(SimilarityCandidates.size());
-
- DenseSet<unsigned> NotSame;
- std::vector<OutlinableGroup *> NegativeCostGroups;
- std::vector<OutlinableRegion *> OutlinedRegions;
- // Iterate over the possible sets of similarity.
- unsigned PotentialGroupIdx = 0;
- for (SimilarityGroup &CandidateVec : SimilarityCandidates) {
- OutlinableGroup &CurrentGroup = PotentialGroups[PotentialGroupIdx++];
-
- // Remove entries that were previously outlined
- pruneIncompatibleRegions(CandidateVec, CurrentGroup);
-
- // We pruned the number of regions to 0 to 1, meaning that it's not worth
- // trying to outlined since there is no compatible similar instance of this
- // code.
- if (CurrentGroup.Regions.size() < 2)
- continue;
-
- // Determine if there are any values that are the same constant throughout
- // each section in the set.
- NotSame.clear();
- CurrentGroup.findSameConstants(NotSame);
-
- if (CurrentGroup.IgnoreGroup)
- continue;
-
- // Create a CodeExtractor for each outlinable region. Identify inputs and
- // outputs for each section using the code extractor and create the argument
- // types for the Aggregate Outlining Function.
- OutlinedRegions.clear();
- for (OutlinableRegion *OS : CurrentGroup.Regions) {
- // Break the outlinable region out of its parent BasicBlock into its own
- // BasicBlocks (see function implementation).
- OS->splitCandidate();
-
- // There's a chance that when the region is split, extra instructions are
- // added to the region. This makes the region no longer viable
- // to be split, so we ignore it for outlining.
- if (!OS->CandidateSplit)
- continue;
-
- SmallVector<BasicBlock *> BE;
- DenseSet<BasicBlock *> BlocksInRegion;
- OS->Candidate->getBasicBlocks(BlocksInRegion, BE);
- OS->CE = new (ExtractorAllocator.Allocate())
- CodeExtractor(BE, nullptr, false, nullptr, nullptr, nullptr, false,
- false, nullptr, {}, "outlined");
- findAddInputsOutputs(M, *OS, NotSame);
- if (!OS->IgnoreRegion)
- OutlinedRegions.push_back(OS);
-
- // We recombine the blocks together now that we have gathered all the
- // needed information.
- OS->reattachCandidate();
- }
-
- CurrentGroup.Regions = std::move(OutlinedRegions);
-
- if (CurrentGroup.Regions.empty())
- continue;
-
- CurrentGroup.collectGVNStoreSets(M);
-
- if (CostModel)
- findCostBenefit(M, CurrentGroup);
-
- // If we are adhering to the cost model, skip those groups where the cost
- // outweighs the benefits.
- if (CurrentGroup.Cost >= CurrentGroup.Benefit && CostModel) {
- OptimizationRemarkEmitter &ORE =
- getORE(*CurrentGroup.Regions[0]->Candidate->getFunction());
- ORE.emit([&]() {
- IRSimilarityCandidate *C = CurrentGroup.Regions[0]->Candidate;
- OptimizationRemarkMissed R(DEBUG_TYPE, "WouldNotDecreaseSize",
- C->frontInstruction());
- R << "did not outline "
- << ore::NV(std::to_string(CurrentGroup.Regions.size()))
- << " regions due to estimated increase of "
- << ore::NV("InstructionIncrease",
- CurrentGroup.Cost - CurrentGroup.Benefit)
- << " instructions at locations ";
- interleave(
- CurrentGroup.Regions.begin(), CurrentGroup.Regions.end(),
- [&R](OutlinableRegion *Region) {
- R << ore::NV(
- "DebugLoc",
- Region->Candidate->frontInstruction()->getDebugLoc());
- },
- [&R]() { R << " "; });
- return R;
- });
- continue;
- }
-
- NegativeCostGroups.push_back(&CurrentGroup);
- }
-
- ExtractorAllocator.DestroyAll();
-
- if (NegativeCostGroups.size() > 1)
- stable_sort(NegativeCostGroups,
- [](const OutlinableGroup *LHS, const OutlinableGroup *RHS) {
- return LHS->Benefit - LHS->Cost > RHS->Benefit - RHS->Cost;
- });
-
- std::vector<Function *> FuncsToRemove;
- for (OutlinableGroup *CG : NegativeCostGroups) {
- OutlinableGroup &CurrentGroup = *CG;
-
- OutlinedRegions.clear();
- for (OutlinableRegion *Region : CurrentGroup.Regions) {
- // We check whether our region is compatible with what has already been
- // outlined, and whether we need to ignore this item.
- if (!isCompatibleWithAlreadyOutlinedCode(*Region))
- continue;
- OutlinedRegions.push_back(Region);
- }
-
- if (OutlinedRegions.size() < 2)
- continue;
-
- // Reestimate the cost and benefit of the OutlinableGroup. Continue only if
- // we are still outlining enough regions to make up for the added cost.
- CurrentGroup.Regions = std::move(OutlinedRegions);
- if (CostModel) {
- CurrentGroup.Benefit = 0;
- CurrentGroup.Cost = 0;
- findCostBenefit(M, CurrentGroup);
- if (CurrentGroup.Cost >= CurrentGroup.Benefit)
- continue;
- }
- OutlinedRegions.clear();
- for (OutlinableRegion *Region : CurrentGroup.Regions) {
- Region->splitCandidate();
- if (!Region->CandidateSplit)
- continue;
- OutlinedRegions.push_back(Region);
- }
-
- CurrentGroup.Regions = std::move(OutlinedRegions);
- if (CurrentGroup.Regions.size() < 2) {
- for (OutlinableRegion *R : CurrentGroup.Regions)
- R->reattachCandidate();
- continue;
- }
-
- LLVM_DEBUG(dbgs() << "Outlining regions with cost " << CurrentGroup.Cost
- << " and benefit " << CurrentGroup.Benefit << "\n");
-
- // Create functions out of all the sections, and mark them as outlined.
- OutlinedRegions.clear();
- for (OutlinableRegion *OS : CurrentGroup.Regions) {
- SmallVector<BasicBlock *> BE;
- DenseSet<BasicBlock *> BlocksInRegion;
- OS->Candidate->getBasicBlocks(BlocksInRegion, BE);
- OS->CE = new (ExtractorAllocator.Allocate())
- CodeExtractor(BE, nullptr, false, nullptr, nullptr, nullptr, false,
- false, nullptr, {}, "outlined");
- bool FunctionOutlined = extractSection(*OS);
- if (FunctionOutlined) {
- unsigned StartIdx = OS->Candidate->getStartIdx();
- unsigned EndIdx = OS->Candidate->getEndIdx();
- for (unsigned Idx = StartIdx; Idx <= EndIdx; Idx++)
- Outlined.insert(Idx);
-
- OutlinedRegions.push_back(OS);
- }
- }
-
- LLVM_DEBUG(dbgs() << "Outlined " << OutlinedRegions.size()
- << " with benefit " << CurrentGroup.Benefit
- << " and cost " << CurrentGroup.Cost << "\n");
-
- CurrentGroup.Regions = std::move(OutlinedRegions);
-
- if (CurrentGroup.Regions.empty())
- continue;
-
- OptimizationRemarkEmitter &ORE =
- getORE(*CurrentGroup.Regions[0]->Call->getFunction());
- ORE.emit([&]() {
- IRSimilarityCandidate *C = CurrentGroup.Regions[0]->Candidate;
- OptimizationRemark R(DEBUG_TYPE, "Outlined", C->front()->Inst);
- R << "outlined " << ore::NV(std::to_string(CurrentGroup.Regions.size()))
- << " regions with decrease of "
- << ore::NV("Benefit", CurrentGroup.Benefit - CurrentGroup.Cost)
- << " instructions at locations ";
- interleave(
- CurrentGroup.Regions.begin(), CurrentGroup.Regions.end(),
- [&R](OutlinableRegion *Region) {
- R << ore::NV("DebugLoc",
- Region->Candidate->frontInstruction()->getDebugLoc());
- },
- [&R]() { R << " "; });
- return R;
- });
-
- deduplicateExtractedSections(M, CurrentGroup, FuncsToRemove,
- OutlinedFunctionNum);
- }
-
- for (Function *F : FuncsToRemove)
- F->eraseFromParent();
-
- return OutlinedFunctionNum;
-}
-
-bool IROutliner::run(Module &M) {
- CostModel = !NoCostModel;
- OutlineFromLinkODRs = EnableLinkOnceODRIROutlining;
-
- return doOutline(M) > 0;
-}
-
-PreservedAnalyses IROutlinerPass::run(Module &M, ModuleAnalysisManager &AM) {
- auto &FAM = AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
-
- std::function<TargetTransformInfo &(Function &)> GTTI =
- [&FAM](Function &F) -> TargetTransformInfo & {
- return FAM.getResult<TargetIRAnalysis>(F);
- };
-
- std::function<IRSimilarityIdentifier &(Module &)> GIRSI =
- [&AM](Module &M) -> IRSimilarityIdentifier & {
- return AM.getResult<IRSimilarityAnalysis>(M);
- };
-
- std::unique_ptr<OptimizationRemarkEmitter> ORE;
- std::function<OptimizationRemarkEmitter &(Function &)> GORE =
- [&ORE](Function &F) -> OptimizationRemarkEmitter & {
- ORE.reset(new OptimizationRemarkEmitter(&F));
- return *ORE;
- };
-
- if (IROutliner(GTTI, GIRSI, GORE).run(M))
- return PreservedAnalyses::none();
- return PreservedAnalyses::all();
-}
diff --git a/llvm/test/Analysis/IRSimilarityIdentifier/basic.ll b/llvm/test/Analysis/IRSimilarityIdentifier/basic.ll
deleted file mode 100644
index 1c08cb407c2e3..0000000000000
--- a/llvm/test/Analysis/IRSimilarityIdentifier/basic.ll
+++ /dev/null
@@ -1,140 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt -disable-output -S -passes=print-ir-similarity < %s 2>&1 | FileCheck %s
-
-; This is a simple test to make sure the IRSimilarityIdentifier and
-; IRSimilarityPrinterPass is working.
-
-; CHECK: 4 candidates of length 6. Found in:
-; CHECK-NEXT: Function: turtle, Basic Block: (unnamed)
-; CHECK-NEXT: Start Instruction: store i32 1, ptr %1, align 4
-; CHECK-NEXT: End Instruction: store i32 6, ptr %6, align 4
-; CHECK-NEXT: Function: cat, Basic Block: entry
-; CHECK-NEXT: Start Instruction: store i32 6, ptr %0, align 4
-; CHECK-NEXT: End Instruction: store i32 5, ptr %5, align 4
-; CHECK-NEXT: Function: fish, Basic Block: entry
-; CHECK-NEXT: Start Instruction: store i32 6, ptr %0, align 4
-; CHECK-NEXT: End Instruction: store i32 5, ptr %5, align 4
-; CHECK-NEXT: Function: dog, Basic Block: entry
-; CHECK-NEXT: Start Instruction: store i32 6, ptr %0, align 4
-; CHECK-NEXT: End Instruction: store i32 5, ptr %5, align 4
-; CHECK-NEXT:4 candidates of length 5. Found in:
-; CHECK-NEXT: Function: turtle, Basic Block: (unnamed)
-; CHECK-NEXT: Start Instruction: store i32 2, ptr %2, align 4
-; CHECK-NEXT: End Instruction: store i32 6, ptr %6, align 4
-; CHECK-NEXT: Function: cat, Basic Block: entry
-; CHECK-NEXT: Start Instruction: store i32 1, ptr %1, align 4
-; CHECK-NEXT: End Instruction: store i32 5, ptr %5, align 4
-; CHECK-NEXT: Function: fish, Basic Block: entry
-; CHECK-NEXT: Start Instruction: store i32 1, ptr %1, align 4
-; CHECK-NEXT: End Instruction: store i32 5, ptr %5, align 4
-; CHECK-NEXT: Function: dog, Basic Block: entry
-; CHECK-NEXT: Start Instruction: store i32 1, ptr %1, align 4
-; CHECK-NEXT: End Instruction: store i32 5, ptr %5, align 4
-; CHECK-NEXT:4 candidates of length 4. Found in:
-; CHECK-NEXT: Function: turtle, Basic Block: (unnamed)
-; CHECK-NEXT: Start Instruction: store i32 3, ptr %3, align 4
-; CHECK-NEXT: End Instruction: store i32 6, ptr %6, align 4
-; CHECK-NEXT: Function: cat, Basic Block: entry
-; CHECK-NEXT: Start Instruction: store i32 2, ptr %2, align 4
-; CHECK-NEXT: End Instruction: store i32 5, ptr %5, align 4
-; CHECK-NEXT: Function: fish, Basic Block: entry
-; CHECK-NEXT: Start Instruction: store i32 2, ptr %2, align 4
-; CHECK-NEXT: End Instruction: store i32 5, ptr %5, align 4
-; CHECK-NEXT: Function: dog, Basic Block: entry
-; CHECK-NEXT: Start Instruction: store i32 2, ptr %2, align 4
-; CHECK-NEXT: End Instruction: store i32 5, ptr %5, align 4
-; CHECK-NEXT:4 candidates of length 3. Found in:
-; CHECK-NEXT: Function: turtle, Basic Block: (unnamed)
-; CHECK-NEXT: Start Instruction: store i32 4, ptr %4, align 4
-; CHECK-NEXT: End Instruction: store i32 6, ptr %6, align 4
-; CHECK-NEXT: Function: cat, Basic Block: entry
-; CHECK-NEXT: Start Instruction: store i32 3, ptr %3, align 4
-; CHECK-NEXT: End Instruction: store i32 5, ptr %5, align 4
-; CHECK-NEXT: Function: fish, Basic Block: entry
-; CHECK-NEXT: Start Instruction: store i32 3, ptr %3, align 4
-; CHECK-NEXT: End Instruction: store i32 5, ptr %5, align 4
-; CHECK-NEXT: Function: dog, Basic Block: entry
-; CHECK-NEXT: Start Instruction: store i32 3, ptr %3, align 4
-; CHECK-NEXT: End Instruction: store i32 5, ptr %5, align 4
-; CHECK-NEXT:4 candidates of length 2. Found in:
-; CHECK-NEXT: Function: turtle, Basic Block: (unnamed)
-; CHECK-NEXT: Start Instruction: store i32 5, ptr %5, align 4
-; CHECK-NEXT: End Instruction: store i32 6, ptr %6, align 4
-; CHECK-NEXT: Function: cat, Basic Block: entry
-; CHECK-NEXT: Start Instruction: store i32 4, ptr %4, align 4
-; CHECK-NEXT: End Instruction: store i32 5, ptr %5, align 4
-; CHECK-NEXT: Function: fish, Basic Block: entry
-; CHECK-NEXT: Start Instruction: store i32 4, ptr %4, align 4
-; CHECK-NEXT: End Instruction: store i32 5, ptr %5, align 4
-; CHECK-NEXT: Function: dog, Basic Block: entry
-; CHECK-NEXT: Start Instruction: store i32 4, ptr %4, align 4
-; CHECK-NEXT: End Instruction: store i32 5, ptr %5, align 4
-
-define linkonce_odr void @fish() {
-entry:
- %0 = alloca i32, align 4
- %1 = alloca i32, align 4
- %2 = alloca i32, align 4
- %3 = alloca i32, align 4
- %4 = alloca i32, align 4
- %5 = alloca i32, align 4
- store i32 6, ptr %0, align 4
- store i32 1, ptr %1, align 4
- store i32 2, ptr %2, align 4
- store i32 3, ptr %3, align 4
- store i32 4, ptr %4, align 4
- store i32 5, ptr %5, align 4
- ret void
-}
-
-define void @turtle() {
- %1 = alloca i32, align 4
- %2 = alloca i32, align 4
- %3 = alloca i32, align 4
- %4 = alloca i32, align 4
- %5 = alloca i32, align 4
- %6 = alloca i32, align 4
- store i32 1, ptr %1, align 4
- store i32 2, ptr %2, align 4
- store i32 3, ptr %3, align 4
- store i32 4, ptr %4, align 4
- store i32 5, ptr %5, align 4
- store i32 6, ptr %6, align 4
- ret void
-}
-
-define void @cat() {
-entry:
- %0 = alloca i32, align 4
- %1 = alloca i32, align 4
- %2 = alloca i32, align 4
- %3 = alloca i32, align 4
- %4 = alloca i32, align 4
- %5 = alloca i32, align 4
- store i32 6, ptr %0, align 4
- store i32 1, ptr %1, align 4
- store i32 2, ptr %2, align 4
- store i32 3, ptr %3, align 4
- store i32 4, ptr %4, align 4
- store i32 5, ptr %5, align 4
- ret void
-}
-
-define void @dog() {
-entry:
- %0 = alloca i32, align 4
- %1 = alloca i32, align 4
- %2 = alloca i32, align 4
- %3 = alloca i32, align 4
- %4 = alloca i32, align 4
- %5 = alloca i32, align 4
- store i32 6, ptr %0, align 4
- store i32 1, ptr %1, align 4
- store i32 2, ptr %2, align 4
- store i32 3, ptr %3, align 4
- store i32 4, ptr %4, align 4
- store i32 5, ptr %5, align 4
- ret void
-}
-;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
-; CHECK: {{.*}}
diff --git a/llvm/test/Analysis/IRSimilarityIdentifier/debug-inst-starts-block.ll b/llvm/test/Analysis/IRSimilarityIdentifier/debug-inst-starts-block.ll
deleted file mode 100644
index 78ecec92cc31a..0000000000000
--- a/llvm/test/Analysis/IRSimilarityIdentifier/debug-inst-starts-block.ll
+++ /dev/null
@@ -1,77 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 2
-; RUN: opt -disable-output -S -passes=print-ir-similarity < %s 2>&1 | FileCheck %s
-
-; When a debug instruction is the first instruction in a block, when that block
-; has not been given a canonical numbering, since debug instructions are not
-; counted in similarity matching they must be ignored when creating canonical
-; relations from one region to another. This checks that this is enforced.
-
-; CHECK: 2 candidates of length 4. Found in:
-; CHECK-NEXT: Function: main, Basic Block: entry
-; CHECK-NEXT: Start Instruction: %0 = add i32 1, 4
-; CHECK-NEXT: End Instruction: %1 = sub i32 1, 4
-; CHECK-NEXT: Function: main, Basic Block: for.body169
-; CHECK-NEXT: Start Instruction: %2 = add i32 1, 4
-; CHECK-NEXT: End Instruction: %3 = sub i32 1, 4
-; CHECK-NEXT: 2 candidates of length 3. Found in:
-; CHECK-NEXT: Function: main, Basic Block: entry
-; CHECK-NEXT: Start Instruction: br label %for.body169
-; CHECK-NEXT: End Instruction: %1 = sub i32 1, 4
-; CHECK-NEXT: Function: main, Basic Block: for.body169
-; CHECK-NEXT: Start Instruction: br label %for.end122
-; CHECK-NEXT: End Instruction: %3 = sub i32 1, 4
-; CHECK-NEXT: 2 candidates of length 2. Found in:
-; CHECK-NEXT: Function: main, Basic Block: for.end122
-; CHECK-NEXT: Start Instruction: store i32 30, ptr undef, align 1
-; CHECK-NEXT: End Instruction: %1 = sub i32 1, 4
-; CHECK-NEXT: Function: main, Basic Block: for.end246
-; CHECK-NEXT: Start Instruction: store i32 0, ptr undef, align 1
-; CHECK-NEXT: End Instruction: %3 = sub i32 1, 4
-
-source_filename = "irsimilarity_crash.ll"
-
- at v_13 = external dso_local global ptr, align 1
-
-; Function Attrs: nocallback nofree nosync nounwind readnone speculatable willreturn
-declare void @llvm.dbg.declare(metadata, metadata, metadata) #0
-
-define dso_local i16 @main() {
-entry:
- %0 = add i32 1, 4
- br label %for.body169
-
-for.end122: ; preds = %for.cond108
- store i32 30, ptr undef, align 1
- %1 = sub i32 1, 4
- ret i16 1
-
-for.body169: ; preds = %for.cond167
- %2 = add i32 1, 4
- br label %for.end122
-
-for.end246: ; preds = %for.cond167
- call void @llvm.dbg.declare(metadata ptr undef, metadata !1, metadata !DIExpression()), !dbg !11
- store i32 0, ptr undef, align 1
- %3 = sub i32 1, 4
- unreachable
-}
-
-attributes #0 = { nocallback nofree nosync nounwind readnone speculatable willreturn }
-
-!llvm.dbg.cu = !{}
-!llvm.module.flags = !{!0}
-
-!0 = !{i32 2, !"Debug Info Version", i32 3}
-!1 = !DILocalVariable(name: "v_68", scope: !2, file: !3, line: 522, type: !10)
-!2 = distinct !DILexicalBlock(scope: !4, file: !3, line: 522, column: 9)
-!3 = !DIFile(filename: "41097217.c", directory: "rt.outdir")
-!4 = distinct !DISubprogram(name: "main", scope: !3, file: !3, line: 480, type: !5, scopeLine: 481, spFlags: DISPFlagDefinition, unit: !8, retainedNodes: !9)
-!5 = !DISubroutineType(types: !6)
-!6 = !{!7}
-!7 = !DIBasicType(name: "int", size: 16, encoding: DW_ATE_signed)
-!8 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 15.0.0.prerel", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, retainedTypes: !9, globals: !9, splitDebugInlining: false, nameTableKind: None)
-!9 = !{}
-!10 = !DIBasicType(name: "long", size: 32, encoding: DW_ATE_signed)
-!11 = !DILocation(line: 522, column: 23, scope: !2)
-;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
-; CHECK: {{.*}}
diff --git a/llvm/test/Analysis/IRSimilarityIdentifier/different.ll b/llvm/test/Analysis/IRSimilarityIdentifier/different.ll
deleted file mode 100644
index e5c9970b159b9..0000000000000
--- a/llvm/test/Analysis/IRSimilarityIdentifier/different.ll
+++ /dev/null
@@ -1,48 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt -disable-output -S -passes=print-ir-similarity < %s 2>&1 | FileCheck --allow-empty %s
-
-; Check to make sure that the IRSimilarityIdentifier and IRSimilarityPrinterPass
-; return items only within the same function when there are different sets of
-; instructions in functions.
-
-; CHECK: 2 candidates of length 5. Found in:
-; CHECK-NEXT: Function: fish, Basic Block: entry
-; CHECK-NEXT: Start Instruction: store i32 6, ptr %0, align 4
-; CHECK-NEXT: End Instruction: store i32 4, ptr %4, align 4
-; CHECK-NEXT: Function: fish, Basic Block: entry
-; CHECK-NEXT: Start Instruction: store i32 1, ptr %1, align 4
-; CHECK-NEXT: End Instruction: store i32 5, ptr %5, align 4
-; CHECK-NEXT: 2 candidates of length 3. Found in:
-; CHECK-NEXT: Function: turtle, Basic Block: (unnamed)
-; CHECK-NEXT: Start Instruction: %b = load i32, ptr %1, align 4
-; CHECK-NEXT: End Instruction: %d = load i32, ptr %3, align 4
-; CHECK-NEXT: Function: turtle, Basic Block: (unnamed)
-; CHECK-NEXT: Start Instruction: %a = load i32, ptr %0, align 4
-; CHECK-NEXT: End Instruction: %c = load i32, ptr %2, align 4
-
-define linkonce_odr void @fish() {
-entry:
- %0 = alloca i32, align 4
- %1 = alloca i32, align 4
- %2 = alloca i32, align 4
- %3 = alloca i32, align 4
- %4 = alloca i32, align 4
- %5 = alloca i32, align 4
- store i32 6, ptr %0, align 4
- store i32 1, ptr %1, align 4
- store i32 2, ptr %2, align 4
- store i32 3, ptr %3, align 4
- store i32 4, ptr %4, align 4
- store i32 5, ptr %5, align 4
- ret void
-}
-
-define void @turtle(ptr %0, ptr %1, ptr %2, ptr %3) {
- %a = load i32, ptr %0
- %b = load i32, ptr %1
- %c = load i32, ptr %2
- %d = load i32, ptr %3
- ret void
-}
-;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
-; CHECK: {{.*}}
diff --git a/llvm/test/Analysis/IRSimilarityIdentifier/nothing.ll b/llvm/test/Analysis/IRSimilarityIdentifier/nothing.ll
deleted file mode 100644
index 4891a587d776f..0000000000000
--- a/llvm/test/Analysis/IRSimilarityIdentifier/nothing.ll
+++ /dev/null
@@ -1,14 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt -disable-output -S -passes=print-ir-similarity < %s 2>&1 | FileCheck --allow-empty %s
-
-; This is a simple test to make sure the IRSimilarityPrinterPass returns
-; nothing when there is nothing to analyze.
-
-; CHECK-NOT: Found in
-
-define linkonce_odr void @fish() {
-entry:
- ret void
-}
-;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
-; CHECK: {{.*}}
diff --git a/llvm/test/CMakeLists.txt b/llvm/test/CMakeLists.txt
index 3f1ee7c18bde7..2a00a429e2626 100644
--- a/llvm/test/CMakeLists.txt
+++ b/llvm/test/CMakeLists.txt
@@ -140,7 +140,6 @@ set(LLVM_TEST_DEPENDS
llvm-reduce
llvm-remarkutil
llvm-rtdyld
- llvm-sim
llvm-size
llvm-split
llvm-stress
diff --git a/llvm/test/DebugInfo/AArch64/ir-outliner.ll b/llvm/test/DebugInfo/AArch64/ir-outliner.ll
deleted file mode 100644
index 168232e215871..0000000000000
--- a/llvm/test/DebugInfo/AArch64/ir-outliner.ll
+++ /dev/null
@@ -1,162 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --include-generated-funcs
-; RUN: opt -passes=verify,iroutliner -ir-outlining-no-cost < %s | \
-; RUN: llc -filetype=obj -mtriple=aarch64-- | llvm-dwarfdump - | FileCheck %s
-
-; RUN: opt -S -passes=verify,iroutliner -ir-outlining-no-cost < %s | FileCheck -check-prefix=IRDEBUG %s
-
-; Ensure that the IR Outliner produces valid DWARF debug information when
-; creating outlined functions.
-
-; CHECK: DW_TAG_compile_unit
-; CHECK-DAG: DW_AT_name ("outline_debug1")
-
-; Check the high address of bar. This is one past the end of bar. It should be
-; the beginning of the outlined function.
-; CHECK: DW_AT_high_pc ([[ONE_PAST_BAR:0x[a-f0-9]+]])
-; CHECK-NEXT: DW_AT_frame_base (DW_OP_reg31 WSP)
-; CHECK-NEXT: DW_AT_linkage_name ("outline_debug2")
-; CHECK-NEXT: DW_AT_name ("outline_debug2")
-
-; Check the outlined function's DWARF.
-; CHECK-DAG: DW_TAG_subprogram
-; CHECK-NEXT: DW_AT_low_pc ([[ONE_PAST_BAR]])
-; CHECK-NEXT: DW_AT_high_pc (0x{{[0-9a-f]+}})
-; CHECK-NEXT: DW_AT_frame_base (DW_OP_reg31 WSP)
-; CHECK-NEXT: DW_AT_linkage_name ("[[NAME:outlined_ir_func_[0-9]+]]")
-; CHECK-NEXT: DW_AT_name ("[[NAME]]")
-; CHECK-NEXT: DW_AT_artificial (true)
-; CHECK-NEXT: DW_AT_external (true)
-
-define void @outline_debug1() !dbg !6 {
-entry:
- %a = alloca i32, align 4, !dbg !17
- call void @llvm.dbg.value(metadata ptr %a, metadata !9, metadata !DIExpression()), !dbg !17
- %b = alloca i32, align 4, !dbg !18
- call void @llvm.dbg.value(metadata ptr %b, metadata !11, metadata !DIExpression()), !dbg !18
- %c = alloca i32, align 4, !dbg !19
- call void @llvm.dbg.value(metadata ptr %c, metadata !12, metadata !DIExpression()), !dbg !19
- store i32 2, ptr %a, align 4, !dbg !20
- store i32 3, ptr %b, align 4, !dbg !21
- store i32 4, ptr %c, align 4, !dbg !22
- %al = load i32, ptr %a, align 4, !dbg !23
- call void @llvm.dbg.value(metadata i32 %al, metadata !13, metadata !DIExpression()), !dbg !23
- %bl = load i32, ptr %b, align 4, !dbg !24
- call void @llvm.dbg.value(metadata i32 %bl, metadata !15, metadata !DIExpression()), !dbg !24
- %cl = load i32, ptr %c, align 4, !dbg !25
- call void @llvm.dbg.value(metadata i32 %cl, metadata !16, metadata !DIExpression()), !dbg !25
- ret void, !dbg !26
-}
-
-define void @outline_debug2() !dbg !27 {
-entry:
- %a = alloca i32, align 4, !dbg !35
- call void @llvm.dbg.value(metadata ptr %a, metadata !29, metadata !DIExpression()), !dbg !35
- %b = alloca i32, align 4, !dbg !36
- call void @llvm.dbg.value(metadata ptr %b, metadata !30, metadata !DIExpression()), !dbg !36
- %c = alloca i32, align 4, !dbg !37
- call void @llvm.dbg.value(metadata ptr %c, metadata !31, metadata !DIExpression()), !dbg !37
- store i32 2, ptr %a, align 4, !dbg !38
- store i32 3, ptr %b, align 4, !dbg !39
- store i32 4, ptr %c, align 4, !dbg !40
- %al = load i32, ptr %a, align 4, !dbg !41
- call void @llvm.dbg.value(metadata i32 %al, metadata !32, metadata !DIExpression()), !dbg !41
- %bl = load i32, ptr %b, align 4, !dbg !42
- call void @llvm.dbg.value(metadata i32 %bl, metadata !33, metadata !DIExpression()), !dbg !42
- %cl = load i32, ptr %c, align 4, !dbg !43
- call void @llvm.dbg.value(metadata i32 %cl, metadata !34, metadata !DIExpression()), !dbg !43
- ret void, !dbg !44
-}
-
-; Function Attrs: nounwind readnone speculatable willreturn
-declare void @llvm.dbg.value(metadata, metadata, metadata) #0
-
-attributes #0 = { nounwind readnone speculatable willreturn }
-
-!llvm.dbg.cu = !{!0}
-!llvm.debugify = !{!3, !4}
-!llvm.module.flags = !{!5}
-
-!0 = distinct !DICompileUnit(language: DW_LANG_C, file: !1, producer: "debugify", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
-!1 = !DIFile(filename: "llvm/test/DebugInfo/ir-outliner.ll", directory: "/")
-!2 = !{}
-!3 = !{i32 20}
-!4 = !{i32 12}
-!5 = !{i32 2, !"Debug Info Version", i32 3}
-!6 = distinct !DISubprogram(name: "outline_debug1", linkageName: "outline_debug1", scope: null, file: !1, line: 1, type: !7, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !8)
-!7 = !DISubroutineType(types: !2)
-!8 = !{!9, !11, !12, !13, !15, !16}
-!9 = !DILocalVariable(name: "1", scope: !6, file: !1, line: 1, type: !10)
-!10 = !DIBasicType(name: "ty64", size: 64, encoding: DW_ATE_unsigned)
-!11 = !DILocalVariable(name: "2", scope: !6, file: !1, line: 2, type: !10)
-!12 = !DILocalVariable(name: "3", scope: !6, file: !1, line: 3, type: !10)
-!13 = !DILocalVariable(name: "4", scope: !6, file: !1, line: 7, type: !14)
-!14 = !DIBasicType(name: "ty32", size: 32, encoding: DW_ATE_unsigned)
-!15 = !DILocalVariable(name: "5", scope: !6, file: !1, line: 8, type: !14)
-!16 = !DILocalVariable(name: "6", scope: !6, file: !1, line: 9, type: !14)
-!17 = !DILocation(line: 1, column: 1, scope: !6)
-!18 = !DILocation(line: 2, column: 1, scope: !6)
-!19 = !DILocation(line: 3, column: 1, scope: !6)
-!20 = !DILocation(line: 4, column: 1, scope: !6)
-!21 = !DILocation(line: 5, column: 1, scope: !6)
-!22 = !DILocation(line: 6, column: 1, scope: !6)
-!23 = !DILocation(line: 7, column: 1, scope: !6)
-!24 = !DILocation(line: 8, column: 1, scope: !6)
-!25 = !DILocation(line: 9, column: 1, scope: !6)
-!26 = !DILocation(line: 10, column: 1, scope: !6)
-!27 = distinct !DISubprogram(name: "outline_debug2", linkageName: "outline_debug2", scope: null, file: !1, line: 11, type: !7, scopeLine: 11, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !28)
-!28 = !{!29, !30, !31, !32, !33, !34}
-!29 = !DILocalVariable(name: "7", scope: !27, file: !1, line: 11, type: !10)
-!30 = !DILocalVariable(name: "8", scope: !27, file: !1, line: 12, type: !10)
-!31 = !DILocalVariable(name: "9", scope: !27, file: !1, line: 13, type: !10)
-!32 = !DILocalVariable(name: "10", scope: !27, file: !1, line: 17, type: !14)
-!33 = !DILocalVariable(name: "11", scope: !27, file: !1, line: 18, type: !14)
-!34 = !DILocalVariable(name: "12", scope: !27, file: !1, line: 19, type: !14)
-!35 = !DILocation(line: 11, column: 1, scope: !27)
-!36 = !DILocation(line: 12, column: 1, scope: !27)
-!37 = !DILocation(line: 13, column: 1, scope: !27)
-!38 = !DILocation(line: 14, column: 1, scope: !27)
-!39 = !DILocation(line: 15, column: 1, scope: !27)
-!40 = !DILocation(line: 16, column: 1, scope: !27)
-!41 = !DILocation(line: 17, column: 1, scope: !27)
-!42 = !DILocation(line: 18, column: 1, scope: !27)
-!43 = !DILocation(line: 19, column: 1, scope: !27)
-!44 = !DILocation(line: 20, column: 1, scope: !27)
-
-; IRDEBUG-LABEL: @outline_debug1(
-; IRDEBUG-NEXT: entry:
-; IRDEBUG-NEXT: [[A:%.*]] = alloca i32, align 4, !dbg [[DBG17:![0-9]+]]
-; IRDEBUG-NEXT: #dbg_value(ptr [[A]], [[META9:![0-9]+]], !DIExpression(), [[DBG17]])
-; IRDEBUG-NEXT: [[B:%.*]] = alloca i32, align 4, !dbg [[DBG18:![0-9]+]]
-; IRDEBUG-NEXT: #dbg_value(ptr [[B]], [[META11:![0-9]+]], !DIExpression(), [[DBG18]])
-; IRDEBUG-NEXT: [[C:%.*]] = alloca i32, align 4, !dbg [[DBG19:![0-9]+]]
-; IRDEBUG-NEXT: #dbg_value(ptr [[C]], [[META12:![0-9]+]], !DIExpression(), [[DBG19]])
-; IRDEBUG-NEXT: call void @outlined_ir_func_0(ptr [[A]], ptr [[B]], ptr [[C]]), !dbg [[DBG20:![0-9]+]]
-; IRDEBUG-NEXT: ret void, !dbg [[DBG21:![0-9]+]]
-;
-;
-; IRDEBUG-LABEL: @outline_debug2(
-; IRDEBUG-NEXT: entry:
-; IRDEBUG-NEXT: [[A:%.*]] = alloca i32, align 4, !dbg [[DBG30:![0-9]+]]
-; IRDEBUG-NEXT: #dbg_value(ptr [[A]], [[META24:![0-9]+]], !DIExpression(), [[DBG30]])
-; IRDEBUG-NEXT: [[B:%.*]] = alloca i32, align 4, !dbg [[DBG31:![0-9]+]]
-; IRDEBUG-NEXT: #dbg_value(ptr [[B]], [[META25:![0-9]+]], !DIExpression(), [[DBG31]])
-; IRDEBUG-NEXT: [[C:%.*]] = alloca i32, align 4, !dbg [[DBG32:![0-9]+]]
-; IRDEBUG-NEXT: #dbg_value(ptr [[C]], [[META26:![0-9]+]], !DIExpression(), [[DBG32]])
-; IRDEBUG-NEXT: call void @outlined_ir_func_0(ptr [[A]], ptr [[B]], ptr [[C]]), !dbg [[DBG33:![0-9]+]]
-; IRDEBUG-NEXT: ret void, !dbg [[DBG34:![0-9]+]]
-;
-;
-; IRDEBUG-LABEL: define {{.+}} @outlined_ir_func_0(
-; IRDEBUG-NEXT: newFuncRoot:
-; IRDEBUG-NEXT: br label [[ENTRY_TO_OUTLINE:%.*]]
-; IRDEBUG: entry_to_outline:
-; IRDEBUG-NEXT: store i32 2, ptr [[TMP0:%.*]], align 4
-; IRDEBUG-NEXT: store i32 3, ptr [[TMP1:%.*]], align 4
-; IRDEBUG-NEXT: store i32 4, ptr [[TMP2:%.*]], align 4
-; IRDEBUG-NEXT: [[AL:%.*]] = load i32, ptr [[TMP0]], align 4
-; IRDEBUG-NEXT: [[BL:%.*]] = load i32, ptr [[TMP1]], align 4
-; IRDEBUG-NEXT: [[CL:%.*]] = load i32, ptr [[TMP2]], align 4
-; IRDEBUG-NEXT: br label [[ENTRY_AFTER_OUTLINE_EXITSTUB:%.*]]
-; IRDEBUG: entry_after_outline.exitStub:
-; IRDEBUG-NEXT: ret void
-;
diff --git a/llvm/test/Other/new-pm-defaults.ll b/llvm/test/Other/new-pm-defaults.ll
index 3d6b2b4b702c6..6b2edf339dfdf 100644
--- a/llvm/test/Other/new-pm-defaults.ll
+++ b/llvm/test/Other/new-pm-defaults.ll
@@ -77,10 +77,6 @@
; RUN: -passes='default<O3>' -enable-merge-functions -S %s 2>&1 \
; RUN: | FileCheck %s --check-prefixes=CHECK-O,CHECK-DEFAULT,CHECK-O3,CHECK-O23,%llvmcheckext,CHECK-MERGE-FUNCS
-; RUN: opt -disable-verify -verify-analysis-invalidation=0 -eagerly-invalidate-analyses=0 -debug-pass-manager \
-; RUN: -passes='default<O3>' -ir-outliner -S %s 2>&1 \
-; RUN: | FileCheck %s --check-prefixes=CHECK-O,CHECK-DEFAULT,CHECK-O3,CHECK-O23,%llvmcheckext,CHECK-IR-OUTLINER
-
; RUN: opt -disable-verify -verify-analysis-invalidation=0 -eagerly-invalidate-analyses=0 -debug-pass-manager \
; RUN: -passes='default<O3>' -hot-cold-split -S %s 2>&1 \
; RUN: | FileCheck %s --check-prefixes=CHECK-O,CHECK-DEFAULT,CHECK-O3,CHECK-O23,%llvmcheckext,CHECK-HOT-COLD-SPLIT
@@ -277,8 +273,6 @@
; CHECK-DEFAULT-NEXT: Running pass: AllocToken
; CHECK-EP-OPTIMIZER-LAST: Running pass: NoOpModulePass
; CHECK-HOT-COLD-SPLIT-NEXT: Running pass: HotColdSplittingPass
-; CHECK-IR-OUTLINER-NEXT: Running pass: IROutlinerPass
-; CHECK-IR-OUTLINER-NEXT: Running analysis: IRSimilarityAnalysis
; CHECK-O-NEXT: Running pass: GlobalDCEPass
; CHECK-O-NEXT: Running pass: ConstantMergePass
; CHECK-MERGE-FUNCS-NEXT: Running pass: MergeFunctionsPass
diff --git a/llvm/test/Transforms/IROutliner/alloca-addrspace-1.ll b/llvm/test/Transforms/IROutliner/alloca-addrspace-1.ll
deleted file mode 100644
index 73db71b6bafc9..0000000000000
--- a/llvm/test/Transforms/IROutliner/alloca-addrspace-1.ll
+++ /dev/null
@@ -1,46 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --include-generated-funcs
-; RUN: opt -S -passes=iroutliner -ir-outlining-no-cost < %s | FileCheck %s
-
-target datalayout = "A5"
-
-define i32 @func_with_outgoing_new_allocas() {
-bb:
- %i = tail call i32 @func0(i32 0, i32 1)
- %i1 = or i32 0, %i
- %i2 = tail call i32 @func0(i32 %i1, i32 0)
- %i3 = or i32 %i1, %i2
- %i4 = tail call i32 @llvm.foo(i32 %i3, i32 0)
- ret i32 0
-}
-
-declare i32 @func0(i32, i32)
-declare i32 @llvm.foo(i32, i32)
-
-; CHECK-LABEL: define {{[^@]+}}@func_with_outgoing_new_allocas() {
-; CHECK-NEXT: bb:
-; CHECK-NEXT: [[I3_LOC:%.*]] = alloca i32, align 4, addrspace(5)
-; CHECK-NEXT: [[I1_LOC:%.*]] = alloca i32, align 4, addrspace(5)
-; CHECK-NEXT: call void @llvm.lifetime.start.p5(ptr addrspace(5) [[I1_LOC]])
-; CHECK-NEXT: call void @outlined_ir_func_0(i32 0, i32 1, ptr addrspace(5) [[I1_LOC]])
-; CHECK-NEXT: [[I1_RELOAD:%.*]] = load i32, ptr addrspace(5) [[I1_LOC]], align 4
-; CHECK-NEXT: call void @llvm.lifetime.end.p5(ptr addrspace(5) [[I1_LOC]])
-; CHECK-NEXT: call void @llvm.lifetime.start.p5(ptr addrspace(5) [[I3_LOC]])
-; CHECK-NEXT: call void @outlined_ir_func_0(i32 [[I1_RELOAD]], i32 0, ptr addrspace(5) [[I3_LOC]])
-; CHECK-NEXT: [[I3_RELOAD:%.*]] = load i32, ptr addrspace(5) [[I3_LOC]], align 4
-; CHECK-NEXT: call void @llvm.lifetime.end.p5(ptr addrspace(5) [[I3_LOC]])
-; CHECK-NEXT: [[I4:%.*]] = tail call i32 @llvm.foo(i32 [[I3_RELOAD]], i32 0)
-; CHECK-NEXT: ret i32 0
-;
-;
-; CHECK-LABEL: define {{[^@]+}}@outlined_ir_func_0
-; CHECK-SAME: (i32 [[TMP0:%.*]], i32 [[TMP1:%.*]], ptr addrspace(5) [[TMP2:%.*]]) #[[ATTR1:[0-9]+]] {
-; CHECK-NEXT: newFuncRoot:
-; CHECK-NEXT: br label [[BB_TO_OUTLINE:%.*]]
-; CHECK: bb_to_outline:
-; CHECK-NEXT: [[I:%.*]] = tail call i32 @func0(i32 [[TMP0]], i32 [[TMP1]])
-; CHECK-NEXT: [[I1:%.*]] = or i32 [[TMP0]], [[I]]
-; CHECK-NEXT: br label [[BB_AFTER_OUTLINE_EXITSTUB:%.*]]
-; CHECK: bb_after_outline.exitStub:
-; CHECK-NEXT: store i32 [[I1]], ptr addrspace(5) [[TMP2]], align 4
-; CHECK-NEXT: ret void
-;
diff --git a/llvm/test/Transforms/IROutliner/alloca-addrspace.ll b/llvm/test/Transforms/IROutliner/alloca-addrspace.ll
deleted file mode 100644
index ed7644426ffc0..0000000000000
--- a/llvm/test/Transforms/IROutliner/alloca-addrspace.ll
+++ /dev/null
@@ -1,46 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --include-generated-funcs
-; RUN: opt -S -passes=iroutliner -ir-outlining-no-cost < %s | FileCheck %s
-
-; Check alloca with non-0 address spaces works correctly.
-
-target datalayout = "A5"
-
-define i32 @outlineable() {
-bb:
- %i = tail call i32 @func(i32 0, i32 1)
- %i1 = or i32 0, %i
- %i2 = tail call i32 @func(i32 %i1, i32 0)
- %i3 = or i32 %i1, %i2
- ret i32 0
-}
-
-declare i32 @func(i32, i32)
-; CHECK-LABEL: define {{[^@]+}}@outlineable() {
-; CHECK-NEXT: bb:
-; CHECK-NEXT: [[I1_LOC:%.*]] = alloca i32, align 4, addrspace(5)
-; CHECK-NEXT: call void @llvm.lifetime.start.p5(ptr addrspace(5) [[I1_LOC]])
-; CHECK-NEXT: call void @outlined_ir_func_0(i32 0, i32 1, ptr addrspace(5) [[I1_LOC]], i32 0)
-; CHECK-NEXT: [[I1_RELOAD:%.*]] = load i32, ptr addrspace(5) [[I1_LOC]], align 4
-; CHECK-NEXT: call void @llvm.lifetime.end.p5(ptr addrspace(5) [[I1_LOC]])
-; CHECK-NEXT: call void @outlined_ir_func_0(i32 [[I1_RELOAD]], i32 0, ptr addrspace(5) null, i32 -1)
-; CHECK-NEXT: ret i32 0
-;
-;
-; CHECK-LABEL: define {{[^@]+}}@outlined_ir_func_0
-; CHECK-SAME: (i32 [[TMP0:%.*]], i32 [[TMP1:%.*]], ptr addrspace(5) [[TMP2:%.*]], i32 [[TMP3:%.*]]) #[[ATTR1:[0-9]+]] {
-; CHECK-NEXT: newFuncRoot:
-; CHECK-NEXT: br label [[BB_TO_OUTLINE:%.*]]
-; CHECK: bb_to_outline:
-; CHECK-NEXT: [[I:%.*]] = tail call i32 @func(i32 [[TMP0]], i32 [[TMP1]])
-; CHECK-NEXT: [[I1:%.*]] = or i32 [[TMP0]], [[I]]
-; CHECK-NEXT: br label [[BB_AFTER_OUTLINE_EXITSTUB:%.*]]
-; CHECK: bb_after_outline.exitStub:
-; CHECK-NEXT: switch i32 [[TMP3]], label [[FINAL_BLOCK_0:%.*]] [
-; CHECK-NEXT: i32 0, label [[OUTPUT_BLOCK_0_0:%.*]]
-; CHECK-NEXT: ]
-; CHECK: output_block_0_0:
-; CHECK-NEXT: store i32 [[I1]], ptr addrspace(5) [[TMP2]], align 4
-; CHECK-NEXT: br label [[FINAL_BLOCK_0]]
-; CHECK: final_block_0:
-; CHECK-NEXT: ret void
-;
diff --git a/llvm/test/Transforms/IROutliner/different-intrinsics.ll b/llvm/test/Transforms/IROutliner/different-intrinsics.ll
deleted file mode 100644
index f0e43bb533fdc..0000000000000
--- a/llvm/test/Transforms/IROutliner/different-intrinsics.ll
+++ /dev/null
@@ -1,92 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --include-generated-funcs
-; RUN: opt -S -passes=verify,iroutliner -ir-outlining-no-cost < %s | FileCheck %s
-
-; This test checks that we do not outline different intrinsics as the same
-; function or as a value like we would for non-intrinsic functions.
-
-declare void @llvm.memcpy.p0.p0.i64(ptr nocapture writeonly, ptr nocapture readonly, i64, i1)
-declare void @llvm.memmove.p0.p0.i64(ptr nocapture writeonly, ptr nocapture readonly, i64, i1)
-
-define i8 @function1(ptr noalias %s, ptr noalias %d, i64 %len) {
-entry:
- %a = load i8, ptr %s
- %b = load i8, ptr %d
- call void @llvm.memcpy.p0.p0.i64(ptr %d, ptr %s, i64 %len, i1 false)
- %c = add i8 %a, %b
- %ret = load i8, ptr %s
- ret i8 %ret
-}
-
-define i8 @function2(ptr noalias %s, ptr noalias %d, i64 %len) {
-entry:
- %a = load i8, ptr %s
- %b = load i8, ptr %d
- call void @llvm.memmove.p0.p0.i64(ptr %d, ptr %s, i64 %len, i1 false)
- %c = add i8 %a, %b
- %ret = load i8, ptr %s
- ret i8 %ret
-}
-; CHECK-LABEL: @function1(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[B_LOC:%.*]] = alloca i8, align 1
-; CHECK-NEXT: [[A_LOC:%.*]] = alloca i8, align 1
-; CHECK-NEXT: [[RET_LOC:%.*]] = alloca i8, align 1
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[A_LOC]])
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[B_LOC]])
-; CHECK-NEXT: call void @outlined_ir_func_1(ptr [[S:%.*]], ptr [[D:%.*]], ptr [[A_LOC]], ptr [[B_LOC]])
-; CHECK-NEXT: [[A_RELOAD:%.*]] = load i8, ptr [[A_LOC]], align 1
-; CHECK-NEXT: [[B_RELOAD:%.*]] = load i8, ptr [[B_LOC]], align 1
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[A_LOC]])
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[B_LOC]])
-; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr [[D]], ptr [[S]], i64 [[LEN:%.*]], i1 false)
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[RET_LOC]])
-; CHECK-NEXT: call void @outlined_ir_func_0(i8 [[A_RELOAD]], i8 [[B_RELOAD]], ptr [[S]], ptr [[RET_LOC]])
-; CHECK-NEXT: [[RET_RELOAD:%.*]] = load i8, ptr [[RET_LOC]], align 1
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[RET_LOC]])
-; CHECK-NEXT: ret i8 [[RET_RELOAD]]
-;
-;
-; CHECK-LABEL: @function2(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[B_LOC:%.*]] = alloca i8, align 1
-; CHECK-NEXT: [[A_LOC:%.*]] = alloca i8, align 1
-; CHECK-NEXT: [[RET_LOC:%.*]] = alloca i8, align 1
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[A_LOC]])
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[B_LOC]])
-; CHECK-NEXT: call void @outlined_ir_func_1(ptr [[S:%.*]], ptr [[D:%.*]], ptr [[A_LOC]], ptr [[B_LOC]])
-; CHECK-NEXT: [[A_RELOAD:%.*]] = load i8, ptr [[A_LOC]], align 1
-; CHECK-NEXT: [[B_RELOAD:%.*]] = load i8, ptr [[B_LOC]], align 1
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[A_LOC]])
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[B_LOC]])
-; CHECK-NEXT: call void @llvm.memmove.p0.p0.i64(ptr [[D]], ptr [[S]], i64 [[LEN:%.*]], i1 false)
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[RET_LOC]])
-; CHECK-NEXT: call void @outlined_ir_func_0(i8 [[A_RELOAD]], i8 [[B_RELOAD]], ptr [[S]], ptr [[RET_LOC]])
-; CHECK-NEXT: [[RET_RELOAD:%.*]] = load i8, ptr [[RET_LOC]], align 1
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[RET_LOC]])
-; CHECK-NEXT: ret i8 [[RET_RELOAD]]
-;
-;
-; CHECK-LABEL: define internal void @outlined_ir_func_0(
-; CHECK-NEXT: newFuncRoot:
-; CHECK-NEXT: br label [[ENTRY_TO_OUTLINE:%.*]]
-; CHECK: entry_to_outline:
-; CHECK-NEXT: [[C:%.*]] = add i8 [[TMP0:%.*]], [[TMP1:%.*]]
-; CHECK-NEXT: [[RET:%.*]] = load i8, ptr [[TMP2:%.*]], align 1
-; CHECK-NEXT: br label [[ENTRY_AFTER_OUTLINE_EXITSTUB:%.*]]
-; CHECK: entry_after_outline.exitStub:
-; CHECK-NEXT: store i8 [[RET]], ptr [[TMP3:%.*]], align 1
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: define internal void @outlined_ir_func_1(
-; CHECK-NEXT: newFuncRoot:
-; CHECK-NEXT: br label [[ENTRY_TO_OUTLINE:%.*]]
-; CHECK: entry_to_outline:
-; CHECK-NEXT: [[A:%.*]] = load i8, ptr [[TMP0:%.*]], align 1
-; CHECK-NEXT: [[B:%.*]] = load i8, ptr [[TMP1:%.*]], align 1
-; CHECK-NEXT: br label [[ENTRY_AFTER_OUTLINE_EXITSTUB:%.*]]
-; CHECK: entry_after_outline.exitStub:
-; CHECK-NEXT: store i8 [[A]], ptr [[TMP2:%.*]], align 1
-; CHECK-NEXT: store i8 [[B]], ptr [[TMP3:%.*]], align 1
-; CHECK-NEXT: ret void
-;
diff --git a/llvm/test/Transforms/IROutliner/different-order-phi-merges.ll b/llvm/test/Transforms/IROutliner/different-order-phi-merges.ll
deleted file mode 100644
index 6730d1bda0f82..0000000000000
--- a/llvm/test/Transforms/IROutliner/different-order-phi-merges.ll
+++ /dev/null
@@ -1,113 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --include-generated-funcs
-; RUN: opt -S -passes=verify,iroutliner -ir-outlining-no-cost < %s | FileCheck %s
-
-; Check that differently ordered phi nodes are not matched when merged, instead
-; generating two output paths.
-
-define void @f1() {
-bb1:
- %0 = add i32 1, 2
- %1 = add i32 3, 4
- %2 = add i32 5, 6
- %3 = add i32 7, 8
- br i1 true, label %bb2, label %bb5
-bb2:
- %4 = mul i32 5, 4
- br label %bb5
-
-placeholder:
- %a = sub i32 5, 4
- ret void
-
-bb5:
- %phinode = phi i32 [%3, %bb1], [%2, %bb2]
- ret void
-}
-
-define void @f2() {
-bb1:
- %0 = add i32 1, 2
- %1 = add i32 3, 4
- %2 = add i32 5, 6
- %3 = add i32 7, 8
- br i1 true, label %bb2, label %bb5
-bb2:
- %4 = mul i32 5, 4
- br label %bb5
-
-placeholder:
- %a = sub i32 5, 4
- ret void
-
-bb5:
- %phinode = phi i32 [%2, %bb1], [%3, %bb2]
- ret void
-}
-; CHECK-LABEL: @f1(
-; CHECK-NEXT: bb1:
-; CHECK-NEXT: [[PHINODE_CE_LOC:%.*]] = alloca i32, align 4
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[PHINODE_CE_LOC]])
-; CHECK-NEXT: [[TMP0:%.*]] = call i1 @outlined_ir_func_0(ptr [[PHINODE_CE_LOC]], i32 0)
-; CHECK-NEXT: [[PHINODE_CE_RELOAD:%.*]] = load i32, ptr [[PHINODE_CE_LOC]], align 4
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[PHINODE_CE_LOC]])
-; CHECK-NEXT: br i1 [[TMP0]], label [[BB5:%.*]], label [[BB1_AFTER_OUTLINE:%.*]]
-; CHECK: bb1_after_outline:
-; CHECK-NEXT: ret void
-; CHECK: bb5:
-; CHECK-NEXT: [[PHINODE:%.*]] = phi i32 [ [[PHINODE_CE_RELOAD]], [[BB1:%.*]] ]
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: @f2(
-; CHECK-NEXT: bb1:
-; CHECK-NEXT: [[PHINODE_CE_LOC:%.*]] = alloca i32, align 4
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[PHINODE_CE_LOC]])
-; CHECK-NEXT: [[TMP0:%.*]] = call i1 @outlined_ir_func_0(ptr [[PHINODE_CE_LOC]], i32 1)
-; CHECK-NEXT: [[PHINODE_CE_RELOAD:%.*]] = load i32, ptr [[PHINODE_CE_LOC]], align 4
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[PHINODE_CE_LOC]])
-; CHECK-NEXT: br i1 [[TMP0]], label [[BB5:%.*]], label [[BB1_AFTER_OUTLINE:%.*]]
-; CHECK: bb1_after_outline:
-; CHECK-NEXT: ret void
-; CHECK: bb5:
-; CHECK-NEXT: [[PHINODE:%.*]] = phi i32 [ [[PHINODE_CE_RELOAD]], [[BB1:%.*]] ]
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: define internal i1 @outlined_ir_func_0(
-; CHECK-NEXT: newFuncRoot:
-; CHECK-NEXT: br label [[BB1_TO_OUTLINE:%.*]]
-; CHECK: bb1_to_outline:
-; CHECK-NEXT: [[TMP2:%.*]] = add i32 1, 2
-; CHECK-NEXT: [[TMP3:%.*]] = add i32 3, 4
-; CHECK-NEXT: [[TMP4:%.*]] = add i32 5, 6
-; CHECK-NEXT: [[TMP5:%.*]] = add i32 7, 8
-; CHECK-NEXT: br i1 true, label [[BB2:%.*]], label [[BB5_SPLIT:%.*]]
-; CHECK: bb2:
-; CHECK-NEXT: [[TMP6:%.*]] = mul i32 5, 4
-; CHECK-NEXT: br label [[BB5_SPLIT]]
-; CHECK: placeholder:
-; CHECK-NEXT: [[A:%.*]] = sub i32 5, 4
-; CHECK-NEXT: br label [[BB1_AFTER_OUTLINE_EXITSTUB:%.*]]
-; CHECK: bb5.split:
-; CHECK-NEXT: [[TMP7:%.*]] = phi i32 [ [[TMP4]], [[BB1_TO_OUTLINE]] ], [ [[TMP5]], [[BB2]] ]
-; CHECK-NEXT: [[PHINODE_CE:%.*]] = phi i32 [ [[TMP5]], [[BB1_TO_OUTLINE]] ], [ [[TMP4]], [[BB2]] ]
-; CHECK-NEXT: br label [[BB5_EXITSTUB:%.*]]
-; CHECK: bb5.exitStub:
-; CHECK-NEXT: switch i32 [[TMP1:%.*]], label [[FINAL_BLOCK_1:%.*]] [
-; CHECK-NEXT: i32 0, label [[OUTPUT_BLOCK_0_1:%.*]]
-; CHECK-NEXT: i32 1, label [[OUTPUT_BLOCK_1_1:%.*]]
-; CHECK-NEXT: ]
-; CHECK: bb1_after_outline.exitStub:
-; CHECK-NEXT: switch i32 [[TMP1]], label [[FINAL_BLOCK_0:%.*]] [
-; CHECK-NEXT: ]
-; CHECK: output_block_0_1:
-; CHECK-NEXT: store i32 [[PHINODE_CE]], ptr [[TMP0:%.*]], align 4
-; CHECK-NEXT: br label [[FINAL_BLOCK_1]]
-; CHECK: output_block_1_1:
-; CHECK-NEXT: store i32 [[TMP7]], ptr [[TMP0]], align 4
-; CHECK-NEXT: br label [[FINAL_BLOCK_1]]
-; CHECK: final_block_0:
-; CHECK-NEXT: ret i1 false
-; CHECK: final_block_1:
-; CHECK-NEXT: ret i1 true
-;
diff --git a/llvm/test/Transforms/IROutliner/duplicate-merging-phis.ll b/llvm/test/Transforms/IROutliner/duplicate-merging-phis.ll
deleted file mode 100644
index 53d52f51f7ad2..0000000000000
--- a/llvm/test/Transforms/IROutliner/duplicate-merging-phis.ll
+++ /dev/null
@@ -1,113 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --include-generated-funcs
-; RUN: opt -S -passes=verify,iroutliner -ir-outlining-no-cost < %s | FileCheck %s
-
-; Make sure that when we merge phi nodes, we do not merge two different PHINodes
-; as the same phi node.
-
-define void @f1() {
-bb1:
- %0 = add i32 1, 2
- %1 = add i32 3, 4
- %2 = add i32 5, 6
- %3 = add i32 7, 8
- br label %bb5
-bb2:
- %4 = mul i32 5, 4
- br label %bb5
-
-placeholder:
- %a = sub i32 5, 4
- ret void
-
-bb5:
- %phinode = phi i32 [5, %bb1], [5, %bb2]
- %phinode1 = phi i32 [5, %bb1], [5, %bb2]
- ret void
-}
-
-define void @f2() {
-bb1:
- %0 = add i32 1, 2
- %1 = add i32 3, 4
- %2 = add i32 5, 6
- %3 = add i32 7, 8
- br label %bb5
-bb2:
- %4 = mul i32 5, 4
- br label %bb5
-
-placeholder:
- %a = sub i32 5, 4
- ret void
-
-bb5:
- %phinode = phi i32 [5, %bb1], [5, %bb2]
- %phinode1 = phi i32 [5, %bb1], [5, %bb2]
- ret void
-}
-; CHECK-LABEL: @f1(
-; CHECK-NEXT: bb1:
-; CHECK-NEXT: [[PHINODE1_CE_LOC:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[PHINODE_CE_LOC:%.*]] = alloca i32, align 4
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[PHINODE_CE_LOC]])
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[PHINODE1_CE_LOC]])
-; CHECK-NEXT: [[TARGETBLOCK:%.*]] = call i1 @outlined_ir_func_0(ptr [[PHINODE_CE_LOC]], ptr [[PHINODE1_CE_LOC]])
-; CHECK-NEXT: [[PHINODE_CE_RELOAD:%.*]] = load i32, ptr [[PHINODE_CE_LOC]], align 4
-; CHECK-NEXT: [[PHINODE1_CE_RELOAD:%.*]] = load i32, ptr [[PHINODE1_CE_LOC]], align 4
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[PHINODE_CE_LOC]])
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[PHINODE1_CE_LOC]])
-; CHECK-NEXT: br i1 [[TARGETBLOCK]], label [[BB5:%.*]], label [[BB1_AFTER_OUTLINE:%.*]]
-; CHECK: bb1_after_outline:
-; CHECK-NEXT: ret void
-; CHECK: bb5:
-; CHECK-NEXT: [[PHINODE:%.*]] = phi i32 [ [[PHINODE_CE_RELOAD]], [[BB1:%.*]] ]
-; CHECK-NEXT: [[PHINODE1:%.*]] = phi i32 [ [[PHINODE1_CE_RELOAD]], [[BB1]] ]
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: @f2(
-; CHECK-NEXT: bb1:
-; CHECK-NEXT: [[PHINODE1_CE_LOC:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[PHINODE_CE_LOC:%.*]] = alloca i32, align 4
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[PHINODE_CE_LOC]])
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[PHINODE1_CE_LOC]])
-; CHECK-NEXT: [[TARGETBLOCK:%.*]] = call i1 @outlined_ir_func_0(ptr [[PHINODE_CE_LOC]], ptr [[PHINODE1_CE_LOC]])
-; CHECK-NEXT: [[PHINODE_CE_RELOAD:%.*]] = load i32, ptr [[PHINODE_CE_LOC]], align 4
-; CHECK-NEXT: [[PHINODE1_CE_RELOAD:%.*]] = load i32, ptr [[PHINODE1_CE_LOC]], align 4
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[PHINODE_CE_LOC]])
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[PHINODE1_CE_LOC]])
-; CHECK-NEXT: br i1 [[TARGETBLOCK]], label [[BB5:%.*]], label [[BB1_AFTER_OUTLINE:%.*]]
-; CHECK: bb1_after_outline:
-; CHECK-NEXT: ret void
-; CHECK: bb5:
-; CHECK-NEXT: [[PHINODE:%.*]] = phi i32 [ [[PHINODE_CE_RELOAD]], [[BB1:%.*]] ]
-; CHECK-NEXT: [[PHINODE1:%.*]] = phi i32 [ [[PHINODE1_CE_RELOAD]], [[BB1]] ]
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: define internal i1 @outlined_ir_func_0(
-; CHECK-NEXT: newFuncRoot:
-; CHECK-NEXT: br label [[BB1_TO_OUTLINE:%.*]]
-; CHECK: bb1_to_outline:
-; CHECK-NEXT: [[TMP2:%.*]] = add i32 1, 2
-; CHECK-NEXT: [[TMP3:%.*]] = add i32 3, 4
-; CHECK-NEXT: [[TMP4:%.*]] = add i32 5, 6
-; CHECK-NEXT: [[TMP5:%.*]] = add i32 7, 8
-; CHECK-NEXT: br label [[BB5_SPLIT:%.*]]
-; CHECK: bb2:
-; CHECK-NEXT: [[TMP6:%.*]] = mul i32 5, 4
-; CHECK-NEXT: br label [[BB5_SPLIT]]
-; CHECK: placeholder:
-; CHECK-NEXT: [[A:%.*]] = sub i32 5, 4
-; CHECK-NEXT: br label [[BB1_AFTER_OUTLINE_EXITSTUB:%.*]]
-; CHECK: bb5.split:
-; CHECK-NEXT: [[PHINODE_CE:%.*]] = phi i32 [ 5, [[BB1_TO_OUTLINE]] ], [ 5, [[BB2:%.*]] ]
-; CHECK-NEXT: [[PHINODE1_CE:%.*]] = phi i32 [ 5, [[BB1_TO_OUTLINE]] ], [ 5, [[BB2]] ]
-; CHECK-NEXT: br label [[BB5_EXITSTUB:%.*]]
-; CHECK: bb5.exitStub:
-; CHECK-NEXT: store i32 [[PHINODE_CE]], ptr [[TMP0:%.*]], align 4
-; CHECK-NEXT: store i32 [[PHINODE1_CE]], ptr [[TMP1:%.*]], align 4
-; CHECK-NEXT: ret i1 true
-; CHECK: bb1_after_outline.exitStub:
-; CHECK-NEXT: ret i1 false
-;
diff --git a/llvm/test/Transforms/IROutliner/exit-block-phi-node-value-attribution.ll b/llvm/test/Transforms/IROutliner/exit-block-phi-node-value-attribution.ll
deleted file mode 100644
index 04ec9284ff5b6..0000000000000
--- a/llvm/test/Transforms/IROutliner/exit-block-phi-node-value-attribution.ll
+++ /dev/null
@@ -1,96 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --include-generated-funcs
-; RUN: opt -S -passes=verify,iroutliner -ir-outlining-no-cost < %s | FileCheck %s
-
-; Make sure that each outlined region only analyzes on the incoming values in exit
-; block phi nodes that come from the outlined region. Without this, more incoming
-; values from the phi node would be considered if the incoming value is
-; included in the outlined region. This is particularly likely to happen for
-; constants.
-
-define void @f1() {
-bb1:
- %0 = add i32 1, 2
- %1 = add i32 3, 4
- %2 = add i32 5, 6
- %3 = add i32 7, 8
- br label %bb5
-bb2:
- %4 = mul i32 5, 4
- br label %bb5
-placeholder:
- %a = sub i32 5, 4
- br label %bb5
-bb3:
- %5 = add i32 1, 2
- %6 = add i32 3, 4
- %7 = add i32 5, 6
- %8 = add i32 7, 8
- br label %bb5
-bb4:
- %9 = mul i32 5, 4
- br label %bb5
-
-placeholder1:
- %b = add i32 5, 4
- ret void
-
-bb5:
- %phinode = phi i32 [5, %placeholder], [5, %bb1], [5, %bb2], [4, %bb3], [4, %bb4]
- ret void
-}
-; CHECK-LABEL: @f1(
-; CHECK-NEXT: bb1:
-; CHECK-NEXT: [[PHINODE_CE_LOC1:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[PHINODE_CE_LOC:%.*]] = alloca i32, align 4
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[PHINODE_CE_LOC]])
-; CHECK-NEXT: call void @outlined_ir_func_0(ptr [[PHINODE_CE_LOC]], i32 0)
-; CHECK-NEXT: [[PHINODE_CE_RELOAD:%.*]] = load i32, ptr [[PHINODE_CE_LOC]], align 4
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[PHINODE_CE_LOC]])
-; CHECK-NEXT: br label [[BB5:%.*]]
-; CHECK: placeholder:
-; CHECK-NEXT: [[A:%.*]] = sub i32 5, 4
-; CHECK-NEXT: br label [[BB5]]
-; CHECK: bb3:
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[PHINODE_CE_LOC1]])
-; CHECK-NEXT: call void @outlined_ir_func_0(ptr [[PHINODE_CE_LOC1]], i32 1)
-; CHECK-NEXT: [[PHINODE_CE_RELOAD2:%.*]] = load i32, ptr [[PHINODE_CE_LOC1]], align 4
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[PHINODE_CE_LOC1]])
-; CHECK-NEXT: br label [[BB5]]
-; CHECK: placeholder1:
-; CHECK-NEXT: [[B:%.*]] = add i32 5, 4
-; CHECK-NEXT: ret void
-; CHECK: bb5:
-; CHECK-NEXT: [[PHINODE:%.*]] = phi i32 [ 5, [[PLACEHOLDER:%.*]] ], [ [[PHINODE_CE_RELOAD]], [[BB1:%.*]] ], [ [[PHINODE_CE_RELOAD2]], [[BB3:%.*]] ]
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: define internal void @outlined_ir_func_0(
-; CHECK-NEXT: newFuncRoot:
-; CHECK-NEXT: br label [[BB1_TO_OUTLINE:%.*]]
-; CHECK: bb1_to_outline:
-; CHECK-NEXT: [[TMP2:%.*]] = add i32 1, 2
-; CHECK-NEXT: [[TMP3:%.*]] = add i32 3, 4
-; CHECK-NEXT: [[TMP4:%.*]] = add i32 5, 6
-; CHECK-NEXT: [[TMP5:%.*]] = add i32 7, 8
-; CHECK-NEXT: br label [[BB5_SPLIT:%.*]]
-; CHECK: bb2:
-; CHECK-NEXT: [[TMP6:%.*]] = mul i32 5, 4
-; CHECK-NEXT: br label [[BB5_SPLIT]]
-; CHECK: bb5.split:
-; CHECK-NEXT: [[TMP7:%.*]] = phi i32 [ 4, [[BB1_TO_OUTLINE]] ], [ 4, [[BB2:%.*]] ]
-; CHECK-NEXT: [[PHINODE_CE:%.*]] = phi i32 [ 5, [[BB1_TO_OUTLINE]] ], [ 5, [[BB2]] ]
-; CHECK-NEXT: br label [[BB5_EXITSTUB:%.*]]
-; CHECK: bb5.exitStub:
-; CHECK-NEXT: switch i32 [[TMP1:%.*]], label [[FINAL_BLOCK_0:%.*]] [
-; CHECK-NEXT: i32 0, label [[OUTPUT_BLOCK_0_0:%.*]]
-; CHECK-NEXT: i32 1, label [[OUTPUT_BLOCK_1_0:%.*]]
-; CHECK-NEXT: ]
-; CHECK: output_block_0_0:
-; CHECK-NEXT: store i32 [[PHINODE_CE]], ptr [[TMP0:%.*]], align 4
-; CHECK-NEXT: br label [[FINAL_BLOCK_0]]
-; CHECK: output_block_1_0:
-; CHECK-NEXT: store i32 [[TMP7]], ptr [[TMP0]], align 4
-; CHECK-NEXT: br label [[FINAL_BLOCK_0]]
-; CHECK: final_block_0:
-; CHECK-NEXT: ret void
-;
diff --git a/llvm/test/Transforms/IROutliner/exit-phi-nodes-incoming-value-constant-argument.ll b/llvm/test/Transforms/IROutliner/exit-phi-nodes-incoming-value-constant-argument.ll
deleted file mode 100644
index 0e82217708d14..0000000000000
--- a/llvm/test/Transforms/IROutliner/exit-phi-nodes-incoming-value-constant-argument.ll
+++ /dev/null
@@ -1,110 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --include-generated-funcs
-; RUN: opt -S -passes=verify,iroutliner -ir-outlining-no-cost < %s | FileCheck %s
-
-; When consolidating PHINodes, the outliner replaces the incoming value with
-; a corresponding value from the first outlined section. When this replaced
-; value is passed in as an argument, the corresponding value is found outside
-; of the outlined region, and must be replaced with an argument to avoid
-; dominating value errors. This checks that we use the argument to replace
-; the incoming value.
-
-define void @func1(i32 %0, i32 %1) local_unnamed_addr #0 {
-bb1:
- br label %bb5
-
-bb2:
- %a = add i32 %0, %1
- %b = add i32 %0, %1
- %c = icmp eq i32 %b, %a
- br i1 %c, label %bb5, label %bb3
-
-bb3:
- %d = add i32 %0, %1
- br label %bb5
-
-bb4:
- %e = sub i32 %0, %1
- br label %bb2
-
-bb5:
- ret void
-}
-
-define void @func2(i32 %0, i32 %1) local_unnamed_addr #0 {
-bb1:
- br label %bb5
-
-bb2:
- %a = sub i32 %0, %1
- %b = add i32 %0, %1
- %c = icmp eq i32 %b, 1
- br i1 %c, label %bb5, label %bb3
-
-bb3:
- %d = add i32 %0, %1
- br label %bb5
-
-bb4:
- %e = add i32 %0, %1
- br label %bb2
-
-bb5:
- %f = phi i32 [ 0, %bb1 ], [ 1, %bb2 ], [ 1, %bb3 ]
- ret void
-}
-; CHECK-LABEL: @func1(
-; CHECK-NEXT: bb1:
-; CHECK-NEXT: br label [[BB5:%.*]]
-; CHECK: bb2:
-; CHECK-NEXT: [[A:%.*]] = add i32 [[TMP0:%.*]], [[TMP1:%.*]]
-; CHECK-NEXT: call void @outlined_ir_func_0(i32 [[TMP0]], i32 [[TMP1]], i32 [[A]], ptr null, i32 -1)
-; CHECK-NEXT: br label [[BB5]]
-; CHECK: bb4:
-; CHECK-NEXT: [[E:%.*]] = sub i32 [[TMP0]], [[TMP1]]
-; CHECK-NEXT: br label [[BB2:%.*]]
-; CHECK: bb5:
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: @func2(
-; CHECK-NEXT: bb1:
-; CHECK-NEXT: [[F_CE_LOC:%.*]] = alloca i32, align 4
-; CHECK-NEXT: br label [[BB5:%.*]]
-; CHECK: bb2:
-; CHECK-NEXT: [[A:%.*]] = sub i32 [[TMP0:%.*]], [[TMP1:%.*]]
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[F_CE_LOC]])
-; CHECK-NEXT: call void @outlined_ir_func_0(i32 [[TMP0]], i32 [[TMP1]], i32 1, ptr [[F_CE_LOC]], i32 0)
-; CHECK-NEXT: [[F_CE_RELOAD:%.*]] = load i32, ptr [[F_CE_LOC]], align 4
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[F_CE_LOC]])
-; CHECK-NEXT: br label [[BB5]]
-; CHECK: bb4:
-; CHECK-NEXT: [[E:%.*]] = add i32 [[TMP0]], [[TMP1]]
-; CHECK-NEXT: br label [[BB2:%.*]]
-; CHECK: bb5:
-; CHECK-NEXT: [[F:%.*]] = phi i32 [ 0, [[BB1:%.*]] ], [ [[F_CE_RELOAD]], [[BB2]] ]
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: define internal void @outlined_ir_func_0(
-; CHECK-NEXT: newFuncRoot:
-; CHECK-NEXT: br label [[BB2_TO_OUTLINE:%.*]]
-; CHECK: bb2_to_outline:
-; CHECK-NEXT: [[B:%.*]] = add i32 [[TMP0:%.*]], [[TMP1:%.*]]
-; CHECK-NEXT: [[C:%.*]] = icmp eq i32 [[B]], [[TMP2:%.*]]
-; CHECK-NEXT: br i1 [[C]], label [[PHI_BLOCK:%.*]], label [[BB3:%.*]]
-; CHECK: bb3:
-; CHECK-NEXT: [[D:%.*]] = add i32 [[TMP0]], [[TMP1]]
-; CHECK-NEXT: br label [[PHI_BLOCK]]
-; CHECK: bb5.exitStub:
-; CHECK-NEXT: switch i32 [[TMP4:%.*]], label [[FINAL_BLOCK_0:%.*]] [
-; CHECK-NEXT: i32 0, label [[OUTPUT_BLOCK_1_0:%.*]]
-; CHECK-NEXT: ]
-; CHECK: output_block_1_0:
-; CHECK-NEXT: store i32 [[TMP5:%.*]], ptr [[TMP3:%.*]], align 4
-; CHECK-NEXT: br label [[FINAL_BLOCK_0]]
-; CHECK: phi_block:
-; CHECK-NEXT: [[TMP5]] = phi i32 [ [[TMP2]], [[BB2_TO_OUTLINE]] ], [ [[TMP2]], [[BB3]] ]
-; CHECK-NEXT: br label [[BB5_EXITSTUB:%.*]]
-; CHECK: final_block_0:
-; CHECK-NEXT: ret void
-;
diff --git a/llvm/test/Transforms/IROutliner/extraction.ll b/llvm/test/Transforms/IROutliner/extraction.ll
deleted file mode 100644
index 77f904dd70861..0000000000000
--- a/llvm/test/Transforms/IROutliner/extraction.ll
+++ /dev/null
@@ -1,127 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt -S -passes=verify,iroutliner -ir-outlining-no-cost < %s | FileCheck %s
-
-; This test makes sure we are extracting the found similarity sections
-; correctly at the call site.
-
-define void @extract1() {
-; CHECK-LABEL: @extract1(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[C:%.*]] = alloca i32, align 4
-; CHECK-NEXT: call void @outlined_ir_func_1(ptr [[A]], ptr [[B]], ptr [[C]])
-; CHECK-NEXT: ret void
-;
-entry:
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- %c = alloca i32, align 4
- store i32 2, ptr %a, align 4
- store i32 3, ptr %b, align 4
- store i32 4, ptr %c, align 4
- %al = load i32, ptr %a
- %bl = load i32, ptr %b
- %cl = load i32, ptr %c
- ret void
-}
-
-define void @extract2() {
-; CHECK-LABEL: @extract2(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[C:%.*]] = alloca i32, align 4
-; CHECK-NEXT: call void @outlined_ir_func_1(ptr [[A]], ptr [[B]], ptr [[C]])
-; CHECK-NEXT: ret void
-;
-entry:
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- %c = alloca i32, align 4
- store i32 2, ptr %a, align 4
- store i32 3, ptr %b, align 4
- store i32 4, ptr %c, align 4
- %al = load i32, ptr %a
- %bl = load i32, ptr %b
- %cl = load i32, ptr %c
- ret void
-}
-
-; There are potential ouptuts in this sections, but we do not extract sections
-; with outputs right now, since they cannot be consolidated.
-define void @extract_outs1() #0 {
-; CHECK-LABEL: @extract_outs1(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[DOTLOC:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[ADD_LOC:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[OUTPUT:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[RESULT:%.*]] = alloca i32, align 4
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[ADD_LOC]])
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[DOTLOC]])
-; CHECK-NEXT: call void @outlined_ir_func_0(ptr [[A]], ptr [[B]], ptr [[OUTPUT]], ptr [[ADD_LOC]], ptr [[DOTLOC]])
-; CHECK-NEXT: [[ADD_RELOAD:%.*]] = load i32, ptr [[ADD_LOC]], align 4
-; CHECK-NEXT: [[DOTRELOAD:%.*]] = load i32, ptr [[DOTLOC]], align 4
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[ADD_LOC]])
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[DOTLOC]])
-; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[OUTPUT]], align 4
-; CHECK-NEXT: call void @outlined_ir_func_2(i32 [[DOTRELOAD]], i32 [[ADD_RELOAD]], ptr [[RESULT]])
-; CHECK-NEXT: ret void
-;
-entry:
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- %output = alloca i32, align 4
- %result = alloca i32, align 4
- store i32 2, ptr %a, align 4
- store i32 3, ptr %b, align 4
- %0 = load i32, ptr %a, align 4
- %1 = load i32, ptr %b, align 4
- %add = add i32 %0, %1
- store i32 %add, ptr %output, align 4
- %2 = load i32, ptr %output, align 4
- %3 = load i32, ptr %output, align 4
- %mul = mul i32 %2, %add
- store i32 %mul, ptr %result, align 4
- ret void
-}
-
-; There are potential ouptuts in this sections, but we do not extract sections
-; with outputs right now, since they cannot be consolidated.
-define void @extract_outs2() #0 {
-; CHECK-LABEL: @extract_outs2(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[DOTLOC:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[ADD_LOC:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[OUTPUT:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[RESULT:%.*]] = alloca i32, align 4
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[ADD_LOC]])
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[DOTLOC]])
-; CHECK-NEXT: call void @outlined_ir_func_0(ptr [[A]], ptr [[B]], ptr [[OUTPUT]], ptr [[ADD_LOC]], ptr [[DOTLOC]])
-; CHECK-NEXT: [[ADD_RELOAD:%.*]] = load i32, ptr [[ADD_LOC]], align 4
-; CHECK-NEXT: [[DOTRELOAD:%.*]] = load i32, ptr [[DOTLOC]], align 4
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[ADD_LOC]])
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[DOTLOC]])
-; CHECK-NEXT: call void @outlined_ir_func_2(i32 [[DOTRELOAD]], i32 [[ADD_RELOAD]], ptr [[RESULT]])
-; CHECK-NEXT: ret void
-;
-entry:
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- %output = alloca i32, align 4
- %result = alloca i32, align 4
- store i32 2, ptr %a, align 4
- store i32 3, ptr %b, align 4
- %0 = load i32, ptr %a, align 4
- %1 = load i32, ptr %b, align 4
- %add = add i32 %0, %1
- store i32 %add, ptr %output, align 4
- %2 = load i32, ptr %output, align 4
- %mul = mul i32 %2, %add
- store i32 %mul, ptr %result, align 4
- ret void
-}
diff --git a/llvm/test/Transforms/IROutliner/gvn-output-set-overload.ll b/llvm/test/Transforms/IROutliner/gvn-output-set-overload.ll
deleted file mode 100644
index 54f013c5652e6..0000000000000
--- a/llvm/test/Transforms/IROutliner/gvn-output-set-overload.ll
+++ /dev/null
@@ -1,119 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --include-generated-funcs
-; RUN: opt -S -passes=verify,iroutliner -ir-outlining-no-cost < %s | FileCheck %s
-
-; Show that we do differentiate between outputs of the region stored in PHINodes
-; versus those stored outside of PHINodes.
-
-define void @function1(ptr %a, ptr %b) {
-entry:
- %0 = alloca i32, align 4
- %c = load i32, ptr %0, align 4
- br label %test1
-test1:
- %e = load i32, ptr %0, align 4
- br i1 true, label %first, label %test
-test:
- %d = load i32, ptr %0, align 4
- br i1 true, label %first, label %next
-first:
- %1 = phi i32 [ %c, %test ], [ %e, %test1 ]
- ret void
-next:
- ret void
-}
-
-define void @function2(ptr %a, ptr %b) {
-entry:
- %0 = alloca i32, align 4
- %c = load i32, ptr %0, align 4
- br label %test1
-test1:
- %e = load i32, ptr %0, align 4
- br i1 true, label %first, label %test
-test:
- %d = load i32, ptr %0, align 4
- br i1 true, label %first, label %next
-first:
- ret void
-next:
- %1 = add i32 %c, 1
- %2 = add i32 %e, 1
- ret void
-}
-; CHECK-LABEL: @function1(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[DOTCE_LOC:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[TMP0:%.*]] = alloca i32, align 4
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[DOTCE_LOC]])
-; CHECK-NEXT: [[TMP1:%.*]] = call i1 @outlined_ir_func_0(ptr [[TMP0]], ptr [[DOTCE_LOC]], ptr null, i32 0)
-; CHECK-NEXT: [[DOTCE_RELOAD:%.*]] = load i32, ptr [[DOTCE_LOC]], align 4
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[DOTCE_LOC]])
-; CHECK-NEXT: br i1 [[TMP1]], label [[FIRST:%.*]], label [[NEXT:%.*]]
-; CHECK: first:
-; CHECK-NEXT: [[TMP2:%.*]] = phi i32 [ [[DOTCE_RELOAD]], [[ENTRY:%.*]] ]
-; CHECK-NEXT: ret void
-; CHECK: next:
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: @function2(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[E_LOC:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[C_LOC:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[TMP0:%.*]] = alloca i32, align 4
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[C_LOC]])
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[E_LOC]])
-; CHECK-NEXT: [[TMP1:%.*]] = call i1 @outlined_ir_func_0(ptr [[TMP0]], ptr [[C_LOC]], ptr [[E_LOC]], i32 1)
-; CHECK-NEXT: [[C_RELOAD:%.*]] = load i32, ptr [[C_LOC]], align 4
-; CHECK-NEXT: [[E_RELOAD:%.*]] = load i32, ptr [[E_LOC]], align 4
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[C_LOC]])
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[E_LOC]])
-; CHECK-NEXT: br i1 [[TMP1]], label [[FIRST:%.*]], label [[NEXT:%.*]]
-; CHECK: first:
-; CHECK-NEXT: ret void
-; CHECK: next:
-; CHECK-NEXT: [[TMP2:%.*]] = add i32 [[C_RELOAD]], 1
-; CHECK-NEXT: [[TMP3:%.*]] = add i32 [[E_RELOAD]], 1
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: define internal i1 @outlined_ir_func_0(
-; CHECK-NEXT: newFuncRoot:
-; CHECK-NEXT: br label [[ENTRY_TO_OUTLINE:%.*]]
-; CHECK: entry_to_outline:
-; CHECK-NEXT: [[C:%.*]] = load i32, ptr [[TMP0:%.*]], align 4
-; CHECK-NEXT: br label [[TEST1:%.*]]
-; CHECK: test1:
-; CHECK-NEXT: [[E:%.*]] = load i32, ptr [[TMP0]], align 4
-; CHECK-NEXT: br i1 true, label [[FIRST_SPLIT:%.*]], label [[TEST:%.*]]
-; CHECK: test:
-; CHECK-NEXT: [[D:%.*]] = load i32, ptr [[TMP0]], align 4
-; CHECK-NEXT: br i1 true, label [[FIRST_SPLIT]], label [[NEXT_EXITSTUB:%.*]]
-; CHECK: first.split:
-; CHECK-NEXT: [[DOTCE:%.*]] = phi i32 [ [[C]], [[TEST]] ], [ [[E]], [[TEST1]] ]
-; CHECK-NEXT: br label [[FIRST_EXITSTUB:%.*]]
-; CHECK: first.exitStub:
-; CHECK-NEXT: switch i32 [[TMP3:%.*]], label [[FINAL_BLOCK_1:%.*]] [
-; CHECK-NEXT: i32 0, label [[OUTPUT_BLOCK_0_1:%.*]]
-; CHECK-NEXT: i32 1, label [[OUTPUT_BLOCK_1_1:%.*]]
-; CHECK-NEXT: ]
-; CHECK: next.exitStub:
-; CHECK-NEXT: switch i32 [[TMP3]], label [[FINAL_BLOCK_0:%.*]] [
-; CHECK-NEXT: i32 0, label [[OUTPUT_BLOCK_1_0:%.*]]
-; CHECK-NEXT: ]
-; CHECK: output_block_0_1:
-; CHECK-NEXT: store i32 [[DOTCE]], ptr [[TMP1:%.*]], align 4
-; CHECK-NEXT: br label [[FINAL_BLOCK_1]]
-; CHECK: output_block_1_0:
-; CHECK-NEXT: store i32 [[C]], ptr [[TMP1]], align 4
-; CHECK-NEXT: store i32 [[E]], ptr [[TMP2:%.*]], align 4
-; CHECK-NEXT: br label [[FINAL_BLOCK_0]]
-; CHECK: output_block_1_1:
-; CHECK-NEXT: store i32 [[C]], ptr [[TMP1]], align 4
-; CHECK-NEXT: store i32 [[E]], ptr [[TMP2]], align 4
-; CHECK-NEXT: br label [[FINAL_BLOCK_1]]
-; CHECK: final_block_0:
-; CHECK-NEXT: ret i1 false
-; CHECK: final_block_1:
-; CHECK-NEXT: ret i1 true
-;
diff --git a/llvm/test/Transforms/IROutliner/gvn-phi-debug.ll b/llvm/test/Transforms/IROutliner/gvn-phi-debug.ll
deleted file mode 100644
index 0c899dcd0339f..0000000000000
--- a/llvm/test/Transforms/IROutliner/gvn-phi-debug.ll
+++ /dev/null
@@ -1,175 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4
-; RUN: opt -S -passes=verify,iroutliner -ir-outlining-no-cost < %s | FileCheck %s
-
-target datalayout = "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"
-target triple = "thumbv7-none-linux-android19"
-
-define i32 @r() {
-; CHECK-LABEL: define i32 @r() {
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[DOTLOC:%.*]] = alloca ptr, align 4
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[DOTLOC]])
-; CHECK-NEXT: [[TMP0:%.*]] = call i1 @outlined_ir_func_0(ptr [[DOTLOC]], i32 0)
-; CHECK-NEXT: [[DOTRELOAD:%.*]] = load ptr, ptr [[DOTLOC]], align 4
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[DOTLOC]])
-; CHECK-NEXT: br i1 [[TMP0]], label [[IF_END8:%.*]], label [[ENTRY_AFTER_OUTLINE:%.*]]
-; CHECK: entry_after_outline:
-; CHECK-NEXT: [[CALL7:%.*]] = call i32 [[DOTRELOAD]]()
-; CHECK-NEXT: br label [[IF_END8]]
-; CHECK: if.end8:
-; CHECK-NEXT: ret i32 0
-;
-entry:
- %.fca.2.insert = insertvalue [5 x i32] zeroinitializer, i32 0, 2
- %.fca.3.load = load i32, ptr null, align 4
- %.fca.3.insert = insertvalue [5 x i32] zeroinitializer, i32 0, 3
- %.fca.4.load = load i32, ptr null, align 4
- %.fca.4.insert = insertvalue [5 x i32] zeroinitializer, i32 0, 4
- %call = call i32 @p()
- %tobool.not = icmp eq i32 0, 0
- br i1 false, label %if.end8, label %if.then
-
-if.then: ; preds = %entry
- %0 = load i32, ptr null, align 4
- %tobool1.not = icmp eq i32 0, 0
- %1 = load i32, ptr null, align 4
- %2 = load i32, ptr null, align 4
- %cond = select i1 false, i32 0, i32 0
- %tobool5.not = icmp eq i32 0, 0
- br i1 false, label %if.end8, label %if.then6
-
-if.then6: ; preds = %if.then
- %3 = load ptr, ptr null, align 4
- %call7 = call i32 %3()
- br label %if.end8
-
-if.end8: ; preds = %if.then6, %if.then, %entry
- ret i32 0
-}
-
-declare i32 @p()
-
-define i32 @u() {
-; CHECK-LABEL: define i32 @u() {
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[TMP0:%.*]] = call i1 @outlined_ir_func_0(ptr null, i32 -1)
-; CHECK-NEXT: br i1 [[TMP0]], label [[IF_END8:%.*]], label [[ENTRY_AFTER_OUTLINE:%.*]]
-; CHECK: entry_after_outline:
-; CHECK-NEXT: br label [[IF_END8]]
-; CHECK: if.end8:
-; CHECK-NEXT: ret i32 0
-;
-entry:
- %.fca.2.insert = insertvalue [5 x i32] zeroinitializer, i32 0, 2
- %.fca.3.load = load i32, ptr null, align 4
- %.fca.3.insert = insertvalue [5 x i32] zeroinitializer, i32 0, 3
- %.fca.4.load = load i32, ptr null, align 4
- %.fca.4.insert = insertvalue [5 x i32] zeroinitializer, i32 0, 4
- %call = call i32 @p()
- %tobool.not = icmp eq i32 0, 0
- br i1 false, label %if.end8, label %if.then
-
-if.then: ; preds = %entry
- %0 = load i32, ptr null, align 4
- %tobool1.not = icmp eq i32 0, 0
- %1 = load i32, ptr null, align 4
- %2 = load i32, ptr null, align 4
- %cond = select i1 false, i32 0, i32 0
- %tobool5.not = icmp eq i32 0, 0
- br i1 false, label %if.end8, label %if.then6
-
-if.then6: ; preds = %if.then
- %3 = load ptr, ptr null, align 4
- br label %if.end8
-
-if.end8: ; preds = %if.then6, %if.then, %entry
- ret i32 0
-}
-
-define i32 @w() !dbg !8 {
-; CHECK-LABEL: define i32 @w(
-; CHECK-SAME: ) !dbg [[DBG8:![0-9]+]] {
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[RETVAL_1_CE_LOC:%.*]] = alloca i32, align 4
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[RETVAL_1_CE_LOC]])
-; CHECK-NEXT: [[TMP0:%.*]] = call i1 @outlined_ir_func_0(ptr [[RETVAL_1_CE_LOC]], i32 1), !dbg [[DBG11:![0-9]+]]
-; CHECK-NEXT: [[RETVAL_1_CE_RELOAD:%.*]] = load i32, ptr [[RETVAL_1_CE_LOC]], align 4
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[RETVAL_1_CE_LOC]])
-; CHECK-NEXT: br i1 [[TMP0]], label [[CLEANUP10:%.*]], label [[ENTRY_AFTER_OUTLINE:%.*]]
-; CHECK: entry_after_outline:
-; CHECK-NEXT: [[CALL8:%.*]] = call i32 @llvm.bswap.i32(i32 0)
-; CHECK-NEXT: br label [[CLEANUP10]]
-; CHECK: cleanup10:
-; CHECK-NEXT: [[RETVAL_1:%.*]] = phi i32 [ 0, [[ENTRY_AFTER_OUTLINE]] ], [ [[RETVAL_1_CE_RELOAD]], [[ENTRY:%.*]] ]
-; CHECK-NEXT: ret i32 0
-;
-entry:
- %.fca.2.insert = insertvalue [5 x i32] zeroinitializer, i32 0, 2
- %.fca.3.load = load i32, ptr null, align 4
- %.fca.3.insert = insertvalue [5 x i32] zeroinitializer, i32 0, 3
- %.fca.4.load = load i32, ptr null, align 4
- %.fca.4.insert = insertvalue [5 x i32] zeroinitializer, i32 0, 4
- %call = call i32 @p()
- %tobool.not = icmp eq i32 0, 0
- br i1 false, label %cleanup10, label %if.then
-
-if.then: ; preds = %entry
- call void @llvm.dbg.value(metadata i32 0, metadata !11, metadata !DIExpression()), !dbg !15
- %0 = load i32, ptr null, align 4
- %tobool1.not = icmp eq i32 0, 0
- %1 = load i32, ptr null, align 4
- %2 = load i32, ptr null, align 4
- %cond = select i1 false, i32 0, i32 0
- %tobool5.not = icmp eq i32 0, 0
- br i1 false, label %cleanup10, label %cleanup
-
-cleanup: ; preds = %if.then
- %3 = load ptr, ptr null, align 4
- %call8 = call i32 @llvm.bswap.i32(i32 0)
- br label %cleanup10
-
-cleanup10: ; preds = %cleanup, %if.then, %entry
- %retval.1 = phi i32 [ 0, %cleanup ], [ 0, %entry ], [ 0, %if.then ]
- ret i32 0
-}
-
-; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
-declare void @llvm.dbg.value(metadata, metadata, metadata) #0
-
-; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
-declare i32 @llvm.bswap.i32(i32) #0
-
-attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }
-
-!llvm.dbg.cu = !{!0}
-!llvm.module.flags = !{!7}
-
-!0 = distinct !DICompileUnit(language: DW_LANG_C11, file: !1, producer: "clang version 18.0.0 (https://github.com/llvm/llvm-project.git 2ca028ce7c6de5f1350440012355a65383b8729a)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, globals: !2, splitDebugInlining: false, nameTableKind: None)
-!1 = !DIFile(filename: "/tmp/foo.c", directory: "/home/davidino/llvm-build-upstream")
-!2 = !{!3}
-!3 = !DIGlobalVariableExpression(var: !4, expr: !DIExpression())
-!4 = distinct !DIGlobalVariable(name: "n", scope: !0, file: !5, line: 19, type: !6, isLocal: false, isDefinition: true)
-!5 = !DIFile(filename: "/tmp/foo.c", directory: "")
-!6 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
-!7 = !{i32 2, !"Debug Info Version", i32 3}
-!8 = distinct !DISubprogram(name: "w", scope: !5, file: !5, line: 54, type: !9, scopeLine: 54, flags: DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !10)
-!9 = !DISubroutineType(types: !10)
-!10 = !{}
-!11 = !DILocalVariable(name: "t", scope: !12, file: !5, line: 57, type: !14)
-!12 = distinct !DILexicalBlock(scope: !13, file: !5, line: 56, column: 17)
-!13 = distinct !DILexicalBlock(scope: !8, file: !5, line: 56, column: 11)
-!14 = !DIDerivedType(tag: DW_TAG_typedef, name: "a", file: !5, line: 2, baseType: !6)
-!15 = !DILocation(line: 0, scope: !12)
-;.
-; CHECK: [[META0:![0-9]+]] = distinct !DICompileUnit(language: DW_LANG_C11, file: [[META1:![0-9]+]], producer: "{{.*}}clang version {{.*}}", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, globals: [[META2:![0-9]+]], splitDebugInlining: false, nameTableKind: None)
-; CHECK: [[META1]] = !DIFile(filename: "/tmp/foo.c", directory: {{.*}})
-; CHECK: [[META2]] = !{[[META3:![0-9]+]]}
-; CHECK: [[META3]] = !DIGlobalVariableExpression(var: [[META4:![0-9]+]], expr: !DIExpression())
-; CHECK: [[META4]] = distinct !DIGlobalVariable(name: "n", scope: [[META0]], file: [[META5:![0-9]+]], line: 19, type: [[META6:![0-9]+]], isLocal: false, isDefinition: true)
-; CHECK: [[META5]] = !DIFile(filename: "/tmp/foo.c", directory: "")
-; CHECK: [[META6]] = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
-; CHECK: [[DBG8]] = distinct !DISubprogram(name: "w", scope: [[META5]], file: [[META5]], line: 54, type: [[META9:![0-9]+]], scopeLine: 54, flags: DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: [[META0]], retainedNodes: [[META10:![0-9]+]])
-; CHECK: [[META9]] = !DISubroutineType(types: [[META10]])
-; CHECK: [[META10]] = !{}
-; CHECK: [[DBG11]] = !DILocation(line: 0, scope: [[DBG8]])
-;.
diff --git a/llvm/test/Transforms/IROutliner/illegal-allocas.ll b/llvm/test/Transforms/IROutliner/illegal-allocas.ll
deleted file mode 100644
index 7dee2f7b3efc3..0000000000000
--- a/llvm/test/Transforms/IROutliner/illegal-allocas.ll
+++ /dev/null
@@ -1,36 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt -S -passes=verify,iroutliner -ir-outlining-no-cost < %s | FileCheck %s
-
-; Show that we do not extract allocas, as outlining allocas may cause
-; inconsistencies with the CodeExtractor's algorithm.
-
-define void @function1() {
-; CHECK-LABEL: @function1(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[C:%.*]] = alloca i32, align 4
-; CHECK-NEXT: ret void
-;
-entry:
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- %c = alloca i32, align 4
-
- ret void
-}
-
-define void @function2() {
-; CHECK-LABEL: @function2(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[C:%.*]] = alloca i32, align 4
-; CHECK-NEXT: ret void
-;
-entry:
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- %c = alloca i32, align 4
- ret void
-}
diff --git a/llvm/test/Transforms/IROutliner/illegal-assumes.ll b/llvm/test/Transforms/IROutliner/illegal-assumes.ll
deleted file mode 100644
index c0c4e1aa42e34..0000000000000
--- a/llvm/test/Transforms/IROutliner/illegal-assumes.ll
+++ /dev/null
@@ -1,143 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt -S -p iroutliner,verify -ir-outlining-no-cost < %s | FileCheck %s
-
-; This test ensures that we do not include llvm.assumes. There are exceptions
-; in the CodeExtractor's algorithm for llvm.assumes, so we ignore it for now.
-
-define void @outline_assumes() {
-; CHECK-LABEL: @outline_assumes(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[DL_LOC:%.*]] = alloca i1, align 1
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[C:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[D:%.*]] = alloca i1, align 4
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[DL_LOC]])
-; CHECK-NEXT: call void @outlined_ir_func_4(i1 true, ptr [[D]], ptr [[DL_LOC]])
-; CHECK-NEXT: [[DL_RELOAD:%.*]] = load i1, ptr [[DL_LOC]], align 1
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[DL_LOC]])
-; CHECK-NEXT: [[SPLIT_INST:%.*]] = sub i1 [[DL_RELOAD]], [[DL_RELOAD]]
-; CHECK-NEXT: call void @outlined_ir_func_1(ptr [[A]], ptr [[B]], ptr [[C]])
-; CHECK-NEXT: call void @llvm.assume(i1 [[DL_RELOAD]])
-; CHECK-NEXT: call void @outlined_ir_func_2(ptr [[A]], ptr [[B]], ptr [[C]])
-; CHECK-NEXT: ret void
-;
-entry:
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- %c = alloca i32, align 4
- %d = alloca i1, align 4
- store i1 1, ptr %d, align 4
- %dl = load i1, ptr %d
- %split_inst = sub i1 %dl, %dl
- store i32 2, ptr %a, align 4
- store i32 3, ptr %b, align 4
- store i32 4, ptr %c, align 4
- call void @llvm.assume(i1 %dl)
- %al = load i32, ptr %a
- %bl = load i32, ptr %b
- %cl = load i32, ptr %c
- ret void
-}
-
-define void @outline_assumes2() {
-; CHECK-LABEL: @outline_assumes2(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[DL_LOC:%.*]] = alloca i1, align 1
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[C:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[D:%.*]] = alloca i1, align 4
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[DL_LOC]])
-; CHECK-NEXT: call void @outlined_ir_func_4(i1 false, ptr [[D]], ptr [[DL_LOC]])
-; CHECK-NEXT: [[DL_RELOAD:%.*]] = load i1, ptr [[DL_LOC]], align 1
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[DL_LOC]])
-; CHECK-NEXT: call void @outlined_ir_func_1(ptr [[A]], ptr [[B]], ptr [[C]])
-; CHECK-NEXT: call void @llvm.assume(i1 [[DL_RELOAD]])
-; CHECK-NEXT: call void @outlined_ir_func_2(ptr [[A]], ptr [[B]], ptr [[C]])
-; CHECK-NEXT: ret void
-;
-entry:
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- %c = alloca i32, align 4
- %d = alloca i1, align 4
- store i1 0, ptr %d, align 4
- %dl = load i1, ptr %d
- store i32 2, ptr %a, align 4
- store i32 3, ptr %b, align 4
- store i32 4, ptr %c, align 4
- call void @llvm.assume(i1 %dl)
- %al = load i32, ptr %a
- %bl = load i32, ptr %b
- %cl = load i32, ptr %c
- ret void
-}
-
-define void @outline_assumes3() {
-; CHECK-LABEL: @outline_assumes3(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[DL_LOC:%.*]] = alloca i1, align 1
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[C:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[D:%.*]] = alloca i1, align 4
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[DL_LOC]])
-; CHECK-NEXT: call void @outlined_ir_func_0(i1 true, ptr [[D]], ptr [[A]], ptr [[B]], ptr [[C]], ptr [[DL_LOC]])
-; CHECK-NEXT: [[DL_RELOAD:%.*]] = load i1, ptr [[DL_LOC]], align 1
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[DL_LOC]])
-; CHECK-NEXT: call void @llvm.assume(i1 [[DL_RELOAD]])
-; CHECK-NEXT: call void @outlined_ir_func_3(ptr [[A]])
-; CHECK-NEXT: ret void
-;
-entry:
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- %c = alloca i32, align 4
- %d = alloca i1, align 4
- store i1 1, ptr %d, align 4
- %dl = load i1, ptr %d
- %split_inst = add i1 %dl, %dl
- store i32 2, ptr %a, align 4
- store i32 3, ptr %b, align 4
- store i32 4, ptr %c, align 4
- call void @llvm.assume(i1 %dl)
- %al = load i32, ptr %a
- %bl = add i32 %al, %al
- ret void
-}
-
-define void @outline_assumes4() {
-; CHECK-LABEL: @outline_assumes4(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[DL_LOC:%.*]] = alloca i1, align 1
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[C:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[D:%.*]] = alloca i1, align 4
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[DL_LOC]])
-; CHECK-NEXT: call void @outlined_ir_func_0(i1 false, ptr [[D]], ptr [[A]], ptr [[B]], ptr [[C]], ptr [[DL_LOC]])
-; CHECK-NEXT: [[DL_RELOAD:%.*]] = load i1, ptr [[DL_LOC]], align 1
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[DL_LOC]])
-; CHECK-NEXT: call void @llvm.assume(i1 [[DL_RELOAD]])
-; CHECK-NEXT: call void @outlined_ir_func_3(ptr [[A]])
-; CHECK-NEXT: ret void
-;
-entry:
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- %c = alloca i32, align 4
- %d = alloca i1, align 4
- store i1 0, ptr %d, align 4
- %dl = load i1, ptr %d
- %split_inst = add i1 %dl, %dl
- store i32 2, ptr %a, align 4
- store i32 3, ptr %b, align 4
- store i32 4, ptr %c, align 4
- call void @llvm.assume(i1 %dl)
- %al = load i32, ptr %a
- %bl = add i32 %al, %al
- ret void
-}
-
-declare void @llvm.assume(i1)
diff --git a/llvm/test/Transforms/IROutliner/illegal-branches.ll b/llvm/test/Transforms/IROutliner/illegal-branches.ll
deleted file mode 100644
index b70d22ab82d90..0000000000000
--- a/llvm/test/Transforms/IROutliner/illegal-branches.ll
+++ /dev/null
@@ -1,51 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt -S -passes=verify,iroutliner -no-ir-sim-branch-matching -ir-outlining-no-cost < %s | FileCheck %s
-
-; Show that we do not extract sections with branches as it would require extra
-; label and control flow checking.
-
-define void @function1() {
-; CHECK-LABEL: @function1(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[C:%.*]] = alloca i32, align 4
-; CHECK-NEXT: call void @outlined_ir_func_0(ptr [[A]], ptr [[B]], ptr [[C]])
-; CHECK-NEXT: br label [[NEXT:%.*]]
-; CHECK: next:
-; CHECK-NEXT: ret void
-;
-entry:
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- %c = alloca i32, align 4
- store i32 2, ptr %a, align 4
- store i32 3, ptr %b, align 4
- store i32 4, ptr %c, align 4
- br label %next
-next:
- ret void
-}
-
-define void @function2() {
-; CHECK-LABEL: @function2(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[C:%.*]] = alloca i32, align 4
-; CHECK-NEXT: call void @outlined_ir_func_0(ptr [[A]], ptr [[B]], ptr [[C]])
-; CHECK-NEXT: br label [[NEXT:%.*]]
-; CHECK: next:
-; CHECK-NEXT: ret void
-;
-entry:
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- %c = alloca i32, align 4
- store i32 2, ptr %a, align 4
- store i32 3, ptr %b, align 4
- store i32 4, ptr %c, align 4
- br label %next
-next:
- ret void
-}
diff --git a/llvm/test/Transforms/IROutliner/illegal-callbr.ll b/llvm/test/Transforms/IROutliner/illegal-callbr.ll
deleted file mode 100644
index cece6b794d2eb..0000000000000
--- a/llvm/test/Transforms/IROutliner/illegal-callbr.ll
+++ /dev/null
@@ -1,64 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt -S -passes=verify,iroutliner -ir-outlining-no-cost < %s | FileCheck %s
-
-; This test checks that we do not outline callbr instruction since as we do not
-; outline any control flow change instructions.
-
-
-define i32 @function1(i32 %a, i32 %b) {
-; CHECK-LABEL: @function1(
-; CHECK-NEXT: bb0:
-; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[A:%.*]], 4
-; CHECK-NEXT: call void @outlined_ir_func_0(i32 [[B:%.*]])
-; CHECK-NEXT: callbr void asm "xorl $0, $0
-; CHECK-NEXT: to label [[NORMAL:%.*]] [label %fail1]
-; CHECK: normal:
-; CHECK-NEXT: call void @outlined_ir_func_0(i32 [[B]])
-; CHECK-NEXT: ret i32 0
-; CHECK: fail1:
-; CHECK-NEXT: call void @outlined_ir_func_0(i32 [[B]])
-; CHECK-NEXT: ret i32 0
-;
-bb0:
- %0 = add i32 %a, 4
- %1 = add i32 %b, 1
- %2 = add i32 %b, 1
- callbr void asm "xorl $0, $0; jmp ${1:l}", "r,!i,~{dirflag},~{fpsr},~{flags}"(i32 %0) to label %normal [label %fail1]
-normal:
- %3 = add i32 %b, 1
- %4 = add i32 %b, 1
- ret i32 0
-fail1:
- %5 = add i32 %b, 1
- %6 = add i32 %b, 1
- ret i32 0
-}
-
-define i32 @function2(i32 %a, i32 %b) {
-; CHECK-LABEL: @function2(
-; CHECK-NEXT: bb0:
-; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[A:%.*]], 4
-; CHECK-NEXT: call void @outlined_ir_func_0(i32 [[B:%.*]])
-; CHECK-NEXT: callbr void asm "xorl $0, $0
-; CHECK-NEXT: to label [[NORMAL:%.*]] [label %fail1]
-; CHECK: normal:
-; CHECK-NEXT: call void @outlined_ir_func_0(i32 [[B]])
-; CHECK-NEXT: ret i32 0
-; CHECK: fail1:
-; CHECK-NEXT: call void @outlined_ir_func_0(i32 [[B]])
-; CHECK-NEXT: ret i32 0
-;
-bb0:
- %0 = add i32 %a, 4
- %1 = add i32 %b, 1
- %2 = add i32 %b, 1
- callbr void asm "xorl $0, $0; jmp ${1:l}", "r,!i,~{dirflag},~{fpsr},~{flags}"(i32 %0) to label %normal [label %fail1]
-normal:
- %3 = add i32 %b, 1
- %4 = add i32 %b, 1
- ret i32 0
-fail1:
- %5 = add i32 %b, 1
- %6 = add i32 %b, 1
- ret i32 0
-}
diff --git a/llvm/test/Transforms/IROutliner/illegal-catchpad.ll b/llvm/test/Transforms/IROutliner/illegal-catchpad.ll
deleted file mode 100644
index a25007fd8034d..0000000000000
--- a/llvm/test/Transforms/IROutliner/illegal-catchpad.ll
+++ /dev/null
@@ -1,70 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt -S -passes=verify,iroutliner -no-ir-sim-branch-matching -ir-outlining-no-cost < %s | FileCheck %s
-
-; This test checks that catchpad instructions are not outlined even if they
-; in a similar section. Dealing with exception handling inside of an outlined
-; function would require a lot of handling that is not implemented yet.
-
-declare void @llvm.donothing() nounwind readnone
-
-define void @function1() personality i8 3 {
-; CHECK-LABEL: @function1(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
-; CHECK-NEXT: invoke void @llvm.donothing()
-; CHECK-NEXT: to label [[NORMAL:%.*]] unwind label [[EXCEPTION:%.*]]
-; CHECK: exception:
-; CHECK-NEXT: [[CS1:%.*]] = catchswitch within none [label %catchpad1] unwind to caller
-; CHECK: catchpad1:
-; CHECK-NEXT: [[TMP0:%.*]] = catchpad within [[CS1]] []
-; CHECK-NEXT: call void @outlined_ir_func_0(ptr [[A]], ptr [[B]])
-; CHECK-NEXT: br label [[NORMAL]]
-; CHECK: normal:
-; CHECK-NEXT: ret void
-;
-entry:
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- invoke void @llvm.donothing() to label %normal unwind label %exception
-exception:
- %cs1 = catchswitch within none [label %catchpad1] unwind to caller
-catchpad1:
- catchpad within %cs1 []
- store i32 2, ptr %a, align 4
- store i32 3, ptr %b, align 4
- br label %normal
-normal:
- ret void
-}
-
-define void @function2() personality i8 3 {
-; CHECK-LABEL: @function2(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
-; CHECK-NEXT: invoke void @llvm.donothing()
-; CHECK-NEXT: to label [[NORMAL:%.*]] unwind label [[EXCEPTION:%.*]]
-; CHECK: exception:
-; CHECK-NEXT: [[CS1:%.*]] = catchswitch within none [label %catchpad1] unwind to caller
-; CHECK: catchpad1:
-; CHECK-NEXT: [[TMP0:%.*]] = catchpad within [[CS1]] []
-; CHECK-NEXT: call void @outlined_ir_func_0(ptr [[A]], ptr [[B]])
-; CHECK-NEXT: br label [[NORMAL]]
-; CHECK: normal:
-; CHECK-NEXT: ret void
-;
-entry:
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- invoke void @llvm.donothing() to label %normal unwind label %exception
-exception:
- %cs1 = catchswitch within none [label %catchpad1] unwind to caller
-catchpad1:
- catchpad within %cs1 []
- store i32 2, ptr %a, align 4
- store i32 3, ptr %b, align 4
- br label %normal
-normal:
- ret void
-}
diff --git a/llvm/test/Transforms/IROutliner/illegal-cleanup.ll b/llvm/test/Transforms/IROutliner/illegal-cleanup.ll
deleted file mode 100644
index b9eeba911f578..0000000000000
--- a/llvm/test/Transforms/IROutliner/illegal-cleanup.ll
+++ /dev/null
@@ -1,62 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt -S -passes=verify,iroutliner -no-ir-sim-branch-matching -ir-outlining-no-cost < %s | FileCheck %s
-
-; This test checks that cleanuppad instructions are not outlined even if they
-; in a similar section. Dealing with exception handling inside of an outlined
-; function would require a lot of handling that is not implemented yet.
-
-declare void @llvm.donothing() nounwind readnone
-
-define void @function1() personality i8 3 {
-; CHECK-LABEL: @function1(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
-; CHECK-NEXT: invoke void @llvm.donothing()
-; CHECK-NEXT: to label [[NORMAL:%.*]] unwind label [[EXCEPTION:%.*]]
-; CHECK: exception:
-; CHECK-NEXT: [[CLEAN:%.*]] = cleanuppad within none []
-; CHECK-NEXT: call void @outlined_ir_func_0(ptr [[A]], ptr [[B]])
-; CHECK-NEXT: br label [[NORMAL]]
-; CHECK: normal:
-; CHECK-NEXT: ret void
-;
-entry:
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- invoke void @llvm.donothing() to label %normal unwind label %exception
-exception:
- %clean = cleanuppad within none []
- store i32 2, ptr %a, align 4
- store i32 3, ptr %b, align 4
- br label %normal
-normal:
- ret void
-}
-
-define void @function2() personality i8 3 {
-; CHECK-LABEL: @function2(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
-; CHECK-NEXT: invoke void @llvm.donothing()
-; CHECK-NEXT: to label [[NORMAL:%.*]] unwind label [[EXCEPTION:%.*]]
-; CHECK: exception:
-; CHECK-NEXT: [[CLEAN:%.*]] = cleanuppad within none []
-; CHECK-NEXT: call void @outlined_ir_func_0(ptr [[A]], ptr [[B]])
-; CHECK-NEXT: br label [[NORMAL]]
-; CHECK: normal:
-; CHECK-NEXT: ret void
-;
-entry:
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- invoke void @llvm.donothing() to label %normal unwind label %exception
-exception:
- %clean = cleanuppad within none []
- store i32 2, ptr %a, align 4
- store i32 3, ptr %b, align 4
- br label %normal
-normal:
- ret void
-}
diff --git a/llvm/test/Transforms/IROutliner/illegal-frozen.ll b/llvm/test/Transforms/IROutliner/illegal-frozen.ll
deleted file mode 100644
index 293f433317bd3..0000000000000
--- a/llvm/test/Transforms/IROutliner/illegal-frozen.ll
+++ /dev/null
@@ -1,49 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt -S -passes=verify,iroutliner -ir-outlining-no-cost < %s | FileCheck %s
-
-; Show that we do not extract freeze instructions, since extra handling is
-; required to mark any outputs used with freeze.
-
-define void @function1(ptr %a, ptr %b) {
-; CHECK-LABEL: @function1(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: br label [[FIRST:%.*]]
-; CHECK: first:
-; CHECK-NEXT: [[C:%.*]] = freeze ptr [[A:%.*]]
-; CHECK-NEXT: call void @outlined_ir_func_0(ptr [[C]], ptr [[B:%.*]])
-; CHECK-NEXT: ret void
-; CHECK: next:
-; CHECK-NEXT: br label [[FIRST]]
-;
-entry:
- br label %first
-first:
- %c = freeze ptr %a
- store i32 2, ptr %c, align 4
- store i32 3, ptr %b, align 4
- ret void
-next:
- br label %first
-}
-
-define void @function2(ptr %a, ptr %b) {
-; CHECK-LABEL: @function2(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: br label [[FIRST:%.*]]
-; CHECK: first:
-; CHECK-NEXT: [[C:%.*]] = freeze ptr [[A:%.*]]
-; CHECK-NEXT: call void @outlined_ir_func_0(ptr [[C]], ptr [[B:%.*]])
-; CHECK-NEXT: ret void
-; CHECK: next:
-; CHECK-NEXT: br label [[FIRST]]
-;
-entry:
- br label %first
-first:
- %c = freeze ptr %a
- store i32 2, ptr %c, align 4
- store i32 3, ptr %b, align 4
- ret void
-next:
- br label %first
-}
diff --git a/llvm/test/Transforms/IROutliner/illegal-indirect-calls.ll b/llvm/test/Transforms/IROutliner/illegal-indirect-calls.ll
deleted file mode 100644
index 76338569707a6..0000000000000
--- a/llvm/test/Transforms/IROutliner/illegal-indirect-calls.ll
+++ /dev/null
@@ -1,58 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt -S -passes=verify,iroutliner -ir-outlining-no-cost --no-ir-sim-indirect-calls < %s | FileCheck %s
-
-; This test checks that we do not outline indirect calls when it is specified
-; that we should not.
-
-declare void @f1(ptr, ptr);
-declare void @f2(ptr, ptr);
-
-define void @function1(ptr %func) {
-; CHECK-LABEL: @function1(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[C:%.*]] = alloca i32, align 4
-; CHECK-NEXT: call void @outlined_ir_func_1(ptr [[A]], ptr [[B]], ptr [[C]])
-; CHECK-NEXT: call void [[FUNC:%.*]]()
-; CHECK-NEXT: call void @outlined_ir_func_0(ptr [[A]], ptr [[B]], ptr [[C]])
-; CHECK-NEXT: ret void
-;
-entry:
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- %c = alloca i32, align 4
- store i32 2, ptr %a, align 4
- store i32 3, ptr %b, align 4
- store i32 4, ptr %c, align 4
- call void %func()
- %al = load i32, ptr %a
- %bl = load i32, ptr %b
- %cl = load i32, ptr %c
- ret void
-}
-
-define void @function2(ptr %func) {
-; CHECK-LABEL: @function2(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[C:%.*]] = alloca i32, align 4
-; CHECK-NEXT: call void @outlined_ir_func_1(ptr [[A]], ptr [[B]], ptr [[C]])
-; CHECK-NEXT: call void [[FUNC:%.*]]()
-; CHECK-NEXT: call void @outlined_ir_func_0(ptr [[A]], ptr [[B]], ptr [[C]])
-; CHECK-NEXT: ret void
-;
-entry:
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- %c = alloca i32, align 4
- store i32 2, ptr %a, align 4
- store i32 3, ptr %b, align 4
- store i32 4, ptr %c, align 4
- call void %func()
- %al = load i32, ptr %a
- %bl = load i32, ptr %b
- %cl = load i32, ptr %c
- ret void
-}
diff --git a/llvm/test/Transforms/IROutliner/illegal-invoke.ll b/llvm/test/Transforms/IROutliner/illegal-invoke.ll
deleted file mode 100644
index 82d62b928a3f8..0000000000000
--- a/llvm/test/Transforms/IROutliner/illegal-invoke.ll
+++ /dev/null
@@ -1,64 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt -S -passes=verify,iroutliner -ir-outlining-no-cost < %s | FileCheck %s
-
-; This test checks that invoke instructions are not outlined even if they
-; in a similar section. Outlining does not currently handle control flow
-; changes.
-
-declare void @llvm.donothing() nounwind readnone
-
-define void @function1() personality i8 3 {
-; CHECK-LABEL: @function1(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
-; CHECK-NEXT: call void @outlined_ir_func_0(ptr [[A]], ptr [[B]])
-; CHECK-NEXT: invoke void @llvm.donothing()
-; CHECK-NEXT: to label [[NORMAL:%.*]] unwind label [[EXCEPTION:%.*]]
-; CHECK: exception:
-; CHECK-NEXT: [[CLEANUP:%.*]] = landingpad i8
-; CHECK-NEXT: cleanup
-; CHECK-NEXT: br label [[NORMAL]]
-; CHECK: normal:
-; CHECK-NEXT: ret void
-;
-entry:
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- store i32 2, ptr %a, align 4
- store i32 3, ptr %b, align 4
- invoke void @llvm.donothing() to label %normal unwind label %exception
-exception:
- %cleanup = landingpad i8 cleanup
- br label %normal
-normal:
- ret void
-}
-
-define void @function2() personality i8 3 {
-; CHECK-LABEL: @function2(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
-; CHECK-NEXT: call void @outlined_ir_func_0(ptr [[A]], ptr [[B]])
-; CHECK-NEXT: invoke void @llvm.donothing()
-; CHECK-NEXT: to label [[NORMAL:%.*]] unwind label [[EXCEPTION:%.*]]
-; CHECK: exception:
-; CHECK-NEXT: [[CLEANUP:%.*]] = landingpad i8
-; CHECK-NEXT: cleanup
-; CHECK-NEXT: br label [[NORMAL]]
-; CHECK: normal:
-; CHECK-NEXT: ret void
-;
-entry:
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- store i32 2, ptr %a, align 4
- store i32 3, ptr %b, align 4
- invoke void @llvm.donothing() to label %normal unwind label %exception
-exception:
- %cleanup = landingpad i8 cleanup
- br label %normal
-normal:
- ret void
-}
diff --git a/llvm/test/Transforms/IROutliner/illegal-landingpad.ll b/llvm/test/Transforms/IROutliner/illegal-landingpad.ll
deleted file mode 100644
index 5d70d55ab6e4e..0000000000000
--- a/llvm/test/Transforms/IROutliner/illegal-landingpad.ll
+++ /dev/null
@@ -1,64 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt -S -passes=verify,iroutliner -no-ir-sim-branch-matching -ir-outlining-no-cost < %s | FileCheck %s
-
-; This test checks that landingpad instructions are not outlined even if they
-; in a similar section. Dealing with exception handling inside of an outlined
-; function would require a lot of handling that is not implemented yet.
-
-declare void @llvm.donothing() nounwind readnone
-
-define void @function1() personality i8 3 {
-; CHECK-LABEL: @function1(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
-; CHECK-NEXT: invoke void @llvm.donothing()
-; CHECK-NEXT: to label [[NORMAL:%.*]] unwind label [[EXCEPTION:%.*]]
-; CHECK: exception:
-; CHECK-NEXT: [[CLEANUP:%.*]] = landingpad i8
-; CHECK-NEXT: cleanup
-; CHECK-NEXT: call void @outlined_ir_func_0(ptr [[A]], ptr [[B]])
-; CHECK-NEXT: br label [[NORMAL]]
-; CHECK: normal:
-; CHECK-NEXT: ret void
-;
-entry:
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- invoke void @llvm.donothing() to label %normal unwind label %exception
-exception:
- %cleanup = landingpad i8 cleanup
- store i32 2, ptr %a, align 4
- store i32 3, ptr %b, align 4
- br label %normal
-normal:
- ret void
-}
-
-define void @function2() personality i8 3 {
-; CHECK-LABEL: @function2(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
-; CHECK-NEXT: invoke void @llvm.donothing()
-; CHECK-NEXT: to label [[NORMAL:%.*]] unwind label [[EXCEPTION:%.*]]
-; CHECK: exception:
-; CHECK-NEXT: [[CLEANUP:%.*]] = landingpad i8
-; CHECK-NEXT: cleanup
-; CHECK-NEXT: call void @outlined_ir_func_0(ptr [[A]], ptr [[B]])
-; CHECK-NEXT: br label [[NORMAL]]
-; CHECK: normal:
-; CHECK-NEXT: ret void
-;
-entry:
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- invoke void @llvm.donothing() to label %normal unwind label %exception
-exception:
- %cleanup = landingpad i8 cleanup
- store i32 2, ptr %a, align 4
- store i32 3, ptr %b, align 4
- br label %normal
-normal:
- ret void
-}
diff --git a/llvm/test/Transforms/IROutliner/illegal-memcpy.ll b/llvm/test/Transforms/IROutliner/illegal-memcpy.ll
deleted file mode 100644
index 523fd23230461..0000000000000
--- a/llvm/test/Transforms/IROutliner/illegal-memcpy.ll
+++ /dev/null
@@ -1,65 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt -S -passes=verify,iroutliner -ir-outlining-no-cost -no-ir-sim-intrinsics < %s | FileCheck %s
-
-; This test checks that we do not outline memcpy intrinsics since it may require
-; extra address space checks.
-
-declare void @llvm.memcpy.p0.p0.i64(ptr nocapture writeonly, ptr nocapture readonly, i64, i1)
-
-define i8 @function1(ptr noalias %s, ptr noalias %d, i64 %len) {
-; CHECK-LABEL: @function1(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[B_LOC:%.*]] = alloca i8, align 1
-; CHECK-NEXT: [[A_LOC:%.*]] = alloca i8, align 1
-; CHECK-NEXT: [[RET_LOC:%.*]] = alloca i8, align 1
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[A_LOC]])
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[B_LOC]])
-; CHECK-NEXT: call void @outlined_ir_func_1(ptr [[S:%.*]], ptr [[D:%.*]], ptr [[A_LOC]], ptr [[B_LOC]])
-; CHECK-NEXT: [[A_RELOAD:%.*]] = load i8, ptr [[A_LOC]], align 1
-; CHECK-NEXT: [[B_RELOAD:%.*]] = load i8, ptr [[B_LOC]], align 1
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[A_LOC]])
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[B_LOC]])
-; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr [[D]], ptr [[S]], i64 [[LEN:%.*]], i1 false)
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[RET_LOC]])
-; CHECK-NEXT: call void @outlined_ir_func_0(i8 [[A_RELOAD]], i8 [[B_RELOAD]], ptr [[S]], ptr [[RET_LOC]])
-; CHECK-NEXT: [[RET_RELOAD:%.*]] = load i8, ptr [[RET_LOC]], align 1
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[RET_LOC]])
-; CHECK-NEXT: ret i8 [[RET_RELOAD]]
-;
-entry:
- %a = load i8, ptr %s
- %b = load i8, ptr %d
- call void @llvm.memcpy.p0.p0.i64(ptr %d, ptr %s, i64 %len, i1 false)
- %c = add i8 %a, %b
- %ret = load i8, ptr %s
- ret i8 %ret
-}
-
-define i8 @function2(ptr noalias %s, ptr noalias %d, i64 %len) {
-; CHECK-LABEL: @function2(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[B_LOC:%.*]] = alloca i8, align 1
-; CHECK-NEXT: [[A_LOC:%.*]] = alloca i8, align 1
-; CHECK-NEXT: [[RET_LOC:%.*]] = alloca i8, align 1
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[A_LOC]])
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[B_LOC]])
-; CHECK-NEXT: call void @outlined_ir_func_1(ptr [[S:%.*]], ptr [[D:%.*]], ptr [[A_LOC]], ptr [[B_LOC]])
-; CHECK-NEXT: [[A_RELOAD:%.*]] = load i8, ptr [[A_LOC]], align 1
-; CHECK-NEXT: [[B_RELOAD:%.*]] = load i8, ptr [[B_LOC]], align 1
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[A_LOC]])
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[B_LOC]])
-; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr [[D]], ptr [[S]], i64 [[LEN:%.*]], i1 false)
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[RET_LOC]])
-; CHECK-NEXT: call void @outlined_ir_func_0(i8 [[A_RELOAD]], i8 [[B_RELOAD]], ptr [[S]], ptr [[RET_LOC]])
-; CHECK-NEXT: [[RET_RELOAD:%.*]] = load i8, ptr [[RET_LOC]], align 1
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[RET_LOC]])
-; CHECK-NEXT: ret i8 [[RET_RELOAD]]
-;
-entry:
- %a = load i8, ptr %s
- %b = load i8, ptr %d
- call void @llvm.memcpy.p0.p0.i64(ptr %d, ptr %s, i64 %len, i1 false)
- %c = add i8 %a, %b
- %ret = load i8, ptr %s
- ret i8 %ret
-}
diff --git a/llvm/test/Transforms/IROutliner/illegal-memmove.ll b/llvm/test/Transforms/IROutliner/illegal-memmove.ll
deleted file mode 100644
index 7482405b9d04d..0000000000000
--- a/llvm/test/Transforms/IROutliner/illegal-memmove.ll
+++ /dev/null
@@ -1,65 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt -S -passes=verify,iroutliner -ir-outlining-no-cost -no-ir-sim-intrinsics < %s | FileCheck %s
-
-; This test checks that we do not outline memcpy intrinsics since it may require
-; extra address space checks.
-
-declare void @llvm.memmove.p0.p0.i64(ptr nocapture writeonly, ptr nocapture readonly, i64, i1)
-
-define i8 @function1(ptr noalias %s, ptr noalias %d, i64 %len) {
-; CHECK-LABEL: @function1(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[B_LOC:%.*]] = alloca i8, align 1
-; CHECK-NEXT: [[A_LOC:%.*]] = alloca i8, align 1
-; CHECK-NEXT: [[RET_LOC:%.*]] = alloca i8, align 1
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[A_LOC]])
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[B_LOC]])
-; CHECK-NEXT: call void @outlined_ir_func_1(ptr [[S:%.*]], ptr [[D:%.*]], ptr [[A_LOC]], ptr [[B_LOC]])
-; CHECK-NEXT: [[A_RELOAD:%.*]] = load i8, ptr [[A_LOC]], align 1
-; CHECK-NEXT: [[B_RELOAD:%.*]] = load i8, ptr [[B_LOC]], align 1
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[A_LOC]])
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[B_LOC]])
-; CHECK-NEXT: call void @llvm.memmove.p0.p0.i64(ptr [[D]], ptr [[S]], i64 [[LEN:%.*]], i1 false)
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[RET_LOC]])
-; CHECK-NEXT: call void @outlined_ir_func_0(i8 [[A_RELOAD]], i8 [[B_RELOAD]], ptr [[S]], ptr [[RET_LOC]])
-; CHECK-NEXT: [[RET_RELOAD:%.*]] = load i8, ptr [[RET_LOC]], align 1
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[RET_LOC]])
-; CHECK-NEXT: ret i8 [[RET_RELOAD]]
-;
-entry:
- %a = load i8, ptr %s
- %b = load i8, ptr %d
- call void @llvm.memmove.p0.p0.i64(ptr %d, ptr %s, i64 %len, i1 false)
- %c = add i8 %a, %b
- %ret = load i8, ptr %s
- ret i8 %ret
-}
-
-define i8 @function2(ptr noalias %s, ptr noalias %d, i64 %len) {
-; CHECK-LABEL: @function2(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[B_LOC:%.*]] = alloca i8, align 1
-; CHECK-NEXT: [[A_LOC:%.*]] = alloca i8, align 1
-; CHECK-NEXT: [[RET_LOC:%.*]] = alloca i8, align 1
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[A_LOC]])
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[B_LOC]])
-; CHECK-NEXT: call void @outlined_ir_func_1(ptr [[S:%.*]], ptr [[D:%.*]], ptr [[A_LOC]], ptr [[B_LOC]])
-; CHECK-NEXT: [[A_RELOAD:%.*]] = load i8, ptr [[A_LOC]], align 1
-; CHECK-NEXT: [[B_RELOAD:%.*]] = load i8, ptr [[B_LOC]], align 1
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[A_LOC]])
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[B_LOC]])
-; CHECK-NEXT: call void @llvm.memmove.p0.p0.i64(ptr [[D]], ptr [[S]], i64 [[LEN:%.*]], i1 false)
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[RET_LOC]])
-; CHECK-NEXT: call void @outlined_ir_func_0(i8 [[A_RELOAD]], i8 [[B_RELOAD]], ptr [[S]], ptr [[RET_LOC]])
-; CHECK-NEXT: [[RET_RELOAD:%.*]] = load i8, ptr [[RET_LOC]], align 1
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[RET_LOC]])
-; CHECK-NEXT: ret i8 [[RET_RELOAD]]
-;
-entry:
- %a = load i8, ptr %s
- %b = load i8, ptr %d
- call void @llvm.memmove.p0.p0.i64(ptr %d, ptr %s, i64 %len, i1 false)
- %c = add i8 %a, %b
- %ret = load i8, ptr %s
- ret i8 %ret
-}
diff --git a/llvm/test/Transforms/IROutliner/illegal-memset.ll b/llvm/test/Transforms/IROutliner/illegal-memset.ll
deleted file mode 100644
index 34658ec85fa5e..0000000000000
--- a/llvm/test/Transforms/IROutliner/illegal-memset.ll
+++ /dev/null
@@ -1,41 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt -S -passes=verify,iroutliner -ir-outlining-no-cost -no-ir-sim-intrinsics < %s | FileCheck %s
-
-; This test checks that we do not outline memset intrinsics since it requires
-; extra address space checks.
-
-declare void @llvm.memset.p0.i64(ptr nocapture writeonly, i8, i64, i32, i1)
-
-define i64 @function1(i64 %x, i64 %z, i64 %n) {
-; CHECK-LABEL: @function1(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[POOL:%.*]] = alloca [59 x i64], align 4
-; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr nonnull align 4 [[POOL]], i8 0, i64 236, i1 false)
-; CHECK-NEXT: call void @outlined_ir_func_0(i64 [[N:%.*]], i64 [[X:%.*]], i64 [[Z:%.*]])
-; CHECK-NEXT: ret i64 0
-;
-entry:
- %pool = alloca [59 x i64], align 4
- call void @llvm.memset.p0.i64(ptr nonnull %pool, i8 0, i64 236, i32 4, i1 false)
- %cmp3 = icmp eq i64 %n, 0
- %a = add i64 %x, %z
- %c = add i64 %x, %z
- ret i64 0
-}
-
-define i64 @function2(i64 %x, i64 %z, i64 %n) {
-; CHECK-LABEL: @function2(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[POOL:%.*]] = alloca [59 x i64], align 4
-; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr nonnull align 4 [[POOL]], i8 0, i64 236, i1 false)
-; CHECK-NEXT: call void @outlined_ir_func_0(i64 [[N:%.*]], i64 [[X:%.*]], i64 [[Z:%.*]])
-; CHECK-NEXT: ret i64 0
-;
-entry:
- %pool = alloca [59 x i64], align 4
- call void @llvm.memset.p0.i64(ptr nonnull %pool, i8 0, i64 236, i32 4, i1 false)
- %cmp3 = icmp eq i64 %n, 0
- %a = add i64 %x, %z
- %c = add i64 %x, %z
- ret i64 0
-}
diff --git a/llvm/test/Transforms/IROutliner/illegal-nomerge.ll b/llvm/test/Transforms/IROutliner/illegal-nomerge.ll
deleted file mode 100644
index d0b367184dc96..0000000000000
--- a/llvm/test/Transforms/IROutliner/illegal-nomerge.ll
+++ /dev/null
@@ -1,104 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --include-generated-funcs --version 6
-; RUN: opt -S -passes=verify,iroutliner -ir-outlining-no-cost < %s | FileCheck %s
-
-; Verify that the IR outliner refuses to outline regions that contain
-; callsites marked with `nomerge`.
-
-declare void @f1(ptr, ptr);
-declare void @f2(ptr, ptr);
-
-define void @function1() {
-entry:
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- %c = alloca i32, align 4
- store i32 2, ptr %a, align 4
- store i32 3, ptr %b, align 4
- store i32 4, ptr %c, align 4
- call void @f1(ptr %a, ptr %b) nomerge
- %al = load i32, ptr %a
- %bl = load i32, ptr %b
- %cl = load i32, ptr %c
- ret void
-}
-
-define void @function2() {
-entry:
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- %c = alloca i32, align 4
- store i32 2, ptr %a, align 4
- store i32 3, ptr %b, align 4
- store i32 4, ptr %c, align 4
- call void @f1(ptr %a, ptr %b) nomerge
- %al = load i32, ptr %a
- %bl = load i32, ptr %b
- %cl = load i32, ptr %c
- ret void
-}
-
-define void @function3() {
-entry:
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- %c = alloca i32, align 4
- store i32 2, ptr %a, align 4
- store i32 3, ptr %b, align 4
- store i32 4, ptr %c, align 4
- call void @f2(ptr %a, ptr %b) nomerge
- %al = load i32, ptr %a
- %bl = load i32, ptr %b
- %cl = load i32, ptr %c
- ret void
-}
-; CHECK-LABEL: define void @function1() {
-; CHECK-NEXT: [[ENTRY:.*:]]
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[C:%.*]] = alloca i32, align 4
-; CHECK-NEXT: store i32 2, ptr [[A]], align 4
-; CHECK-NEXT: store i32 3, ptr [[B]], align 4
-; CHECK-NEXT: store i32 4, ptr [[C]], align 4
-; CHECK-NEXT: call void @f1(ptr [[A]], ptr [[B]]) #[[ATTR1:[0-9]+]]
-; CHECK-NEXT: call void @outlined_ir_func_0(ptr [[A]], ptr [[B]], ptr [[C]])
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: define void @function2() {
-; CHECK-NEXT: [[ENTRY:.*:]]
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[C:%.*]] = alloca i32, align 4
-; CHECK-NEXT: store i32 2, ptr [[A]], align 4
-; CHECK-NEXT: store i32 3, ptr [[B]], align 4
-; CHECK-NEXT: store i32 4, ptr [[C]], align 4
-; CHECK-NEXT: call void @f1(ptr [[A]], ptr [[B]]) #[[ATTR1]]
-; CHECK-NEXT: call void @outlined_ir_func_0(ptr [[A]], ptr [[B]], ptr [[C]])
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: define void @function3() {
-; CHECK-NEXT: [[ENTRY:.*:]]
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[C:%.*]] = alloca i32, align 4
-; CHECK-NEXT: store i32 2, ptr [[A]], align 4
-; CHECK-NEXT: store i32 3, ptr [[B]], align 4
-; CHECK-NEXT: store i32 4, ptr [[C]], align 4
-; CHECK-NEXT: call void @f2(ptr [[A]], ptr [[B]]) #[[ATTR1]]
-; CHECK-NEXT: call void @outlined_ir_func_0(ptr [[A]], ptr [[B]], ptr [[C]])
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: define internal void @outlined_ir_func_0(
-; CHECK-SAME: ptr [[TMP0:%.*]], ptr [[TMP1:%.*]], ptr [[TMP2:%.*]]) #[[ATTR0:[0-9]+]] {
-; CHECK-NEXT: [[NEWFUNCROOT:.*:]]
-; CHECK-NEXT: br label %[[ENTRY_TO_OUTLINE:.*]]
-; CHECK: [[ENTRY_TO_OUTLINE]]:
-; CHECK-NEXT: [[AL:%.*]] = load i32, ptr [[TMP0]], align 4
-; CHECK-NEXT: [[BL:%.*]] = load i32, ptr [[TMP1]], align 4
-; CHECK-NEXT: [[CL:%.*]] = load i32, ptr [[TMP2]], align 4
-; CHECK-NEXT: br label %[[ENTRY_AFTER_OUTLINE_EXITSTUB:.*]]
-; CHECK: [[ENTRY_AFTER_OUTLINE_EXITSTUB]]:
-; CHECK-NEXT: ret void
-;
diff --git a/llvm/test/Transforms/IROutliner/illegal-phi-nodes.ll b/llvm/test/Transforms/IROutliner/illegal-phi-nodes.ll
deleted file mode 100644
index 46d069d5afcc0..0000000000000
--- a/llvm/test/Transforms/IROutliner/illegal-phi-nodes.ll
+++ /dev/null
@@ -1,49 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt -S -passes=verify,iroutliner -ir-outlining-no-cost < %s | FileCheck %s
-
-; Show that we do not extract phi nodes as it would require extra label and
-; control flow checking.
-
-define void @function1(ptr %a, ptr %b) {
-; CHECK-LABEL: @function1(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: br label [[FIRST:%.*]]
-; CHECK: first:
-; CHECK-NEXT: [[TMP0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ 3, [[NEXT:%.*]] ]
-; CHECK-NEXT: call void @outlined_ir_func_0(ptr [[A:%.*]], ptr [[B:%.*]])
-; CHECK-NEXT: ret void
-; CHECK: next:
-; CHECK-NEXT: br label [[FIRST]]
-;
-entry:
- br label %first
-first:
- %0 = phi i32 [ 0, %entry ], [ 3, %next ]
- store i32 2, ptr %a, align 4
- store i32 3, ptr %b, align 4
- ret void
-next:
- br label %first
-}
-
-define void @function2(ptr %a, ptr %b) {
-; CHECK-LABEL: @function2(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: br label [[FIRST:%.*]]
-; CHECK: first:
-; CHECK-NEXT: [[TMP0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ 3, [[NEXT:%.*]] ]
-; CHECK-NEXT: call void @outlined_ir_func_0(ptr [[A:%.*]], ptr [[B:%.*]])
-; CHECK-NEXT: ret void
-; CHECK: next:
-; CHECK-NEXT: br label [[FIRST]]
-;
-entry:
- br label %first
-first:
- %0 = phi i32 [ 0, %entry ], [ 3, %next ]
- store i32 2, ptr %a, align 4
- store i32 3, ptr %b, align 4
- ret void
-next:
- br label %first
-}
diff --git a/llvm/test/Transforms/IROutliner/illegal-returns-twice.ll b/llvm/test/Transforms/IROutliner/illegal-returns-twice.ll
deleted file mode 100644
index a520cb1b54cef..0000000000000
--- a/llvm/test/Transforms/IROutliner/illegal-returns-twice.ll
+++ /dev/null
@@ -1,66 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt -S -passes=verify,iroutliner -ir-outlining-no-cost < %s | FileCheck %s
-
-; This test checks that we do not outline functions that are marked as returns
-; twice, since these can alter the frame of the function and affect how the
-; outliner behaves, causing miscompiles.
-
-; Function Attrs: optsize returns_twice
-declare i32 @setjmp(ptr) local_unnamed_addr #1
- at tmp_jmpb = global [37 x i32] zeroinitializer, align 16
-
-define void @function1() {
-; CHECK-LABEL: @function1(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[C:%.*]] = alloca i32, align 4
-; CHECK-NEXT: store i32 2, ptr [[A]], align 4
-; CHECK-NEXT: store i32 3, ptr [[B]], align 4
-; CHECK-NEXT: store i32 4, ptr [[C]], align 4
-; CHECK-NEXT: [[CALL:%.*]] = call i32 @setjmp(ptr @tmp_jmpb)
-; CHECK-NEXT: call void @outlined_ir_func_0(ptr [[A]], ptr [[B]], ptr [[C]])
-; CHECK-NEXT: ret void
-;
-entry:
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- %c = alloca i32, align 4
- store i32 2, ptr %a, align 4
- store i32 3, ptr %b, align 4
- store i32 4, ptr %c, align 4
- %call = call i32 @setjmp(ptr @tmp_jmpb)
- %al = load i32, ptr %a
- %bl = load i32, ptr %b
- %cl = load i32, ptr %c
- ret void
-}
-
-define void @function2() {
-; CHECK-LABEL: @function2(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[C:%.*]] = alloca i32, align 4
-; CHECK-NEXT: store i32 2, ptr [[A]], align 4
-; CHECK-NEXT: store i32 3, ptr [[B]], align 4
-; CHECK-NEXT: store i32 4, ptr [[C]], align 4
-; CHECK-NEXT: [[CALL:%.*]] = call i32 @setjmp(ptr @tmp_jmpb)
-; CHECK-NEXT: call void @outlined_ir_func_0(ptr [[A]], ptr [[B]], ptr [[C]])
-; CHECK-NEXT: ret void
-;
-entry:
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- %c = alloca i32, align 4
- store i32 2, ptr %a, align 4
- store i32 3, ptr %b, align 4
- store i32 4, ptr %c, align 4
- %call = call i32 @setjmp(ptr @tmp_jmpb)
- %al = load i32, ptr %a
- %bl = load i32, ptr %b
- %cl = load i32, ptr %c
- ret void
-}
-
-attributes #1 = { optsize returns_twice }
diff --git a/llvm/test/Transforms/IROutliner/illegal-typeid-for.ll b/llvm/test/Transforms/IROutliner/illegal-typeid-for.ll
deleted file mode 100644
index f15504cd10dae..0000000000000
--- a/llvm/test/Transforms/IROutliner/illegal-typeid-for.ll
+++ /dev/null
@@ -1,127 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --include-generated-funcs --version 6
-; RUN: opt -S -passes=verify,iroutliner -ir-outlining-no-cost -no-ir-sim-intrinsics=0 < %s | FileCheck %s
-
-; Verify that @llvm.eh.typeid.for is not outlined
-
-%C6object9ClassInfo = type { ptr, ptr }
-%C6object9ClassInfo__vtbl = type { ptr }
-
- at C6object9ClassInfo__ClassInfo = linkonce_odr constant %C6object9ClassInfo { ptr @C6object9ClassInfo__vtblZ, ptr @C6object8TypeInfo__ClassInfo }
- at C6object9ClassInfo__vtblZ = linkonce_odr constant %C6object9ClassInfo__vtbl { ptr @C6object9ClassInfo__ClassInfo }
- at C6object8TypeInfo__ClassInfo = linkonce_odr constant %C6object9ClassInfo { ptr @C6object9ClassInfo__vtblZ, ptr @C6object6Object__ClassInfo }
- at C6object6Object__ClassInfo = linkonce_odr constant %C6object9ClassInfo { ptr @C6object9ClassInfo__vtblZ, ptr @C6object6Object__ClassInfo }
- at C6object9Throwable__ClassInfo = linkonce_odr constant %C6object9ClassInfo { ptr @C6object9ClassInfo__vtblZ, ptr @C6object6Object__ClassInfo }
-
-declare i32 @__sd_eh_personality(i32, i32, i64, ptr, ptr)
-
-declare void @test2(ptr)
-declare void @test3(ptr)
-declare void @test4(ptr)
-
-define i32 @test1(ptr %arg0) personality ptr @__sd_eh_personality {
-body:
- invoke void @test2(ptr %arg0) to label %then1 unwind label %lpad1
-
-then1:
- invoke void @test3(ptr %arg0) to label %then2 unwind label %lpad2
-
-then2:
- invoke void @test4(ptr %arg0) to label %then3 unwind label %lpad3
-
-then3:
- ret i32 0
-
-unwind:
- %0 = phi { ptr, i32 } [ %1, %lpad1 ], [ %5, %lpad2 ], [ %9, %lpad3 ]
- resume { ptr, i32 } %0
-
-lpad1:
- %1 = landingpad { ptr, i32 } cleanup catch ptr @C6object9Throwable__ClassInfo
- %2 = extractvalue { ptr, i32 } %1, 1
- %3 = call i32 @llvm.eh.typeid.for(ptr nonnull @C6object9Throwable__ClassInfo)
- %4 = icmp eq i32 %3, %2
- br i1 %4, label %catch1, label %unwind
-
-catch1:
- ret i32 1
-
-lpad2:
- %5 = landingpad { ptr, i32 } cleanup catch ptr @C6object9Throwable__ClassInfo
- %6 = extractvalue { ptr, i32 } %5, 1
- %7 = call i32 @llvm.eh.typeid.for(ptr nonnull @C6object9Throwable__ClassInfo)
- %8 = icmp eq i32 %7, %6
- br i1 %8, label %catch2, label %unwind
-
-catch2:
- ret i32 2
-
-lpad3:
- %9 = landingpad { ptr, i32 } cleanup catch ptr @C6object9Throwable__ClassInfo
- %10 = extractvalue { ptr, i32 } %9, 1
- %11 = call i32 @llvm.eh.typeid.for(ptr nonnull @C6object9Throwable__ClassInfo)
- %12 = icmp eq i32 %11, %10
- br i1 %12, label %catch2, label %unwind
-
-catch3:
- ret i32 3
-}
-; CHECK-LABEL: define i32 @test1(
-; CHECK-SAME: ptr [[ARG0:%.*]]) personality ptr @__sd_eh_personality {
-; CHECK-NEXT: [[BODY:.*:]]
-; CHECK-NEXT: invoke void @test2(ptr [[ARG0]])
-; CHECK-NEXT: to label %[[THEN1:.*]] unwind label %[[LPAD1:.*]]
-; CHECK: [[THEN1]]:
-; CHECK-NEXT: invoke void @test3(ptr [[ARG0]])
-; CHECK-NEXT: to label %[[THEN2:.*]] unwind label %[[LPAD2:.*]]
-; CHECK: [[THEN2]]:
-; CHECK-NEXT: invoke void @test4(ptr [[ARG0]])
-; CHECK-NEXT: to label %[[THEN3:.*]] unwind label %[[UNWIND2:.*]]
-; CHECK: [[THEN3]]:
-; CHECK-NEXT: ret i32 0
-; CHECK: [[UNWIND1:.*]]:
-; CHECK-NEXT: [[TMP6:%.*]] = phi { ptr, i32 } [ [[TMP0:%.*]], %[[LPAD1]] ], [ [[TMP3:%.*]], %[[LPAD2]] ], [ [[TMP7:%.*]], %[[UNWIND2]] ]
-; CHECK-NEXT: resume { ptr, i32 } [[TMP6]]
-; CHECK: [[LPAD1]]:
-; CHECK-NEXT: [[TMP0]] = landingpad { ptr, i32 }
-; CHECK-NEXT: cleanup
-; CHECK-NEXT: catch ptr @C6object9Throwable__ClassInfo
-; CHECK-NEXT: [[TMP1:%.*]] = extractvalue { ptr, i32 } [[TMP0]], 1
-; CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.eh.typeid.for.p0(ptr nonnull @C6object9Throwable__ClassInfo)
-; CHECK-NEXT: [[TARGETBLOCK:%.*]] = call i1 @outlined_ir_func_0(i32 [[TMP2]], i32 [[TMP1]])
-; CHECK-NEXT: br i1 [[TARGETBLOCK]], label %[[CATCH1:.*]], label %[[UNWIND1]]
-; CHECK: [[CATCH1]]:
-; CHECK-NEXT: ret i32 1
-; CHECK: [[LPAD2]]:
-; CHECK-NEXT: [[TMP3]] = landingpad { ptr, i32 }
-; CHECK-NEXT: cleanup
-; CHECK-NEXT: catch ptr @C6object9Throwable__ClassInfo
-; CHECK-NEXT: [[TMP4:%.*]] = extractvalue { ptr, i32 } [[TMP3]], 1
-; CHECK-NEXT: [[TMP5:%.*]] = call i32 @llvm.eh.typeid.for.p0(ptr nonnull @C6object9Throwable__ClassInfo)
-; CHECK-NEXT: [[TARGETBLOCK1:%.*]] = call i1 @outlined_ir_func_0(i32 [[TMP5]], i32 [[TMP4]])
-; CHECK-NEXT: br i1 [[TARGETBLOCK1]], label %[[CATCH2:.*]], label %[[UNWIND1]]
-; CHECK: [[CATCH2]]:
-; CHECK-NEXT: ret i32 2
-; CHECK: [[UNWIND2]]:
-; CHECK-NEXT: [[TMP7]] = landingpad { ptr, i32 }
-; CHECK-NEXT: cleanup
-; CHECK-NEXT: catch ptr @C6object9Throwable__ClassInfo
-; CHECK-NEXT: [[TMP8:%.*]] = extractvalue { ptr, i32 } [[TMP7]], 1
-; CHECK-NEXT: [[TMP9:%.*]] = call i32 @llvm.eh.typeid.for.p0(ptr nonnull @C6object9Throwable__ClassInfo)
-; CHECK-NEXT: [[TARGETBLOCK2:%.*]] = call i1 @outlined_ir_func_0(i32 [[TMP9]], i32 [[TMP8]])
-; CHECK-NEXT: br i1 [[TARGETBLOCK2]], label %[[CATCH2]], label %[[UNWIND1]]
-; CHECK: [[CATCH3:.*:]]
-; CHECK-NEXT: ret i32 3
-;
-;
-; CHECK-LABEL: define internal i1 @outlined_ir_func_0(
-; CHECK-SAME: i32 [[TMP0:%.*]], i32 [[TMP1:%.*]]) #[[ATTR1:[0-9]+]] {
-; CHECK-NEXT: [[NEWFUNCROOT:.*:]]
-; CHECK-NEXT: br label %[[LPAD1_TO_OUTLINE:.*]]
-; CHECK: [[LPAD1_TO_OUTLINE]]:
-; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]]
-; CHECK-NEXT: br i1 [[TMP2]], label %[[CATCH1_EXITSTUB:.*]], label %[[UNWIND1_EXITSTUB:.*]]
-; CHECK: [[CATCH1_EXITSTUB]]:
-; CHECK-NEXT: ret i1 true
-; CHECK: [[UNWIND1_EXITSTUB]]:
-; CHECK-NEXT: ret i1 false
-;
diff --git a/llvm/test/Transforms/IROutliner/illegal-vaarg.ll b/llvm/test/Transforms/IROutliner/illegal-vaarg.ll
deleted file mode 100644
index 15f9aa2f5932a..0000000000000
--- a/llvm/test/Transforms/IROutliner/illegal-vaarg.ll
+++ /dev/null
@@ -1,79 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt -S -passes=verify,iroutliner -ir-outlining-no-cost -no-ir-sim-intrinsics < %s | FileCheck %s
-
-; This test ensures that we do not outline vararg instructions or intrinsics, as
-; they may cause inconsistencies when outlining.
-
-declare void @llvm.va_start(ptr)
-declare void @llvm.va_copy(ptr, ptr)
-declare void @llvm.va_end(ptr)
-
-define i32 @func1(i32 %a, double %b, ptr %v, ...) nounwind {
-; CHECK-LABEL: @func1(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[TMP_LOC:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B_ADDR:%.*]] = alloca double, align 8
-; CHECK-NEXT: [[AP:%.*]] = alloca ptr, align 4
-; CHECK-NEXT: [[C:%.*]] = alloca i32, align 4
-; CHECK-NEXT: call void @outlined_ir_func_0(i32 [[A:%.*]], ptr [[A_ADDR]], double [[B:%.*]], ptr [[B_ADDR]])
-; CHECK-NEXT: call void @llvm.va_start.p0(ptr [[AP]])
-; CHECK-NEXT: [[TMP0:%.*]] = va_arg ptr [[AP]], i32
-; CHECK-NEXT: call void @llvm.va_copy.p0(ptr [[V:%.*]], ptr [[AP]])
-; CHECK-NEXT: call void @llvm.va_end.p0(ptr [[AP]])
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[TMP_LOC]])
-; CHECK-NEXT: call void @outlined_ir_func_1(i32 [[TMP0]], ptr [[C]], ptr [[TMP_LOC]])
-; CHECK-NEXT: [[TMP_RELOAD:%.*]] = load i32, ptr [[TMP_LOC]], align 4
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[TMP_LOC]])
-; CHECK-NEXT: ret i32 [[TMP_RELOAD]]
-;
-entry:
- %a.addr = alloca i32, align 4
- %b.addr = alloca double, align 8
- %ap = alloca ptr, align 4
- %c = alloca i32, align 4
- store i32 %a, ptr %a.addr, align 4
- store double %b, ptr %b.addr, align 8
- call void @llvm.va_start(ptr %ap)
- %0 = va_arg ptr %ap, i32
- call void @llvm.va_copy(ptr %v, ptr %ap)
- call void @llvm.va_end(ptr %ap)
- store i32 %0, ptr %c, align 4
- %tmp = load i32, ptr %c, align 4
- ret i32 %tmp
-}
-
-define i32 @func2(i32 %a, double %b, ptr %v, ...) nounwind {
-; CHECK-LABEL: @func2(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[TMP_LOC:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B_ADDR:%.*]] = alloca double, align 8
-; CHECK-NEXT: [[AP:%.*]] = alloca ptr, align 4
-; CHECK-NEXT: [[C:%.*]] = alloca i32, align 4
-; CHECK-NEXT: call void @outlined_ir_func_0(i32 [[A:%.*]], ptr [[A_ADDR]], double [[B:%.*]], ptr [[B_ADDR]])
-; CHECK-NEXT: call void @llvm.va_start.p0(ptr [[AP]])
-; CHECK-NEXT: [[TMP0:%.*]] = va_arg ptr [[AP]], i32
-; CHECK-NEXT: call void @llvm.va_copy.p0(ptr [[V:%.*]], ptr [[AP]])
-; CHECK-NEXT: call void @llvm.va_end.p0(ptr [[AP]])
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[TMP_LOC]])
-; CHECK-NEXT: call void @outlined_ir_func_1(i32 [[TMP0]], ptr [[C]], ptr [[TMP_LOC]])
-; CHECK-NEXT: [[TMP_RELOAD:%.*]] = load i32, ptr [[TMP_LOC]], align 4
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[TMP_LOC]])
-; CHECK-NEXT: ret i32 [[TMP_RELOAD]]
-;
-entry:
- %a.addr = alloca i32, align 4
- %b.addr = alloca double, align 8
- %ap = alloca ptr, align 4
- %c = alloca i32, align 4
- store i32 %a, ptr %a.addr, align 4
- store double %b, ptr %b.addr, align 8
- call void @llvm.va_start(ptr %ap)
- %0 = va_arg ptr %ap, i32
- call void @llvm.va_copy(ptr %v, ptr %ap)
- call void @llvm.va_end(ptr %ap)
- store i32 %0, ptr %c, align 4
- %tmp = load i32, ptr %c, align 4
- ret i32 %tmp
-}
diff --git a/llvm/test/Transforms/IROutliner/included-phi-nodes-begin.ll b/llvm/test/Transforms/IROutliner/included-phi-nodes-begin.ll
deleted file mode 100644
index c788b61d18989..0000000000000
--- a/llvm/test/Transforms/IROutliner/included-phi-nodes-begin.ll
+++ /dev/null
@@ -1,93 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --include-generated-funcs
-; RUN: opt -S -passes=verify,iroutliner -ir-outlining-no-cost < %s | FileCheck %s
-
-; Show that we are able to outline when all of the phi nodes in the starting
-; block are included in the region and there is no more than one predecessor
-; into those phi nodes from outside of the region.
-
-define void @function1(ptr %a, ptr %b) {
-entry:
- %0 = alloca i32, align 4
- %c = load i32, ptr %0, align 4
- %y = add i32 %c, %c
- br label %test1
-dummy:
- ret void
-test1:
- %1 = phi i32 [ %e, %test1 ], [ %y, %entry ]
- %2 = phi i32 [ %e, %test1 ], [ %y, %entry ]
- %e = load i32, ptr %0, align 4
- %3 = add i32 %c, %c
- br i1 true, label %test, label %test1
-test:
- %d = load i32, ptr %0, align 4
- br label %first
-first:
- ret void
-}
-
-define void @function2(ptr %a, ptr %b) {
-entry:
- %0 = alloca i32, align 4
- %c = load i32, ptr %0, align 4
- %y = mul i32 %c, %c
- br label %test1
-dummy:
- ret void
-test1:
- %1 = phi i32 [ %e, %test1 ], [ %y, %entry ]
- %2 = phi i32 [ %e, %test1 ], [ %y, %entry ]
- %e = load i32, ptr %0, align 4
- %3 = add i32 %c, %c
- br i1 true, label %test, label %test1
-test:
- %d = load i32, ptr %0, align 4
- br label %first
-first:
- ret void
-}
-; CHECK-LABEL: @function1(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[TMP0:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[C:%.*]] = load i32, ptr [[TMP0]], align 4
-; CHECK-NEXT: [[Y:%.*]] = add i32 [[C]], [[C]]
-; CHECK-NEXT: br label [[TEST1:%.*]]
-; CHECK: dummy:
-; CHECK-NEXT: ret void
-; CHECK: test1:
-; CHECK-NEXT: call void @outlined_ir_func_0(i32 [[Y]], ptr [[TMP0]], i32 [[C]])
-; CHECK-NEXT: br label [[FIRST:%.*]]
-; CHECK: first:
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: @function2(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[TMP0:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[C:%.*]] = load i32, ptr [[TMP0]], align 4
-; CHECK-NEXT: [[Y:%.*]] = mul i32 [[C]], [[C]]
-; CHECK-NEXT: br label [[TEST1:%.*]]
-; CHECK: dummy:
-; CHECK-NEXT: ret void
-; CHECK: test1:
-; CHECK-NEXT: call void @outlined_ir_func_0(i32 [[Y]], ptr [[TMP0]], i32 [[C]])
-; CHECK-NEXT: br label [[FIRST:%.*]]
-; CHECK: first:
-; CHECK-NEXT: ret void
-;
-;
-; CHECK: define internal void @outlined_ir_func_0(
-; CHECK-NEXT: newFuncRoot:
-; CHECK-NEXT: br label [[TEST1_TO_OUTLINE:%.*]]
-; CHECK: test1_to_outline:
-; CHECK-NEXT: [[TMP3:%.*]] = phi i32 [ [[E:%.*]], [[TEST1_TO_OUTLINE]] ], [ [[TMP0:%.*]], [[NEWFUNCROOT:%.*]] ]
-; CHECK-NEXT: [[TMP4:%.*]] = phi i32 [ [[E]], [[TEST1_TO_OUTLINE]] ], [ [[TMP0]], [[NEWFUNCROOT]] ]
-; CHECK-NEXT: [[E]] = load i32, ptr [[TMP1:%.*]], align 4
-; CHECK-NEXT: [[TMP5:%.*]] = add i32 [[TMP2:%.*]], [[TMP2]]
-; CHECK-NEXT: br i1 true, label [[TEST:%.*]], label [[TEST1_TO_OUTLINE]]
-; CHECK: test:
-; CHECK-NEXT: [[D:%.*]] = load i32, ptr [[TMP1]], align 4
-; CHECK-NEXT: br label [[FIRST_EXITSTUB:%.*]]
-; CHECK: first.exitStub:
-; CHECK-NEXT: ret void
-;
diff --git a/llvm/test/Transforms/IROutliner/included-phi-nodes-end.ll b/llvm/test/Transforms/IROutliner/included-phi-nodes-end.ll
deleted file mode 100644
index d36c3dad41b3a..0000000000000
--- a/llvm/test/Transforms/IROutliner/included-phi-nodes-end.ll
+++ /dev/null
@@ -1,94 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --include-generated-funcs
-; RUN: opt -S -passes=verify,iroutliner -ir-outlining-no-cost < %s | FileCheck %s
-
-; Show that we are able to propagate inputs to the region into the split PHINode
-; outside of the region if necessary.
-
-define void @function1(ptr %a, ptr %b) {
-entry:
- %0 = alloca i32, align 4
- %c = load i32, ptr %0, align 4
- %z = add i32 %c, %c
- br i1 true, label %test1, label %first
-test1:
- %e = load i32, ptr %0, align 4
- %1 = add i32 %c, %c
- br i1 true, label %first, label %test
-test:
- %d = load i32, ptr %0, align 4
- br i1 true, label %first, label %next
-first:
- %2 = phi i32 [ %d, %test ], [ %e, %test1 ], [ %c, %entry ]
- %3 = phi i32 [ %d, %test ], [ %e, %test1 ], [ %c, %entry ]
- ret void
-next:
- ret void
-}
-
-define void @function2(ptr %a, ptr %b) {
-entry:
- %0 = alloca i32, align 4
- %c = load i32, ptr %0, align 4
- %z = mul i32 %c, %c
- br i1 true, label %test1, label %first
-test1:
- %e = load i32, ptr %0, align 4
- %1 = add i32 %c, %c
- br i1 true, label %first, label %test
-test:
- %d = load i32, ptr %0, align 4
- br i1 true, label %first, label %next
-first:
- %2 = phi i32 [ %d, %test ], [ %e, %test1 ], [ %c, %entry ]
- %3 = phi i32 [ %d, %test ], [ %e, %test1 ], [ %c, %entry ]
- ret void
-next:
- ret void
-}
-; CHECK-LABEL: @function1(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[TMP0:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[C:%.*]] = load i32, ptr [[TMP0]], align 4
-; CHECK-NEXT: [[Z:%.*]] = add i32 [[C]], [[C]]
-; CHECK-NEXT: [[TARGETBLOCK:%.*]] = call i1 @outlined_ir_func_0(ptr [[TMP0]], i32 [[C]])
-; CHECK-NEXT: br i1 [[TARGETBLOCK]], label [[NEXT:%.*]], label [[ENTRY_AFTER_OUTLINE:%.*]]
-; CHECK: entry_after_outline:
-; CHECK-NEXT: ret void
-; CHECK: next:
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: @function2(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[TMP0:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[C:%.*]] = load i32, ptr [[TMP0]], align 4
-; CHECK-NEXT: [[Z:%.*]] = mul i32 [[C]], [[C]]
-; CHECK-NEXT: [[TARGETBLOCK:%.*]] = call i1 @outlined_ir_func_0(ptr [[TMP0]], i32 [[C]])
-; CHECK-NEXT: br i1 [[TARGETBLOCK]], label [[NEXT:%.*]], label [[ENTRY_AFTER_OUTLINE:%.*]]
-; CHECK: entry_after_outline:
-; CHECK-NEXT: ret void
-; CHECK: next:
-; CHECK-NEXT: ret void
-;
-;
-; CHECK: define internal i1 @outlined_ir_func_0(
-; CHECK-NEXT: newFuncRoot:
-; CHECK-NEXT: br label [[ENTRY_TO_OUTLINE:%.*]]
-; CHECK: entry_to_outline:
-; CHECK-NEXT: br i1 true, label [[TEST1:%.*]], label [[FIRST:%.*]]
-; CHECK: test1:
-; CHECK-NEXT: [[E:%.*]] = load i32, ptr [[TMP0:%.*]], align 4
-; CHECK-NEXT: [[TMP2:%.*]] = add i32 [[TMP1:%.*]], [[TMP1]]
-; CHECK-NEXT: br i1 true, label [[FIRST]], label [[TEST:%.*]]
-; CHECK: test:
-; CHECK-NEXT: [[D:%.*]] = load i32, ptr [[TMP0]], align 4
-; CHECK-NEXT: br i1 true, label [[FIRST]], label [[NEXT_EXITSTUB:%.*]]
-; CHECK: first:
-; CHECK-NEXT: [[TMP3:%.*]] = phi i32 [ [[D]], [[TEST]] ], [ [[E]], [[TEST1]] ], [ [[TMP1]], [[ENTRY_TO_OUTLINE]] ]
-; CHECK-NEXT: [[TMP4:%.*]] = phi i32 [ [[D]], [[TEST]] ], [ [[E]], [[TEST1]] ], [ [[TMP1]], [[ENTRY_TO_OUTLINE]] ]
-; CHECK-NEXT: br label [[ENTRY_AFTER_OUTLINE_EXITSTUB:%.*]]
-; CHECK: next.exitStub:
-; CHECK-NEXT: ret i1 true
-; CHECK: entry_after_outline.exitStub:
-; CHECK-NEXT: ret i1 false
-;
diff --git a/llvm/test/Transforms/IROutliner/legal-debug.ll b/llvm/test/Transforms/IROutliner/legal-debug.ll
deleted file mode 100644
index 2e5f25bf756cf..0000000000000
--- a/llvm/test/Transforms/IROutliner/legal-debug.ll
+++ /dev/null
@@ -1,139 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --include-generated-funcs
-; RUN: opt -S -passes=verify,iroutliner -ir-outlining-no-cost < %s | FileCheck %s
-
-; This test checks that debug info is recognized as able to be extracted along
-; with the other instructions, but is not included in the consolidated function.
-
-define void @function1() !dbg !6 {
-entry:
- %a = alloca i32, align 4, !dbg !17
- call void @llvm.dbg.value(metadata ptr %a, metadata !9, metadata !DIExpression()), !dbg !17
- %b = alloca i32, align 4, !dbg !18
- call void @llvm.dbg.value(metadata ptr %b, metadata !11, metadata !DIExpression()), !dbg !18
- %c = alloca i32, align 4, !dbg !19
- call void @llvm.dbg.value(metadata ptr %c, metadata !12, metadata !DIExpression()), !dbg !19
- store i32 2, ptr %a, align 4, !dbg !20
- store i32 3, ptr %b, align 4, !dbg !21
- store i32 4, ptr %c, align 4, !dbg !22
- %al = load i32, ptr %a, align 4, !dbg !23
- call void @llvm.dbg.value(metadata i32 %al, metadata !13, metadata !DIExpression()), !dbg !23
- %bl = load i32, ptr %b, align 4, !dbg !24
- call void @llvm.dbg.value(metadata i32 %bl, metadata !15, metadata !DIExpression()), !dbg !24
- %cl = load i32, ptr %c, align 4, !dbg !25
- call void @llvm.dbg.value(metadata i32 %cl, metadata !16, metadata !DIExpression()), !dbg !25
- ret void, !dbg !26
-}
-
-define void @function2() !dbg !27 {
-entry:
- %a = alloca i32, align 4, !dbg !35
- call void @llvm.dbg.value(metadata ptr %a, metadata !29, metadata !DIExpression()), !dbg !35
- %b = alloca i32, align 4, !dbg !36
- call void @llvm.dbg.value(metadata ptr %b, metadata !30, metadata !DIExpression()), !dbg !36
- %c = alloca i32, align 4, !dbg !37
- call void @llvm.dbg.value(metadata ptr %c, metadata !31, metadata !DIExpression()), !dbg !37
- store i32 2, ptr %a, align 4, !dbg !38
- store i32 3, ptr %b, align 4, !dbg !39
- store i32 4, ptr %c, align 4, !dbg !40
- %al = load i32, ptr %a, align 4, !dbg !41
- call void @llvm.dbg.value(metadata i32 %al, metadata !32, metadata !DIExpression()), !dbg !41
- %bl = load i32, ptr %b, align 4, !dbg !42
- call void @llvm.dbg.value(metadata i32 %bl, metadata !33, metadata !DIExpression()), !dbg !42
- %cl = load i32, ptr %c, align 4, !dbg !43
- call void @llvm.dbg.value(metadata i32 %cl, metadata !34, metadata !DIExpression()), !dbg !43
- ret void, !dbg !44
-}
-
-
-; Function Attrs: nounwind readnone speculatable willreturn
-declare void @llvm.dbg.value(metadata, metadata, metadata) #0
-
-attributes #0 = { nounwind readnone speculatable willreturn }
-
-!llvm.dbg.cu = !{!0}
-!llvm.debugify = !{!3, !4}
-!llvm.module.flags = !{!5}
-
-!0 = distinct !DICompileUnit(language: DW_LANG_C, file: !1, producer: "debugify", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
-!1 = !DIFile(filename: "legal-debug.ll", directory: "/")
-!2 = !{}
-!3 = !{i32 20}
-!4 = !{i32 12}
-!5 = !{i32 2, !"Debug Info Version", i32 3}
-!6 = distinct !DISubprogram(name: "function1", linkageName: "function1", scope: null, file: !1, line: 1, type: !7, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !8)
-!7 = !DISubroutineType(types: !2)
-!8 = !{!9, !11, !12, !13, !15, !16}
-!9 = !DILocalVariable(name: "1", scope: !6, file: !1, line: 1, type: !10)
-!10 = !DIBasicType(name: "ty64", size: 64, encoding: DW_ATE_unsigned)
-!11 = !DILocalVariable(name: "2", scope: !6, file: !1, line: 2, type: !10)
-!12 = !DILocalVariable(name: "3", scope: !6, file: !1, line: 3, type: !10)
-!13 = !DILocalVariable(name: "4", scope: !6, file: !1, line: 7, type: !14)
-!14 = !DIBasicType(name: "ty32", size: 32, encoding: DW_ATE_unsigned)
-!15 = !DILocalVariable(name: "5", scope: !6, file: !1, line: 8, type: !14)
-!16 = !DILocalVariable(name: "6", scope: !6, file: !1, line: 9, type: !14)
-!17 = !DILocation(line: 1, column: 1, scope: !6)
-!18 = !DILocation(line: 2, column: 1, scope: !6)
-!19 = !DILocation(line: 3, column: 1, scope: !6)
-!20 = !DILocation(line: 4, column: 1, scope: !6)
-!21 = !DILocation(line: 5, column: 1, scope: !6)
-!22 = !DILocation(line: 6, column: 1, scope: !6)
-!23 = !DILocation(line: 7, column: 1, scope: !6)
-!24 = !DILocation(line: 8, column: 1, scope: !6)
-!25 = !DILocation(line: 9, column: 1, scope: !6)
-!26 = !DILocation(line: 10, column: 1, scope: !6)
-!27 = distinct !DISubprogram(name: "function2", linkageName: "function2", scope: null, file: !1, line: 11, type: !7, scopeLine: 11, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !28)
-!28 = !{!29, !30, !31, !32, !33, !34}
-!29 = !DILocalVariable(name: "7", scope: !27, file: !1, line: 11, type: !10)
-!30 = !DILocalVariable(name: "8", scope: !27, file: !1, line: 12, type: !10)
-!31 = !DILocalVariable(name: "9", scope: !27, file: !1, line: 13, type: !10)
-!32 = !DILocalVariable(name: "10", scope: !27, file: !1, line: 17, type: !14)
-!33 = !DILocalVariable(name: "11", scope: !27, file: !1, line: 18, type: !14)
-!34 = !DILocalVariable(name: "12", scope: !27, file: !1, line: 19, type: !14)
-!35 = !DILocation(line: 11, column: 1, scope: !27)
-!36 = !DILocation(line: 12, column: 1, scope: !27)
-!37 = !DILocation(line: 13, column: 1, scope: !27)
-!38 = !DILocation(line: 14, column: 1, scope: !27)
-!39 = !DILocation(line: 15, column: 1, scope: !27)
-!40 = !DILocation(line: 16, column: 1, scope: !27)
-!41 = !DILocation(line: 17, column: 1, scope: !27)
-!42 = !DILocation(line: 18, column: 1, scope: !27)
-!43 = !DILocation(line: 19, column: 1, scope: !27)
-!44 = !DILocation(line: 20, column: 1, scope: !27)
-; CHECK-LABEL: @function1(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4, !dbg [[DBG17:![0-9]+]]
-; CHECK-NEXT: #dbg_value(ptr [[A]], [[META9:![0-9]+]], !DIExpression(), [[DBG17]])
-; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4, !dbg [[DBG18:![0-9]+]]
-; CHECK-NEXT: #dbg_value(ptr [[B]], [[META11:![0-9]+]], !DIExpression(), [[DBG18]])
-; CHECK-NEXT: [[C:%.*]] = alloca i32, align 4, !dbg [[DBG19:![0-9]+]]
-; CHECK-NEXT: #dbg_value(ptr [[C]], [[META12:![0-9]+]], !DIExpression(), [[DBG19]])
-; CHECK-NEXT: call void @outlined_ir_func_0(ptr [[A]], ptr [[B]], ptr [[C]]), !dbg [[DBG20:![0-9]+]]
-; CHECK-NEXT: ret void, !dbg [[DBG21:![0-9]+]]
-;
-;
-; CHECK-LABEL: @function2(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4, !dbg [[DBG30:![0-9]+]]
-; CHECK-NEXT: #dbg_value(ptr [[A]], [[META24:![0-9]+]], !DIExpression(), [[DBG30]])
-; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4, !dbg [[DBG31:![0-9]+]]
-; CHECK-NEXT: #dbg_value(ptr [[B]], [[META25:![0-9]+]], !DIExpression(), [[DBG31]])
-; CHECK-NEXT: [[C:%.*]] = alloca i32, align 4, !dbg [[DBG32:![0-9]+]]
-; CHECK-NEXT: #dbg_value(ptr [[C]], [[META26:![0-9]+]], !DIExpression(), [[DBG32]])
-; CHECK-NEXT: call void @outlined_ir_func_0(ptr [[A]], ptr [[B]], ptr [[C]]), !dbg [[DBG33:![0-9]+]]
-; CHECK-NEXT: ret void, !dbg [[DBG34:![0-9]+]]
-;
-;
-; CHECK-LABEL: define {{.+}} @outlined_ir_func_0(
-; CHECK-NEXT: newFuncRoot:
-; CHECK-NEXT: br label [[ENTRY_TO_OUTLINE:%.*]]
-; CHECK: entry_to_outline:
-; CHECK-NEXT: store i32 2, ptr [[TMP0:%.*]], align 4
-; CHECK-NEXT: store i32 3, ptr [[TMP1:%.*]], align 4
-; CHECK-NEXT: store i32 4, ptr [[TMP2:%.*]], align 4
-; CHECK-NEXT: [[AL:%.*]] = load i32, ptr [[TMP0]], align 4
-; CHECK-NEXT: [[BL:%.*]] = load i32, ptr [[TMP1]], align 4
-; CHECK-NEXT: [[CL:%.*]] = load i32, ptr [[TMP2]], align 4
-; CHECK-NEXT: br label [[ENTRY_AFTER_OUTLINE_EXITSTUB:%.*]]
-; CHECK: entry_after_outline.exitStub:
-; CHECK-NEXT: ret void
-;
diff --git a/llvm/test/Transforms/IROutliner/legal-indirect-calls.ll b/llvm/test/Transforms/IROutliner/legal-indirect-calls.ll
deleted file mode 100644
index 1733bdb508565..0000000000000
--- a/llvm/test/Transforms/IROutliner/legal-indirect-calls.ll
+++ /dev/null
@@ -1,71 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --include-generated-funcs
-; RUN: opt -S -passes=verify,iroutliner -ir-outlining-no-cost < %s | FileCheck %s
-
-; This test checks that we do outline indirect calls when it is not specified
-; that we should not.
-
-declare void @f1(ptr, ptr);
-declare void @f2(ptr, ptr);
-
-define void @function1(ptr %func) {
-entry:
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- %c = alloca i32, align 4
- store i32 2, ptr %a, align 4
- store i32 3, ptr %b, align 4
- store i32 4, ptr %c, align 4
- call void %func()
- %al = load i32, ptr %a
- %bl = load i32, ptr %b
- %cl = load i32, ptr %c
- ret void
-}
-
-define void @function2(ptr %func) {
-entry:
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- %c = alloca i32, align 4
- store i32 2, ptr %a, align 4
- store i32 3, ptr %b, align 4
- store i32 4, ptr %c, align 4
- call void %func()
- %al = load i32, ptr %a
- %bl = load i32, ptr %b
- %cl = load i32, ptr %c
- ret void
-}
-; CHECK-LABEL: @function1(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[C:%.*]] = alloca i32, align 4
-; CHECK-NEXT: call void @outlined_ir_func_0(ptr [[A]], ptr [[B]], ptr [[C]], ptr [[FUNC:%.*]])
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: @function2(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[C:%.*]] = alloca i32, align 4
-; CHECK-NEXT: call void @outlined_ir_func_0(ptr [[A]], ptr [[B]], ptr [[C]], ptr [[FUNC:%.*]])
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: define internal void @outlined_ir_func_0(
-; CHECK-NEXT: newFuncRoot:
-; CHECK-NEXT: br label [[ENTRY_TO_OUTLINE:%.*]]
-; CHECK: entry_to_outline:
-; CHECK-NEXT: store i32 2, ptr [[TMP0:%.*]], align 4
-; CHECK-NEXT: store i32 3, ptr [[TMP1:%.*]], align 4
-; CHECK-NEXT: store i32 4, ptr [[TMP2:%.*]], align 4
-; CHECK-NEXT: call void [[TMP3:%.*]]()
-; CHECK-NEXT: [[AL:%.*]] = load i32, ptr [[TMP0]], align 4
-; CHECK-NEXT: [[BL:%.*]] = load i32, ptr [[TMP1]], align 4
-; CHECK-NEXT: [[CL:%.*]] = load i32, ptr [[TMP2]], align 4
-; CHECK-NEXT: br label [[ENTRY_AFTER_OUTLINE_EXITSTUB:%.*]]
-; CHECK: entry_after_outline.exitStub:
-; CHECK-NEXT: ret void
-;
diff --git a/llvm/test/Transforms/IROutliner/mismatched-phi-exits-not-in-first-outlined.ll b/llvm/test/Transforms/IROutliner/mismatched-phi-exits-not-in-first-outlined.ll
deleted file mode 100644
index f9d49993b692d..0000000000000
--- a/llvm/test/Transforms/IROutliner/mismatched-phi-exits-not-in-first-outlined.ll
+++ /dev/null
@@ -1,84 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --include-generated-funcs
-; RUN: opt -S -passes=verify,iroutliner -ir-outlining-no-cost < %s | FileCheck %s
-
-; Show that we are able to extract blocks that contain PHINodes, and selectively
-; store into it's respective block, creating a new block if needed.
-
-define void @function1(ptr %a, ptr %b) {
-entry:
- %0 = alloca i32, align 4
- %c = load i32, ptr %0, align 4
- br label %test1
-test1:
- %e = load i32, ptr %0, align 4
- br label %first
-test:
- %d = load i32, ptr %0, align 4
- br label %first
-first:
- ret void
-}
-
-define void @function2(ptr %a, ptr %b) {
-entry:
- %0 = alloca i32, align 4
- %c = load i32, ptr %0, align 4
- br label %test1
-test1:
- %e = load i32, ptr %0, align 4
- br label %first
-test:
- %d = load i32, ptr %0, align 4
- br label %first
-first:
- %1 = phi i32 [ %c, %test ], [ %e, %test1 ]
- ret void
-}
-; CHECK-LABEL: @function1(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[TMP0:%.*]] = alloca i32, align 4
-; CHECK-NEXT: call void @outlined_ir_func_0(ptr [[TMP0]], ptr null, i32 -1)
-; CHECK-NEXT: br label [[FIRST:%.*]]
-; CHECK: first:
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: @function2(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[DOTCE_LOC:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[TMP0:%.*]] = alloca i32, align 4
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[DOTCE_LOC]])
-; CHECK-NEXT: call void @outlined_ir_func_0(ptr [[TMP0]], ptr [[DOTCE_LOC]], i32 0)
-; CHECK-NEXT: [[DOTCE_RELOAD:%.*]] = load i32, ptr [[DOTCE_LOC]], align 4
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[DOTCE_LOC]])
-; CHECK-NEXT: br label [[FIRST:%.*]]
-; CHECK: first:
-; CHECK-NEXT: [[TMP1:%.*]] = phi i32 [ [[DOTCE_RELOAD]], [[ENTRY:%.*]] ]
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: define internal void @outlined_ir_func_0(
-; CHECK-NEXT: newFuncRoot:
-; CHECK-NEXT: br label [[ENTRY_TO_OUTLINE:%.*]]
-; CHECK: entry_to_outline:
-; CHECK-NEXT: [[C:%.*]] = load i32, ptr [[TMP0:%.*]], align 4
-; CHECK-NEXT: br label [[TEST1:%.*]]
-; CHECK: test1:
-; CHECK-NEXT: [[E:%.*]] = load i32, ptr [[TMP0]], align 4
-; CHECK-NEXT: br label [[PHI_BLOCK:%.*]]
-; CHECK: test:
-; CHECK-NEXT: [[D:%.*]] = load i32, ptr [[TMP0]], align 4
-; CHECK-NEXT: br label [[PHI_BLOCK]]
-; CHECK: first.exitStub:
-; CHECK-NEXT: switch i32 [[TMP2:%.*]], label [[FINAL_BLOCK_0:%.*]] [
-; CHECK-NEXT: i32 0, label [[OUTPUT_BLOCK_1_0:%.*]]
-; CHECK-NEXT: ]
-; CHECK: output_block_1_0:
-; CHECK-NEXT: store i32 [[TMP3:%.*]], ptr [[TMP1:%.*]], align 4
-; CHECK-NEXT: br label [[FINAL_BLOCK_0]]
-; CHECK: phi_block:
-; CHECK-NEXT: [[TMP3]] = phi i32 [ [[C]], [[TEST:%.*]] ], [ [[E]], [[TEST1]] ]
-; CHECK-NEXT: br label [[FIRST_EXITSTUB:%.*]]
-; CHECK: final_block_0:
-; CHECK-NEXT: ret void
-;
diff --git a/llvm/test/Transforms/IROutliner/mismatched-phi-exits.ll b/llvm/test/Transforms/IROutliner/mismatched-phi-exits.ll
deleted file mode 100644
index 7191c80534f1b..0000000000000
--- a/llvm/test/Transforms/IROutliner/mismatched-phi-exits.ll
+++ /dev/null
@@ -1,84 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --include-generated-funcs
-; RUN: opt -S -passes=verify,iroutliner -ir-outlining-no-cost < %s | FileCheck %s
-
-; Show that we are able to extract blocks that contain PHINodes, and selectively
-; store into it's respective block, only using if needed.
-
-define void @function1(ptr %a, ptr %b) {
-entry:
- %0 = alloca i32, align 4
- %c = load i32, ptr %0, align 4
- br label %test1
-test1:
- %e = load i32, ptr %0, align 4
- br label %first
-test:
- %d = load i32, ptr %0, align 4
- br label %first
-first:
- %1 = phi i32 [ %c, %test ], [ %e, %test1 ]
- ret void
-}
-
-define void @function2(ptr %a, ptr %b) {
-entry:
- %0 = alloca i32, align 4
- %c = load i32, ptr %0, align 4
- br label %test1
-test1:
- %e = load i32, ptr %0, align 4
- br label %first
-test:
- %d = load i32, ptr %0, align 4
- br label %first
-first:
- ret void
-}
-; CHECK-LABEL: @function1(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[DOTCE_LOC:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[TMP0:%.*]] = alloca i32, align 4
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[DOTCE_LOC]])
-; CHECK-NEXT: call void @outlined_ir_func_0(ptr [[TMP0]], ptr [[DOTCE_LOC]], i32 0)
-; CHECK-NEXT: [[DOTCE_RELOAD:%.*]] = load i32, ptr [[DOTCE_LOC]], align 4
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[DOTCE_LOC]])
-; CHECK-NEXT: br label [[FIRST:%.*]]
-; CHECK: first:
-; CHECK-NEXT: [[TMP1:%.*]] = phi i32 [ [[DOTCE_RELOAD]], [[ENTRY:%.*]] ]
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: @function2(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[TMP0:%.*]] = alloca i32, align 4
-; CHECK-NEXT: call void @outlined_ir_func_0(ptr [[TMP0]], ptr null, i32 -1)
-; CHECK-NEXT: br label [[FIRST:%.*]]
-; CHECK: first:
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: define internal void @outlined_ir_func_0(
-; CHECK-NEXT: newFuncRoot:
-; CHECK-NEXT: br label [[ENTRY_TO_OUTLINE:%.*]]
-; CHECK: entry_to_outline:
-; CHECK-NEXT: [[C:%.*]] = load i32, ptr [[TMP0:%.*]], align 4
-; CHECK-NEXT: br label [[TEST1:%.*]]
-; CHECK: test1:
-; CHECK-NEXT: [[E:%.*]] = load i32, ptr [[TMP0]], align 4
-; CHECK-NEXT: br label [[FIRST_SPLIT:%.*]]
-; CHECK: test:
-; CHECK-NEXT: [[D:%.*]] = load i32, ptr [[TMP0]], align 4
-; CHECK-NEXT: br label [[FIRST_SPLIT]]
-; CHECK: first.split:
-; CHECK-NEXT: [[DOTCE:%.*]] = phi i32 [ [[C]], [[TEST:%.*]] ], [ [[E]], [[TEST1]] ]
-; CHECK-NEXT: br label [[FIRST_EXITSTUB:%.*]]
-; CHECK: first.exitStub:
-; CHECK-NEXT: switch i32 [[TMP2:%.*]], label [[FINAL_BLOCK_0:%.*]] [
-; CHECK-NEXT: i32 0, label [[OUTPUT_BLOCK_0_0:%.*]]
-; CHECK-NEXT: ]
-; CHECK: output_block_0_0:
-; CHECK-NEXT: store i32 [[DOTCE]], ptr [[TMP1:%.*]], align 4
-; CHECK-NEXT: br label [[FINAL_BLOCK_0]]
-; CHECK: final_block_0:
-; CHECK-NEXT: ret void
-;
diff --git a/llvm/test/Transforms/IROutliner/mismatched-phi-outputs-ordering.ll b/llvm/test/Transforms/IROutliner/mismatched-phi-outputs-ordering.ll
deleted file mode 100644
index 9085e7e507726..0000000000000
--- a/llvm/test/Transforms/IROutliner/mismatched-phi-outputs-ordering.ll
+++ /dev/null
@@ -1,145 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --include-generated-funcs
-; RUN: opt -S -passes=verify,iroutliner -ir-outlining-no-cost < %s | FileCheck %s
-
-; Show that we do not extract similar regions that would involve the splitting
-; of phi nodes on exit.
-
-define void @function1(ptr %a, ptr %b) {
-entry:
- %0 = alloca i32, align 4
- %c = load i32, ptr %0, align 4
- br label %test1
-test1:
- %e = load i32, ptr %0, align 4
- br i1 true, label %first, label %test
-test:
- %d = load i32, ptr %0, align 4
- br i1 true, label %first, label %next
-first:
- %1 = phi i32 [ %c, %test ], [ %e, %test1 ]
- ret void
-next:
- %2 = add i32 %d, 1
- %3 = add i32 %e, 1
- ret void
-}
-
-define void @function2(ptr %a, ptr %b) {
-entry:
- %0 = alloca i32, align 4
- %c = load i32, ptr %0, align 4
- br label %test1
-test1:
- %e = load i32, ptr %0, align 4
- br i1 true, label %first, label %test
-test:
- %d = load i32, ptr %0, align 4
- br i1 true, label %first, label %next
-first:
- ret void
-next:
- %1 = add i32 %d, 1
- %2 = add i32 %e, 1
- ret void
-}
-; CHECK-LABEL: @function1(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[DOTCE_LOC:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[D_LOC:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[E_LOC:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[TMP0:%.*]] = alloca i32, align 4
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[E_LOC]])
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[D_LOC]])
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[DOTCE_LOC]])
-; CHECK-NEXT: [[TMP1:%.*]] = call i1 @outlined_ir_func_0(ptr [[TMP0]], ptr [[E_LOC]], ptr [[D_LOC]], ptr [[DOTCE_LOC]], i32 0)
-; CHECK-NEXT: [[E_RELOAD:%.*]] = load i32, ptr [[E_LOC]], align 4
-; CHECK-NEXT: [[D_RELOAD:%.*]] = load i32, ptr [[D_LOC]], align 4
-; CHECK-NEXT: [[DOTCE_RELOAD:%.*]] = load i32, ptr [[DOTCE_LOC]], align 4
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[E_LOC]])
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[D_LOC]])
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[DOTCE_LOC]])
-; CHECK-NEXT: br i1 [[TMP1]], label [[FIRST:%.*]], label [[NEXT:%.*]]
-; CHECK: first:
-; CHECK-NEXT: [[TMP2:%.*]] = phi i32 [ [[DOTCE_RELOAD]], [[ENTRY:%.*]] ]
-; CHECK-NEXT: ret void
-; CHECK: next:
-; CHECK-NEXT: call void @outlined_ir_func_1(i32 [[D_RELOAD]], i32 [[E_RELOAD]])
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: @function2(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[D_LOC:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[E_LOC:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[TMP0:%.*]] = alloca i32, align 4
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[E_LOC]])
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[D_LOC]])
-; CHECK-NEXT: [[TMP1:%.*]] = call i1 @outlined_ir_func_0(ptr [[TMP0]], ptr [[E_LOC]], ptr [[D_LOC]], ptr null, i32 1)
-; CHECK-NEXT: [[E_RELOAD:%.*]] = load i32, ptr [[E_LOC]], align 4
-; CHECK-NEXT: [[D_RELOAD:%.*]] = load i32, ptr [[D_LOC]], align 4
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[E_LOC]])
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[D_LOC]])
-; CHECK-NEXT: br i1 [[TMP1]], label [[FIRST:%.*]], label [[NEXT:%.*]]
-; CHECK: first:
-; CHECK-NEXT: ret void
-; CHECK: next:
-; CHECK-NEXT: call void @outlined_ir_func_1(i32 [[D_RELOAD]], i32 [[E_RELOAD]])
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: define internal i1 @outlined_ir_func_0(
-; CHECK-NEXT: newFuncRoot:
-; CHECK-NEXT: br label [[ENTRY_TO_OUTLINE:%.*]]
-; CHECK: entry_to_outline:
-; CHECK-NEXT: [[C:%.*]] = load i32, ptr [[TMP0:%.*]], align 4
-; CHECK-NEXT: br label [[TEST1:%.*]]
-; CHECK: test1:
-; CHECK-NEXT: [[E:%.*]] = load i32, ptr [[TMP0]], align 4
-; CHECK-NEXT: br i1 true, label [[FIRST_SPLIT:%.*]], label [[TEST:%.*]]
-; CHECK: test:
-; CHECK-NEXT: [[D:%.*]] = load i32, ptr [[TMP0]], align 4
-; CHECK-NEXT: br i1 true, label [[FIRST_SPLIT]], label [[NEXT_EXITSTUB:%.*]]
-; CHECK: first.split:
-; CHECK-NEXT: [[DOTCE:%.*]] = phi i32 [ [[C]], [[TEST]] ], [ [[E]], [[TEST1]] ]
-; CHECK-NEXT: br label [[FIRST_EXITSTUB:%.*]]
-; CHECK: first.exitStub:
-; CHECK-NEXT: switch i32 [[TMP4:%.*]], label [[FINAL_BLOCK_1:%.*]] [
-; CHECK-NEXT: i32 0, label [[OUTPUT_BLOCK_0_1:%.*]]
-; CHECK-NEXT: i32 1, label [[OUTPUT_BLOCK_1_1:%.*]]
-; CHECK-NEXT: ]
-; CHECK: next.exitStub:
-; CHECK-NEXT: switch i32 [[TMP4]], label [[FINAL_BLOCK_0:%.*]] [
-; CHECK-NEXT: i32 0, label [[OUTPUT_BLOCK_0_0:%.*]]
-; CHECK-NEXT: i32 1, label [[OUTPUT_BLOCK_1_0:%.*]]
-; CHECK-NEXT: ]
-; CHECK: output_block_0_0:
-; CHECK-NEXT: store i32 [[E]], ptr [[TMP1:%.*]], align 4
-; CHECK-NEXT: store i32 [[D]], ptr [[TMP2:%.*]], align 4
-; CHECK-NEXT: br label [[FINAL_BLOCK_0]]
-; CHECK: output_block_0_1:
-; CHECK-NEXT: store i32 [[E]], ptr [[TMP1]], align 4
-; CHECK-NEXT: store i32 [[DOTCE]], ptr [[TMP3:%.*]], align 4
-; CHECK-NEXT: br label [[FINAL_BLOCK_1]]
-; CHECK: output_block_1_0:
-; CHECK-NEXT: store i32 [[E]], ptr [[TMP1]], align 4
-; CHECK-NEXT: store i32 [[D]], ptr [[TMP2]], align 4
-; CHECK-NEXT: br label [[FINAL_BLOCK_0]]
-; CHECK: output_block_1_1:
-; CHECK-NEXT: store i32 [[E]], ptr [[TMP1]], align 4
-; CHECK-NEXT: br label [[FINAL_BLOCK_1]]
-; CHECK: final_block_0:
-; CHECK-NEXT: ret i1 false
-; CHECK: final_block_1:
-; CHECK-NEXT: ret i1 true
-;
-;
-; CHECK-LABEL: @outlined_ir_func_1(
-; CHECK-NEXT: newFuncRoot:
-; CHECK-NEXT: br label [[NEXT_TO_OUTLINE:%.*]]
-; CHECK: next_to_outline:
-; CHECK-NEXT: [[TMP2:%.*]] = add i32 [[TMP0:%.*]], 1
-; CHECK-NEXT: [[TMP3:%.*]] = add i32 [[TMP1:%.*]], 1
-; CHECK-NEXT: br label [[NEXT_AFTER_OUTLINE_EXITSTUB:%.*]]
-; CHECK: next_after_outline.exitStub:
-; CHECK-NEXT: ret void
-;
diff --git a/llvm/test/Transforms/IROutliner/must-capture-all-phi-nodes-begin.ll b/llvm/test/Transforms/IROutliner/must-capture-all-phi-nodes-begin.ll
deleted file mode 100644
index 3229f4255c31d..0000000000000
--- a/llvm/test/Transforms/IROutliner/must-capture-all-phi-nodes-begin.ll
+++ /dev/null
@@ -1,106 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --include-generated-funcs
-; RUN: opt -S -passes=verify,iroutliner -ir-outlining-no-cost < %s | FileCheck %s
-
-; Show that we do not outline when all of the phi nodes in the beginning
-; block are included not in the region.
-
-define void @function1(ptr %a, ptr %b) {
-entry:
- %0 = alloca i32, align 4
- %c = load i32, ptr %0, align 4
- %y = add i32 %c, %c
- br label %test1
-dummy:
- ret void
-test1:
- %1 = phi i32 [ %e, %test1 ], [ %y, %entry ]
- %2 = phi i32 [ %e, %test1 ], [ %y, %entry ]
- %e = load i32, ptr %0, align 4
- %3 = add i32 %c, %c
- br i1 true, label %test, label %test1
-test:
- %d = load i32, ptr %0, align 4
- br label %first
-first:
- ret void
-}
-
-define void @function2(ptr %a, ptr %b) {
-entry:
- %0 = alloca i32, align 4
- %c = load i32, ptr %0, align 4
- %y = mul i32 %c, %c
- br label %test1
-dummy:
- ret void
-test1:
- %1 = phi i32 [ %e, %test1 ], [ %y, %entry ]
- %2 = phi i32 [ %y, %entry ], [ %e, %test1 ]
- %e = load i32, ptr %0, align 4
- %3 = add i32 %c, %c
- br i1 true, label %test, label %test1
-test:
- %d = load i32, ptr %0, align 4
- br label %first
-first:
- ret void
-}
-; CHECK-LABEL: @function1(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[E_LOC:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[TMP0:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[C:%.*]] = load i32, ptr [[TMP0]], align 4
-; CHECK-NEXT: [[Y:%.*]] = add i32 [[C]], [[C]]
-; CHECK-NEXT: br label [[TEST1:%.*]]
-; CHECK: dummy:
-; CHECK-NEXT: ret void
-; CHECK: test1:
-; CHECK-NEXT: [[TMP1:%.*]] = phi i32 [ [[E_RELOAD:%.*]], [[TEST1]] ], [ [[Y]], [[ENTRY:%.*]] ]
-; CHECK-NEXT: [[TMP2:%.*]] = phi i32 [ [[E_RELOAD]], [[TEST1]] ], [ [[Y]], [[ENTRY]] ]
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[E_LOC]])
-; CHECK-NEXT: [[TARGETBLOCK:%.*]] = call i1 @outlined_ir_func_0(ptr [[TMP0]], i32 [[C]], ptr [[E_LOC]])
-; CHECK-NEXT: [[E_RELOAD]] = load i32, ptr [[E_LOC]], align 4
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[E_LOC]])
-; CHECK-NEXT: br i1 [[TARGETBLOCK]], label [[TEST1]], label [[FIRST:%.*]]
-; CHECK: first:
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: @function2(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[E_LOC:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[TMP0:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[C:%.*]] = load i32, ptr [[TMP0]], align 4
-; CHECK-NEXT: [[Y:%.*]] = mul i32 [[C]], [[C]]
-; CHECK-NEXT: br label [[TEST1:%.*]]
-; CHECK: dummy:
-; CHECK-NEXT: ret void
-; CHECK: test1:
-; CHECK-NEXT: [[TMP1:%.*]] = phi i32 [ [[E_RELOAD:%.*]], [[TEST1]] ], [ [[Y]], [[ENTRY:%.*]] ]
-; CHECK-NEXT: [[TMP2:%.*]] = phi i32 [ [[Y]], [[ENTRY]] ], [ [[E_RELOAD]], [[TEST1]] ]
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[E_LOC]])
-; CHECK-NEXT: [[TARGETBLOCK:%.*]] = call i1 @outlined_ir_func_0(ptr [[TMP0]], i32 [[C]], ptr [[E_LOC]])
-; CHECK-NEXT: [[E_RELOAD]] = load i32, ptr [[E_LOC]], align 4
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[E_LOC]])
-; CHECK-NEXT: br i1 [[TARGETBLOCK]], label [[TEST1]], label [[FIRST:%.*]]
-; CHECK: first:
-; CHECK-NEXT: ret void
-;
-;
-; CHECK: define internal i1 @outlined_ir_func_0(
-; CHECK-NEXT: newFuncRoot:
-; CHECK-NEXT: br label [[TEST1_TO_OUTLINE:%.*]]
-; CHECK: test1_to_outline:
-; CHECK-NEXT: [[E:%.*]] = load i32, ptr [[TMP0:%.*]], align 4
-; CHECK-NEXT: [[TMP3:%.*]] = add i32 [[TMP1:%.*]], [[TMP1]]
-; CHECK-NEXT: br i1 true, label [[TEST:%.*]], label [[TEST1_EXITSTUB:%.*]]
-; CHECK: test:
-; CHECK-NEXT: [[D:%.*]] = load i32, ptr [[TMP0]], align 4
-; CHECK-NEXT: br label [[FIRST_EXITSTUB:%.*]]
-; CHECK: test1.exitStub:
-; CHECK-NEXT: store i32 [[E]], ptr [[TMP2:%.*]], align 4
-; CHECK-NEXT: ret i1 true
-; CHECK: first.exitStub:
-; CHECK-NEXT: store i32 [[E]], ptr [[TMP2]], align 4
-; CHECK-NEXT: ret i1 false
-;
diff --git a/llvm/test/Transforms/IROutliner/must-capture-all-phi-nodes-end.ll b/llvm/test/Transforms/IROutliner/must-capture-all-phi-nodes-end.ll
deleted file mode 100644
index 6f64414640d4c..0000000000000
--- a/llvm/test/Transforms/IROutliner/must-capture-all-phi-nodes-end.ll
+++ /dev/null
@@ -1,88 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --include-generated-funcs
-; RUN: opt -S -passes=verify,iroutliner -ir-outlining-no-cost < %s | FileCheck %s
-
-; Show that we do not outline when all of the phi nodes in the end
-; block are not included in the region.
-
-define void @function1(ptr %a, ptr %b) {
-entry:
- %0 = alloca i32, align 4
- %c = load i32, ptr %0, align 4
- %z = add i32 %c, %c
- br i1 true, label %test1, label %first
-test1:
- %e = load i32, ptr %0, align 4
- %1 = add i32 %c, %c
- br i1 true, label %first, label %test
-test:
- %d = load i32, ptr %0, align 4
- br i1 true, label %first, label %next
-first:
- %2 = phi i32 [ %d, %test ], [ %e, %test1 ], [ %c, %entry ]
- %3 = phi i32 [ %d, %test ], [ %e, %test1 ], [ %c, %entry ]
- ret void
-next:
- ret void
-}
-
-define void @function2(ptr %a, ptr %b) {
-entry:
- %0 = alloca i32, align 4
- %c = load i32, ptr %0, align 4
- %z = mul i32 %c, %c
- br i1 true, label %test1, label %first
-test1:
- %e = load i32, ptr %0, align 4
- %1 = add i32 %c, %c
- br i1 true, label %first, label %test
-test:
- %d = load i32, ptr %0, align 4
- br i1 true, label %first, label %next
-first:
- %2 = phi i32 [ %d, %test ], [ %e, %test1 ], [ %c, %entry ]
- %3 = phi i32 [ %d, %test ], [ %c, %entry ], [ %e, %test1 ]
- ret void
-next:
- ret void
-}
-; CHECK-LABEL: @function1(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[TMP0:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[C:%.*]] = load i32, ptr [[TMP0]], align 4
-; CHECK-NEXT: [[Z:%.*]] = add i32 [[C]], [[C]]
-; CHECK-NEXT: br i1 true, label [[TEST1:%.*]], label [[FIRST:%.*]]
-; CHECK: test1:
-; CHECK-NEXT: [[E:%.*]] = load i32, ptr [[TMP0]], align 4
-; CHECK-NEXT: [[TMP1:%.*]] = add i32 [[C]], [[C]]
-; CHECK-NEXT: br i1 true, label [[FIRST]], label [[TEST:%.*]]
-; CHECK: test:
-; CHECK-NEXT: [[D:%.*]] = load i32, ptr [[TMP0]], align 4
-; CHECK-NEXT: br i1 true, label [[FIRST]], label [[NEXT:%.*]]
-; CHECK: first:
-; CHECK-NEXT: [[TMP2:%.*]] = phi i32 [ [[D]], [[TEST]] ], [ [[E]], [[TEST1]] ], [ [[C]], [[ENTRY:%.*]] ]
-; CHECK-NEXT: [[TMP3:%.*]] = phi i32 [ [[D]], [[TEST]] ], [ [[E]], [[TEST1]] ], [ [[C]], [[ENTRY]] ]
-; CHECK-NEXT: ret void
-; CHECK: next:
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: @function2(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[TMP0:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[C:%.*]] = load i32, ptr [[TMP0]], align 4
-; CHECK-NEXT: [[Z:%.*]] = mul i32 [[C]], [[C]]
-; CHECK-NEXT: br i1 true, label [[TEST1:%.*]], label [[FIRST:%.*]]
-; CHECK: test1:
-; CHECK-NEXT: [[E:%.*]] = load i32, ptr [[TMP0]], align 4
-; CHECK-NEXT: [[TMP1:%.*]] = add i32 [[C]], [[C]]
-; CHECK-NEXT: br i1 true, label [[FIRST]], label [[TEST:%.*]]
-; CHECK: test:
-; CHECK-NEXT: [[D:%.*]] = load i32, ptr [[TMP0]], align 4
-; CHECK-NEXT: br i1 true, label [[FIRST]], label [[NEXT:%.*]]
-; CHECK: first:
-; CHECK-NEXT: [[TMP2:%.*]] = phi i32 [ [[D]], [[TEST]] ], [ [[E]], [[TEST1]] ], [ [[C]], [[ENTRY:%.*]] ]
-; CHECK-NEXT: [[TMP3:%.*]] = phi i32 [ [[D]], [[TEST]] ], [ [[C]], [[ENTRY]] ], [ [[E]], [[TEST1]] ]
-; CHECK-NEXT: ret void
-; CHECK: next:
-; CHECK-NEXT: ret void
-;
diff --git a/llvm/test/Transforms/IROutliner/no-external-block-entries.ll b/llvm/test/Transforms/IROutliner/no-external-block-entries.ll
deleted file mode 100644
index fb2c5e9701f68..0000000000000
--- a/llvm/test/Transforms/IROutliner/no-external-block-entries.ll
+++ /dev/null
@@ -1,75 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --include-generated-funcs
-; RUN: opt -S -passes=verify,iroutliner -ir-outlining-no-cost < %s | FileCheck %s
-
-; When the an outlined section contains a PHINode no incoming blocks outside
-; the region, we need to make sure that we do not try to reassign
-; the incoming blocks when splitting and reattaching the region.
-
-define void @fn1() local_unnamed_addr #0 {
-entry:
- br label %block_2
-
-block_1:
- %a = phi i32 [ 0, %block_2], [ 1, %intermediate_block_1 ]
- br i1 0, label %block_3, label %block_2
-intermediate_block_1:
- br label %block_1
-block_2:
- br i1 0, label %block_3, label %block_1
-
-block_3:
- %b = phi i32 [ 0, %block_2 ], [ 1, %block_1 ]
- br label %block_5
-
-block_4:
- %c = phi i32 [ 0, %block_5 ], [ 1, %intermediate_block_2 ]
- br i1 0, label %block_6, label %block_5
-intermediate_block_2:
- br label %block_4
-block_5:
- br i1 0, label %block_6, label %block_4
-
-block_6:
- unreachable
-}
-; CHECK-LABEL: @fn1(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[B_CE_LOC:%.*]] = alloca i32, align 4
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[B_CE_LOC]])
-; CHECK-NEXT: call void @outlined_ir_func_0(ptr [[B_CE_LOC]], i32 0)
-; CHECK-NEXT: [[B_CE_RELOAD:%.*]] = load i32, ptr [[B_CE_LOC]], align 4
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[B_CE_LOC]])
-; CHECK-NEXT: br label [[BLOCK_3:%.*]]
-; CHECK: block_3:
-; CHECK-NEXT: [[B:%.*]] = phi i32 [ [[B_CE_RELOAD]], [[ENTRY:%.*]] ]
-; CHECK-NEXT: call void @outlined_ir_func_0(ptr null, i32 -1)
-; CHECK-NEXT: br label [[BLOCK_6:%.*]]
-; CHECK: block_6:
-; CHECK-NEXT: unreachable
-;
-;
-; CHECK-LABEL: define internal void @outlined_ir_func_0(
-; CHECK-NEXT: newFuncRoot:
-; CHECK-NEXT: br label [[ENTRY_TO_OUTLINE:%.*]]
-; CHECK: entry_to_outline:
-; CHECK-NEXT: br label [[BLOCK_2:%.*]]
-; CHECK: block_1:
-; CHECK-NEXT: [[A:%.*]] = phi i32 [ 0, [[BLOCK_2]] ], [ 1, [[INTERMEDIATE_BLOCK_1:%.*]] ]
-; CHECK-NEXT: br i1 false, label [[BLOCK_3_SPLIT:%.*]], label [[BLOCK_2]]
-; CHECK: intermediate_block_1:
-; CHECK-NEXT: br label [[BLOCK_1:%.*]]
-; CHECK: block_2:
-; CHECK-NEXT: br i1 false, label [[BLOCK_3_SPLIT]], label [[BLOCK_1]]
-; CHECK: block_3.split:
-; CHECK-NEXT: [[B_CE:%.*]] = phi i32 [ 0, [[BLOCK_2]] ], [ 1, [[BLOCK_1]] ]
-; CHECK-NEXT: br label [[BLOCK_3_EXITSTUB:%.*]]
-; CHECK: block_3.exitStub:
-; CHECK-NEXT: switch i32 [[TMP1:%.*]], label [[FINAL_BLOCK_0:%.*]] [
-; CHECK-NEXT: i32 0, label [[OUTPUT_BLOCK_0_0:%.*]]
-; CHECK-NEXT: ]
-; CHECK: output_block_0_0:
-; CHECK-NEXT: store i32 [[B_CE]], ptr [[TMP0:%.*]], align 4
-; CHECK-NEXT: br label [[FINAL_BLOCK_0]]
-; CHECK: final_block_0:
-; CHECK-NEXT: ret void
-;
diff --git a/llvm/test/Transforms/IROutliner/no-outlining-optnone.ll b/llvm/test/Transforms/IROutliner/no-outlining-optnone.ll
deleted file mode 100644
index 4d1836b544c1e..0000000000000
--- a/llvm/test/Transforms/IROutliner/no-outlining-optnone.ll
+++ /dev/null
@@ -1,61 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --include-generated-funcs
-; RUN: opt -S -passes=verify,iroutliner -ir-outlining-no-cost < %s | FileCheck %s
-
-; Ensure that a function is not outlined if a function has the optnone
-; attribute.
-
-define void @outline_constants1() optnone noinline {
-entry:
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- %c = alloca i32, align 4
- store i32 3, ptr %a, align 4
- store i32 4, ptr %b, align 4
- store i32 5, ptr %c, align 4
- %al = load i32, ptr %a
- %bl = load i32, ptr %b
- %cl = load i32, ptr %c
- ret void
-}
-
-define void @outline_constants2() optnone noinline {
-entry:
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- %c = alloca i32, align 4
- store i32 2, ptr %a, align 4
- store i32 3, ptr %b, align 4
- store i32 4, ptr %c, align 4
- %al = load i32, ptr %a
- %bl = load i32, ptr %b
- %cl = load i32, ptr %c
- ret void
-}
-
-; CHECK-LABEL: @outline_constants1(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[C:%.*]] = alloca i32, align 4
-; CHECK-NEXT: store i32 3, ptr [[A]], align 4
-; CHECK-NEXT: store i32 4, ptr [[B]], align 4
-; CHECK-NEXT: store i32 5, ptr [[C]], align 4
-; CHECK-NEXT: [[AL:%.*]] = load i32, ptr [[A]], align 4
-; CHECK-NEXT: [[BL:%.*]] = load i32, ptr [[B]], align 4
-; CHECK-NEXT: [[CL:%.*]] = load i32, ptr [[C]], align 4
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: @outline_constants2(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[C:%.*]] = alloca i32, align 4
-; CHECK-NEXT: store i32 2, ptr [[A]], align 4
-; CHECK-NEXT: store i32 3, ptr [[B]], align 4
-; CHECK-NEXT: store i32 4, ptr [[C]], align 4
-; CHECK-NEXT: [[AL:%.*]] = load i32, ptr [[A]], align 4
-; CHECK-NEXT: [[BL:%.*]] = load i32, ptr [[B]], align 4
-; CHECK-NEXT: [[CL:%.*]] = load i32, ptr [[C]], align 4
-; CHECK-NEXT: ret void
-;
diff --git a/llvm/test/Transforms/IROutliner/nooutline-attribute.ll b/llvm/test/Transforms/IROutliner/nooutline-attribute.ll
deleted file mode 100644
index a61a1614a3115..0000000000000
--- a/llvm/test/Transforms/IROutliner/nooutline-attribute.ll
+++ /dev/null
@@ -1,30 +0,0 @@
-; RUN: opt -S -debug-only=iroutliner -p=iroutliner -ir-outlining-no-cost %s -o - 2>&1 | FileCheck %s
-; REQUIRES: asserts
-
-; CHECK-NOT: ... Skipping function with nooutline attribute: outlinable
-; CHECK-NOT: @outlined_ir_func
-; CHECK: ... Skipping function with nooutline attribute: nooutline1
-; CHECK: ... Skipping function with nooutline attribute: nooutline2
-
-define void @outlinable() { ret void }
-
-define i8 @nooutline1(ptr noalias %s, ptr noalias %d, i64 %len) nooutline {
- %a = load i8, ptr %s
- %b = load i8, ptr %d
- call void @llvm.memcpy.p0.p0.i64(ptr %d, ptr %s, i64 %len, i1 false)
- %c = add i8 %a, %b
- %ret = load i8, ptr %s
- ret i8 %ret
-}
-
-define i8 @nooutline2(ptr noalias %s, ptr noalias %d, i64 %len) nooutline {
- %a = load i8, ptr %s
- %b = load i8, ptr %d
- call void @llvm.memcpy.p0.p0.i64(ptr %d, ptr %s, i64 %len, i1 false)
- %c = add i8 %a, %b
- %ret = load i8, ptr %s
- ret i8 %ret
-}
-
-declare void @llvm.memcpy.p0.p0.i64(ptr nocapture writeonly, ptr nocapture readonly, i64, i1)
-
diff --git a/llvm/test/Transforms/IROutliner/one-external-incoming-block-phi-node.ll b/llvm/test/Transforms/IROutliner/one-external-incoming-block-phi-node.ll
deleted file mode 100644
index 96272745df70b..0000000000000
--- a/llvm/test/Transforms/IROutliner/one-external-incoming-block-phi-node.ll
+++ /dev/null
@@ -1,71 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --include-generated-funcs
-; RUN: opt -S -passes=verify,iroutliner -ir-outlining-no-cost < %s | FileCheck %s
-
-; When the an outlined section contains a PHINode with an incoming block
-; outside of the region, the predecessors to be handled specially to ensure that
-; a global value is properly assigned. This ensures that there is no crash
-; in that situation.
-
-define void @fn1() local_unnamed_addr #0 {
-entry:
- br label %block_1
-
-block_1:
- %a = phi i32 [ 0, %block_2], [ 1, %entry ]
- br i1 0, label %block_3, label %block_2
-block_2:
- br i1 0, label %block_3, label %block_1
-
-block_3:
- %b = phi i32 [ 0, %block_2 ], [ 1, %block_1 ]
- br label %block_4
-
-block_4:
- %c = phi i32 [ 0, %block_5 ], [ 1, %block_3 ]
- br i1 0, label %block_6, label %block_5
-
-block_5:
- br i1 0, label %block_6, label %block_4
-
-block_6:
- unreachable
-}
-; CHECK-LABEL: @fn1(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[B_CE_LOC:%.*]] = alloca i32, align 4
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[B_CE_LOC]])
-; CHECK-NEXT: call void @outlined_ir_func_0(ptr [[B_CE_LOC]], i32 0)
-; CHECK-NEXT: [[B_CE_RELOAD:%.*]] = load i32, ptr [[B_CE_LOC]], align 4
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[B_CE_LOC]])
-; CHECK-NEXT: br label [[BLOCK_3:%.*]]
-; CHECK: block_3:
-; CHECK-NEXT: [[B:%.*]] = phi i32 [ [[B_CE_RELOAD]], [[ENTRY:%.*]] ]
-; CHECK-NEXT: call void @outlined_ir_func_0(ptr null, i32 -1)
-; CHECK-NEXT: br label [[BLOCK_6:%.*]]
-; CHECK: block_6:
-; CHECK-NEXT: unreachable
-;
-;
-; CHECK-LABEL: define internal void @outlined_ir_func_0(
-; CHECK-NEXT: newFuncRoot:
-; CHECK-NEXT: br label [[ENTRY_TO_OUTLINE:%.*]]
-; CHECK: entry_to_outline:
-; CHECK-NEXT: br label [[BLOCK_1:%.*]]
-; CHECK: block_1:
-; CHECK-NEXT: [[A:%.*]] = phi i32 [ 0, [[BLOCK_2:%.*]] ], [ 1, [[ENTRY_TO_OUTLINE]] ]
-; CHECK-NEXT: br i1 false, label [[BLOCK_3_SPLIT:%.*]], label [[BLOCK_2]]
-; CHECK: block_2:
-; CHECK-NEXT: br i1 false, label [[BLOCK_3_SPLIT]], label [[BLOCK_1]]
-; CHECK: block_3.split:
-; CHECK-NEXT: [[B_CE:%.*]] = phi i32 [ 0, [[BLOCK_2]] ], [ 1, [[BLOCK_1]] ]
-; CHECK-NEXT: br label [[BLOCK_3_EXITSTUB:%.*]]
-; CHECK: block_3.exitStub:
-; CHECK-NEXT: switch i32 [[TMP1:%.*]], label [[FINAL_BLOCK_0:%.*]] [
-; CHECK-NEXT: i32 0, label [[OUTPUT_BLOCK_0_0:%.*]]
-; CHECK-NEXT: ]
-; CHECK: output_block_0_0:
-; CHECK-NEXT: store i32 [[B_CE]], ptr [[TMP0:%.*]], align 4
-; CHECK-NEXT: br label [[FINAL_BLOCK_0]]
-; CHECK: final_block_0:
-; CHECK-NEXT: ret void
-;
diff --git a/llvm/test/Transforms/IROutliner/opt-remarks.ll b/llvm/test/Transforms/IROutliner/opt-remarks.ll
deleted file mode 100644
index e0dc72bf8df59..0000000000000
--- a/llvm/test/Transforms/IROutliner/opt-remarks.ll
+++ /dev/null
@@ -1,405 +0,0 @@
-; RUN: opt -S -passes=verify,iroutliner -o /dev/null \
-; RUN: -pass-remarks=iroutliner -pass-remarks-missed=iroutliner < %s \
-; RUN: 2>&1 | FileCheck -check-prefix=CHECK %s
-; RUN: opt -S -passes=verify,iroutliner -o /dev/null \
-; RUN: -pass-remarks-output=%t < %s
-; RUN: cat %t | FileCheck -check-prefix=YAML %s
-
-; CHECK: remark: <unknown>:0:0: did not outline 2 regions due to estimated increase of 10 instructions at locations <UNKNOWN LOCATION> <UNKNOWN LOCATION>
-; CHECK-NEXT: remark: <unknown>:0:0: did not outline 2 regions due to estimated increase of 4 instructions at locations <UNKNOWN LOCATION> <UNKNOWN LOCATION>
-; CHECK-NEXT: remark: <unknown>:0:0: did not outline 2 regions due to estimated increase of 0 instructions at locations <UNKNOWN LOCATION> <UNKNOWN LOCATION>
-; CHECK-NEXT: remark: <unknown>:0:0: did not outline 2 regions due to estimated increase of 10 instructions at locations <UNKNOWN LOCATION> <UNKNOWN LOCATION>
-; CHECK-NEXT: remark: <unknown>:0:0: did not outline 2 regions due to estimated increase of 1 instructions at locations <UNKNOWN LOCATION> <UNKNOWN LOCATION>
-; CHECK-NEXT: remark: <unknown>:0:0: did not outline 2 regions due to estimated increase of 11 instructions at locations <UNKNOWN LOCATION> <UNKNOWN LOCATION>
-; CHECK-NEXT: remark: <unknown>:0:0: did not outline 2 regions due to estimated increase of 12 instructions at locations <UNKNOWN LOCATION> <UNKNOWN LOCATION>
-; CHECK-NEXT: remark: <unknown>:0:0: did not outline 2 regions due to estimated increase of 2 instructions at locations <UNKNOWN LOCATION> <UNKNOWN LOCATION>
-; CHECK-NEXT: remark: <unknown>:0:0: did not outline 2 regions due to estimated increase of 3 instructions at locations <UNKNOWN LOCATION> <UNKNOWN LOCATION>
-; CHECK-NEXT: remark: <unknown>:0:0: did not outline 2 regions due to estimated increase of 13 instructions at locations <UNKNOWN LOCATION> <UNKNOWN LOCATION>
-; CHECK-NEXT: remark: <unknown>:0:0: did not outline 2 regions due to estimated increase of 4 instructions at locations <UNKNOWN LOCATION> <UNKNOWN LOCATION>
-; CHECK-NEXT: remark: <unknown>:0:0: did not outline 2 regions due to estimated increase of 14 instructions at locations <UNKNOWN LOCATION> <UNKNOWN LOCATION>
-; CHECK-NEXT: remark: <unknown>:0:0: did not outline 2 regions due to estimated increase of 5 instructions at locations <UNKNOWN LOCATION> <UNKNOWN LOCATION>
-; CHECK-NEXT: remark: <unknown>:0:0: did not outline 2 regions due to estimated increase of 10 instructions at locations <UNKNOWN LOCATION> <UNKNOWN LOCATION>
-; CHECK-NEXT: remark: <unknown>:0:0: did not outline 2 regions due to estimated increase of 11 instructions at locations <UNKNOWN LOCATION> <UNKNOWN LOCATION>
-; CHECK-NEXT: remark: <unknown>:0:0: did not outline 2 regions due to estimated increase of 6 instructions at locations <UNKNOWN LOCATION> <UNKNOWN LOCATION>
-; CHECK-NEXT: remark: <unknown>:0:0: did not outline 2 regions due to estimated increase of 7 instructions at locations <UNKNOWN LOCATION> <UNKNOWN LOCATION>
-; CHECK-NEXT: remark: <unknown>:0:0: did not outline 2 regions due to estimated increase of 17 instructions at locations <UNKNOWN LOCATION> <UNKNOWN LOCATION>
-; CHECK-NEXT: remark: <unknown>:0:0: did not outline 2 regions due to estimated increase of 13 instructions at locations <UNKNOWN LOCATION> <UNKNOWN LOCATION>
-; CHECK-NEXT: remark: <unknown>:0:0: did not outline 2 regions due to estimated increase of 8 instructions at locations <UNKNOWN LOCATION> <UNKNOWN LOCATION>
-; CHECK-NEXT: remark: <unknown>:0:0: outlined 2 regions with decrease of 2 instructions at locations <UNKNOWN LOCATION> <UNKNOWN LOCATION>
-
-; YAML: --- !Missed
-; YAML-NEXT: Pass: iroutliner
-; YAML-NEXT: Name: WouldNotDecreaseSize
-; YAML-NEXT: Function: function3
-; YAML-NEXT: Args:
-; YAML-NEXT: - String: 'did not outline '
-; YAML-NEXT: - String: '2'
-; YAML-NEXT: - String: ' regions due to estimated increase of '
-; YAML-NEXT: - InstructionIncrease: '10'
-; YAML-NEXT: - String: ' instructions at locations '
-; YAML-NEXT: - DebugLoc: '<UNKNOWN LOCATION>'
-; YAML-NEXT: - String: ' '
-; YAML-NEXT: - DebugLoc: '<UNKNOWN LOCATION>'
-; YAML-NEXT: ...
-; YAML-NEXT: --- !Missed
-; YAML-NEXT: Pass: iroutliner
-; YAML-NEXT: Name: WouldNotDecreaseSize
-; YAML-NEXT: Function: function3
-; YAML-NEXT: Args:
-; YAML-NEXT: - String: 'did not outline '
-; YAML-NEXT: - String: '2'
-; YAML-NEXT: - String: ' regions due to estimated increase of '
-; YAML-NEXT: - InstructionIncrease: '4'
-; YAML-NEXT: - String: ' instructions at locations '
-; YAML-NEXT: - DebugLoc: '<UNKNOWN LOCATION>'
-; YAML-NEXT: - String: ' '
-; YAML-NEXT: - DebugLoc: '<UNKNOWN LOCATION>'
-; YAML-NEXT: ...
-; YAML-NEXT: --- !Missed
-; YAML-NEXT: Pass: iroutliner
-; YAML-NEXT: Name: WouldNotDecreaseSize
-; YAML-NEXT: Function: function3
-; YAML-NEXT: Args:
-; YAML-NEXT: - String: 'did not outline '
-; YAML-NEXT: - String: '2'
-; YAML-NEXT: - String: ' regions due to estimated increase of '
-; YAML-NEXT: - InstructionIncrease: '0'
-; YAML-NEXT: - String: ' instructions at locations '
-; YAML-NEXT: - DebugLoc: '<UNKNOWN LOCATION>'
-; YAML-NEXT: - String: ' '
-; YAML-NEXT: - DebugLoc: '<UNKNOWN LOCATION>'
-; YAML-NEXT: ...
-; YAML-NEXT: --- !Missed
-; YAML-NEXT: Pass: iroutliner
-; YAML-NEXT: Name: WouldNotDecreaseSize
-; YAML-NEXT: Function: function1
-; YAML-NEXT: Args:
-; YAML-NEXT: - String: 'did not outline '
-; YAML-NEXT: - String: '2'
-; YAML-NEXT: - String: ' regions due to estimated increase of '
-; YAML-NEXT: - InstructionIncrease: '10'
-; YAML-NEXT: - String: ' instructions at locations '
-; YAML-NEXT: - DebugLoc: '<UNKNOWN LOCATION>'
-; YAML-NEXT: - String: ' '
-; YAML-NEXT: - DebugLoc: '<UNKNOWN LOCATION>'
-; YAML-NEXT: ...
-; YAML-NEXT: --- !Missed
-; YAML-NEXT: Pass: iroutliner
-; YAML-NEXT: Name: WouldNotDecreaseSize
-; YAML-NEXT: Function: function3
-; YAML-NEXT: Args:
-; YAML-NEXT: - String: 'did not outline '
-; YAML-NEXT: - String: '2'
-; YAML-NEXT: - String: ' regions due to estimated increase of '
-; YAML-NEXT: - InstructionIncrease: '1'
-; YAML-NEXT: - String: ' instructions at locations '
-; YAML-NEXT: - DebugLoc: '<UNKNOWN LOCATION>'
-; YAML-NEXT: - String: ' '
-; YAML-NEXT: - DebugLoc: '<UNKNOWN LOCATION>'
-; YAML-NEXT: ...
-; YAML-NEXT: --- !Missed
-; YAML-NEXT: Pass: iroutliner
-; YAML-NEXT: Name: WouldNotDecreaseSize
-; YAML-NEXT: Function: function1
-; YAML-NEXT: Args:
-; YAML-NEXT: - String: 'did not outline '
-; YAML-NEXT: - String: '2'
-; YAML-NEXT: - String: ' regions due to estimated increase of '
-; YAML-NEXT: - InstructionIncrease: '11'
-; YAML-NEXT: - String: ' instructions at locations '
-; YAML-NEXT: - DebugLoc: '<UNKNOWN LOCATION>'
-; YAML-NEXT: - String: ' '
-; YAML-NEXT: - DebugLoc: '<UNKNOWN LOCATION>'
-; YAML-NEXT: ...
-; YAML-NEXT: --- !Missed
-; YAML-NEXT: Pass: iroutliner
-; YAML-NEXT: Name: WouldNotDecreaseSize
-; YAML-NEXT: Function: function1
-; YAML-NEXT: Args:
-; YAML-NEXT: - String: 'did not outline '
-; YAML-NEXT: - String: '2'
-; YAML-NEXT: - String: ' regions due to estimated increase of '
-; YAML-NEXT: - InstructionIncrease: '12'
-; YAML-NEXT: - String: ' instructions at locations '
-; YAML-NEXT: - DebugLoc: '<UNKNOWN LOCATION>'
-; YAML-NEXT: - String: ' '
-; YAML-NEXT: - DebugLoc: '<UNKNOWN LOCATION>'
-; YAML-NEXT: ...
-; YAML-NEXT: --- !Missed
-; YAML-NEXT: Pass: iroutliner
-; YAML-NEXT: Name: WouldNotDecreaseSize
-; YAML-NEXT: Function: function3
-; YAML-NEXT: Args:
-; YAML-NEXT: - String: 'did not outline '
-; YAML-NEXT: - String: '2'
-; YAML-NEXT: - String: ' regions due to estimated increase of '
-; YAML-NEXT: - InstructionIncrease: '2'
-; YAML-NEXT: - String: ' instructions at locations '
-; YAML-NEXT: - DebugLoc: '<UNKNOWN LOCATION>'
-; YAML-NEXT: - String: ' '
-; YAML-NEXT: - DebugLoc: '<UNKNOWN LOCATION>'
-; YAML-NEXT: ...
-; YAML-NEXT: --- !Missed
-; YAML-NEXT: Pass: iroutliner
-; YAML-NEXT: Name: WouldNotDecreaseSize
-; YAML-NEXT: Function: function3
-; YAML-NEXT: Args:
-; YAML-NEXT: - String: 'did not outline '
-; YAML-NEXT: - String: '2'
-; YAML-NEXT: - String: ' regions due to estimated increase of '
-; YAML-NEXT: - InstructionIncrease: '3'
-; YAML-NEXT: - String: ' instructions at locations '
-; YAML-NEXT: - DebugLoc: '<UNKNOWN LOCATION>'
-; YAML-NEXT: - String: ' '
-; YAML-NEXT: - DebugLoc: '<UNKNOWN LOCATION>'
-; YAML-NEXT: ...
-; YAML-NEXT: --- !Missed
-; YAML-NEXT: Pass: iroutliner
-; YAML-NEXT: Name: WouldNotDecreaseSize
-; YAML-NEXT: Function: function1
-; YAML-NEXT: Args:
-; YAML-NEXT: - String: 'did not outline '
-; YAML-NEXT: - String: '2'
-; YAML-NEXT: - String: ' regions due to estimated increase of '
-; YAML-NEXT: - InstructionIncrease: '13'
-; YAML-NEXT: - String: ' instructions at locations '
-; YAML-NEXT: - DebugLoc: '<UNKNOWN LOCATION>'
-; YAML-NEXT: - String: ' '
-; YAML-NEXT: - DebugLoc: '<UNKNOWN LOCATION>'
-; YAML-NEXT: ...
-; YAML-NEXT: --- !Missed
-; YAML-NEXT: Pass: iroutliner
-; YAML-NEXT: Name: WouldNotDecreaseSize
-; YAML-NEXT: Function: function3
-; YAML-NEXT: Args:
-; YAML-NEXT: - String: 'did not outline '
-; YAML-NEXT: - String: '2'
-; YAML-NEXT: - String: ' regions due to estimated increase of '
-; YAML-NEXT: - InstructionIncrease: '4'
-; YAML-NEXT: - String: ' instructions at locations '
-; YAML-NEXT: - DebugLoc: '<UNKNOWN LOCATION>'
-; YAML-NEXT: - String: ' '
-; YAML-NEXT: - DebugLoc: '<UNKNOWN LOCATION>'
-; YAML-NEXT: ...
-; YAML-NEXT: --- !Missed
-; YAML-NEXT: Pass: iroutliner
-; YAML-NEXT: Name: WouldNotDecreaseSize
-; YAML-NEXT: Function: function1
-; YAML-NEXT: Args:
-; YAML-NEXT: - String: 'did not outline '
-; YAML-NEXT: - String: '2'
-; YAML-NEXT: - String: ' regions due to estimated increase of '
-; YAML-NEXT: - InstructionIncrease: '14'
-; YAML-NEXT: - String: ' instructions at locations '
-; YAML-NEXT: - DebugLoc: '<UNKNOWN LOCATION>'
-; YAML-NEXT: - String: ' '
-; YAML-NEXT: - DebugLoc: '<UNKNOWN LOCATION>'
-; YAML-NEXT: ...
-; YAML-NEXT: --- !Missed
-; YAML-NEXT: Pass: iroutliner
-; YAML-NEXT: Name: WouldNotDecreaseSize
-; YAML-NEXT: Function: function3
-; YAML-NEXT: Args:
-; YAML-NEXT: - String: 'did not outline '
-; YAML-NEXT: - String: '2'
-; YAML-NEXT: - String: ' regions due to estimated increase of '
-; YAML-NEXT: - InstructionIncrease: '5'
-; YAML-NEXT: - String: ' instructions at locations '
-; YAML-NEXT: - DebugLoc: '<UNKNOWN LOCATION>'
-; YAML-NEXT: - String: ' '
-; YAML-NEXT: - DebugLoc: '<UNKNOWN LOCATION>'
-; YAML-NEXT: ...
-; YAML-NEXT: --- !Missed
-; YAML-NEXT: Pass: iroutliner
-; YAML-NEXT: Name: WouldNotDecreaseSize
-; YAML-NEXT: Function: function1
-; YAML-NEXT: Args:
-; YAML-NEXT: - String: 'did not outline '
-; YAML-NEXT: - String: '2'
-; YAML-NEXT: - String: ' regions due to estimated increase of '
-; YAML-NEXT: - InstructionIncrease: '10'
-; YAML-NEXT: - String: ' instructions at locations '
-; YAML-NEXT: - DebugLoc: '<UNKNOWN LOCATION>'
-; YAML-NEXT: - String: ' '
-; YAML-NEXT: - DebugLoc: '<UNKNOWN LOCATION>'
-; YAML-NEXT: ...
-; YAML-NEXT: --- !Missed
-; YAML-NEXT: Pass: iroutliner
-; YAML-NEXT: Name: WouldNotDecreaseSize
-; YAML-NEXT: Function: function1
-; YAML-NEXT: Args:
-; YAML-NEXT: - String: 'did not outline '
-; YAML-NEXT: - String: '2'
-; YAML-NEXT: - String: ' regions due to estimated increase of '
-; YAML-NEXT: - InstructionIncrease: '11'
-; YAML-NEXT: - String: ' instructions at locations '
-; YAML-NEXT: - DebugLoc: '<UNKNOWN LOCATION>'
-; YAML-NEXT: - String: ' '
-; YAML-NEXT: - DebugLoc: '<UNKNOWN LOCATION>'
-; YAML-NEXT: ...
-; YAML-NEXT: --- !Missed
-; YAML-NEXT: Pass: iroutliner
-; YAML-NEXT: Name: WouldNotDecreaseSize
-; YAML-NEXT: Function: function3
-; YAML-NEXT: Args:
-; YAML-NEXT: - String: 'did not outline '
-; YAML-NEXT: - String: '2'
-; YAML-NEXT: - String: ' regions due to estimated increase of '
-; YAML-NEXT: - InstructionIncrease: '6'
-; YAML-NEXT: - String: ' instructions at locations '
-; YAML-NEXT: - DebugLoc: '<UNKNOWN LOCATION>'
-; YAML-NEXT: - String: ' '
-; YAML-NEXT: - DebugLoc: '<UNKNOWN LOCATION>'
-; YAML-NEXT: ...
-; YAML-NEXT: --- !Missed
-; YAML-NEXT: Pass: iroutliner
-; YAML-NEXT: Name: WouldNotDecreaseSize
-; YAML-NEXT: Function: function3
-; YAML-NEXT: Args:
-; YAML-NEXT: - String: 'did not outline '
-; YAML-NEXT: - String: '2'
-; YAML-NEXT: - String: ' regions due to estimated increase of '
-; YAML-NEXT: - InstructionIncrease: '7'
-; YAML-NEXT: - String: ' instructions at locations '
-; YAML-NEXT: - DebugLoc: '<UNKNOWN LOCATION>'
-; YAML-NEXT: - String: ' '
-; YAML-NEXT: - DebugLoc: '<UNKNOWN LOCATION>'
-; YAML-NEXT: ...
-; YAML-NEXT: --- !Missed
-; YAML-NEXT: Pass: iroutliner
-; YAML-NEXT: Name: WouldNotDecreaseSize
-; YAML-NEXT: Function: function1
-; YAML-NEXT: Args:
-; YAML-NEXT: - String: 'did not outline '
-; YAML-NEXT: - String: '2'
-; YAML-NEXT: - String: ' regions due to estimated increase of '
-; YAML-NEXT: - InstructionIncrease: '17'
-; YAML-NEXT: - String: ' instructions at locations '
-; YAML-NEXT: - DebugLoc: '<UNKNOWN LOCATION>'
-; YAML-NEXT: - String: ' '
-; YAML-NEXT: - DebugLoc: '<UNKNOWN LOCATION>'
-; YAML-NEXT: ...
-; YAML-NEXT: --- !Missed
-; YAML-NEXT: Pass: iroutliner
-; YAML-NEXT: Name: WouldNotDecreaseSize
-; YAML-NEXT: Function: function1
-; YAML-NEXT: Args:
-; YAML-NEXT: - String: 'did not outline '
-; YAML-NEXT: - String: '2'
-; YAML-NEXT: - String: ' regions due to estimated increase of '
-; YAML-NEXT: - InstructionIncrease: '13'
-; YAML-NEXT: - String: ' instructions at locations '
-; YAML-NEXT: - DebugLoc: '<UNKNOWN LOCATION>'
-; YAML-NEXT: - String: ' '
-; YAML-NEXT: - DebugLoc: '<UNKNOWN LOCATION>'
-; YAML-NEXT: ...
-; YAML-NEXT: --- !Missed
-; YAML-NEXT: Pass: iroutliner
-; YAML-NEXT: Name: WouldNotDecreaseSize
-; YAML-NEXT: Function: function3
-; YAML-NEXT: Args:
-; YAML-NEXT: - String: 'did not outline '
-; YAML-NEXT: - String: '2'
-; YAML-NEXT: - String: ' regions due to estimated increase of '
-; YAML-NEXT: - InstructionIncrease: '8'
-; YAML-NEXT: - String: ' instructions at locations '
-; YAML-NEXT: - DebugLoc: '<UNKNOWN LOCATION>'
-; YAML-NEXT: - String: ' '
-; YAML-NEXT: - DebugLoc: '<UNKNOWN LOCATION>'
-; YAML-NEXT: ...
-; YAML-NEXT: --- !Passed
-; YAML-NEXT: Pass: iroutliner
-; YAML-NEXT: Name: Outlined
-; YAML-NEXT: Function: function3.outlined
-; YAML-NEXT: Args:
-; YAML-NEXT: - String: 'outlined '
-; YAML-NEXT: - String: '2'
-; YAML-NEXT: - String: ' regions with decrease of '
-; YAML-NEXT: - Benefit: '2'
-; YAML-NEXT: - String: ' instructions at locations '
-; YAML-NEXT: - DebugLoc: '<UNKNOWN LOCATION>'
-; YAML-NEXT: - String: ' '
-; YAML-NEXT: - DebugLoc: '<UNKNOWN LOCATION>'
-; YAML-NEXT: ...
-
-define void @function1() #0 {
-entry:
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- %output = alloca i32, align 4
- %result = alloca i32, align 4
- store i32 2, ptr %a, align 4
- store i32 3, ptr %b, align 4
- %0 = load i32, ptr %a, align 4
- %1 = load i32, ptr %b, align 4
- %add = add i32 %0, %1
- store i32 %add, ptr %output, align 4
- %2 = load i32, ptr %output, align 4
- %3 = load i32, ptr %output, align 4
- %mul = mul i32 %2, %add
- store i32 %mul, ptr %result, align 4
- ret void
-}
-
-define void @function2() #0 {
-entry:
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- %output = alloca i32, align 4
- %result = alloca i32, align 4
- store i32 2, ptr %a, align 4
- store i32 3, ptr %b, align 4
- %0 = load i32, ptr %a, align 4
- %1 = load i32, ptr %b, align 4
- %add = add i32 %0, %1
- store i32 %add, ptr %output, align 4
- %2 = load i32, ptr %output, align 4
- %3 = load i32, ptr %output, align 4
- %mul = mul i32 %2, %add
- store i32 %mul, ptr %result, align 4
- ret void
-}
-
-define void @function3() #0 {
-entry:
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- %0 = load i32, ptr %a, align 4
- %1 = load i32, ptr %b, align 4
- %add = add i32 %0, %1
- %mul = mul i32 %0, %1
- %sub = sub i32 %0, %1
- %div = sdiv i32 %0, %1
- %add1 = add i32 %0, %1
- %mul1 = mul i32 %0, %1
- %sub1 = sub i32 %0, %1
- %div1 = sdiv i32 %0, %1
- %add2 = add i32 %0, %1
- %mul2 = mul i32 %0, %1
- %sub2 = sub i32 %0, %1
- %div2 = sdiv i32 %0, %1
- %mul3 = mul i32 %0, %1
- ret void
-}
-
-define void @function4() #0 {
-entry:
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- %0 = load i32, ptr %a, align 4
- %1 = load i32, ptr %b, align 4
- %add = add i32 %0, %1
- %mul = mul i32 %0, %1
- %sub = sub i32 %0, %1
- %div = sdiv i32 %0, %1
- %add1 = add i32 %0, %1
- %mul1 = mul i32 %0, %1
- %sub1 = sub i32 %0, %1
- %div1 = sdiv i32 %0, %1
- %add2 = add i32 %0, %1
- %mul2 = mul i32 %0, %1
- %sub2 = sub i32 %0, %1
- %div2 = sdiv i32 %0, %1
- %div3 = sdiv i32 %0, %1
- ret void
-}
diff --git a/llvm/test/Transforms/IROutliner/outline-memcpy.ll b/llvm/test/Transforms/IROutliner/outline-memcpy.ll
deleted file mode 100644
index 83fd5f6af925c..0000000000000
--- a/llvm/test/Transforms/IROutliner/outline-memcpy.ll
+++ /dev/null
@@ -1,60 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --include-generated-funcs
-; RUN: opt -S -passes=verify,iroutliner -ir-outlining-no-cost < %s | FileCheck %s
-
-; This test checks that we successfully outline identical memcpy instructions.
-
-declare void @llvm.memcpy.p0.p0.i64(ptr nocapture writeonly, ptr nocapture readonly, i64, i1)
-
-define i8 @function1(ptr noalias %s, ptr noalias %d, i64 %len) {
-entry:
- %a = load i8, ptr %s
- %b = load i8, ptr %d
- call void @llvm.memcpy.p0.p0.i64(ptr %d, ptr %s, i64 %len, i1 false)
- %c = add i8 %a, %b
- %ret = load i8, ptr %s
- ret i8 %ret
-}
-
-define i8 @function2(ptr noalias %s, ptr noalias %d, i64 %len) {
-entry:
- %a = load i8, ptr %s
- %b = load i8, ptr %d
- call void @llvm.memcpy.p0.p0.i64(ptr %d, ptr %s, i64 %len, i1 false)
- %c = add i8 %a, %b
- %ret = load i8, ptr %s
- ret i8 %ret
-}
-; CHECK-LABEL: @function1(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[RET_LOC:%.*]] = alloca i8, align 1
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[RET_LOC]])
-; CHECK-NEXT: call void @outlined_ir_func_0(ptr [[S:%.*]], ptr [[D:%.*]], i64 [[LEN:%.*]], ptr [[RET_LOC]])
-; CHECK-NEXT: [[RET_RELOAD:%.*]] = load i8, ptr [[RET_LOC]], align 1
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[RET_LOC]])
-; CHECK-NEXT: ret i8 [[RET_RELOAD]]
-;
-;
-; CHECK-LABEL: @function2(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[RET_LOC:%.*]] = alloca i8, align 1
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[RET_LOC]])
-; CHECK-NEXT: call void @outlined_ir_func_0(ptr [[S:%.*]], ptr [[D:%.*]], i64 [[LEN:%.*]], ptr [[RET_LOC]])
-; CHECK-NEXT: [[RET_RELOAD:%.*]] = load i8, ptr [[RET_LOC]], align 1
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[RET_LOC]])
-; CHECK-NEXT: ret i8 [[RET_RELOAD]]
-;
-;
-; CHECK: define internal void @outlined_ir_func_0(
-; CHECK-NEXT: newFuncRoot:
-; CHECK-NEXT: br label [[ENTRY_TO_OUTLINE:%.*]]
-; CHECK: entry_to_outline:
-; CHECK-NEXT: [[A:%.*]] = load i8, ptr [[TMP0:%.*]], align 1
-; CHECK-NEXT: [[B:%.*]] = load i8, ptr [[TMP1:%.*]], align 1
-; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr [[TMP1]], ptr [[TMP0]], i64 [[TMP2:%.*]], i1 false)
-; CHECK-NEXT: [[C:%.*]] = add i8 [[A]], [[B]]
-; CHECK-NEXT: [[RET:%.*]] = load i8, ptr [[TMP0]], align 1
-; CHECK-NEXT: br label [[ENTRY_AFTER_OUTLINE_EXITSTUB:%.*]]
-; CHECK: entry_after_outline.exitStub:
-; CHECK-NEXT: store i8 [[RET]], ptr [[TMP3:%.*]], align 1
-; CHECK-NEXT: ret void
-;
diff --git a/llvm/test/Transforms/IROutliner/outline-memmove.ll b/llvm/test/Transforms/IROutliner/outline-memmove.ll
deleted file mode 100644
index c512cd4a22e8f..0000000000000
--- a/llvm/test/Transforms/IROutliner/outline-memmove.ll
+++ /dev/null
@@ -1,60 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --include-generated-funcs
-; RUN: opt -S -passes=verify,iroutliner -ir-outlining-no-cost < %s | FileCheck %s
-
-; This test checks that we sucecssfully outline identical memmove instructions.
-
-declare void @llvm.memmove.p0.p0.i64(ptr nocapture writeonly, ptr nocapture readonly, i64, i1)
-
-define i8 @function1(ptr noalias %s, ptr noalias %d, i64 %len) {
-entry:
- %a = load i8, ptr %s
- %b = load i8, ptr %d
- call void @llvm.memmove.p0.p0.i64(ptr %d, ptr %s, i64 %len, i1 false)
- %c = add i8 %a, %b
- %ret = load i8, ptr %s
- ret i8 %ret
-}
-
-define i8 @function2(ptr noalias %s, ptr noalias %d, i64 %len) {
-entry:
- %a = load i8, ptr %s
- %b = load i8, ptr %d
- call void @llvm.memmove.p0.p0.i64(ptr %d, ptr %s, i64 %len, i1 false)
- %c = add i8 %a, %b
- %ret = load i8, ptr %s
- ret i8 %ret
-}
-; CHECK-LABEL: @function1(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[RET_LOC:%.*]] = alloca i8, align 1
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[RET_LOC]])
-; CHECK-NEXT: call void @outlined_ir_func_0(ptr [[S:%.*]], ptr [[D:%.*]], i64 [[LEN:%.*]], ptr [[RET_LOC]])
-; CHECK-NEXT: [[RET_RELOAD:%.*]] = load i8, ptr [[RET_LOC]], align 1
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[RET_LOC]])
-; CHECK-NEXT: ret i8 [[RET_RELOAD]]
-;
-;
-; CHECK-LABEL: @function2(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[RET_LOC:%.*]] = alloca i8, align 1
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[RET_LOC]])
-; CHECK-NEXT: call void @outlined_ir_func_0(ptr [[S:%.*]], ptr [[D:%.*]], i64 [[LEN:%.*]], ptr [[RET_LOC]])
-; CHECK-NEXT: [[RET_RELOAD:%.*]] = load i8, ptr [[RET_LOC]], align 1
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[RET_LOC]])
-; CHECK-NEXT: ret i8 [[RET_RELOAD]]
-;
-;
-; CHECK: define internal void @outlined_ir_func_0(
-; CHECK-NEXT: newFuncRoot:
-; CHECK-NEXT: br label [[ENTRY_TO_OUTLINE:%.*]]
-; CHECK: entry_to_outline:
-; CHECK-NEXT: [[A:%.*]] = load i8, ptr [[TMP0:%.*]], align 1
-; CHECK-NEXT: [[B:%.*]] = load i8, ptr [[TMP1:%.*]], align 1
-; CHECK-NEXT: call void @llvm.memmove.p0.p0.i64(ptr [[TMP1]], ptr [[TMP0]], i64 [[TMP2:%.*]], i1 false)
-; CHECK-NEXT: [[C:%.*]] = add i8 [[A]], [[B]]
-; CHECK-NEXT: [[RET:%.*]] = load i8, ptr [[TMP0]], align 1
-; CHECK-NEXT: br label [[ENTRY_AFTER_OUTLINE_EXITSTUB:%.*]]
-; CHECK: entry_after_outline.exitStub:
-; CHECK-NEXT: store i8 [[RET]], ptr [[TMP3:%.*]], align 1
-; CHECK-NEXT: ret void
-;
diff --git a/llvm/test/Transforms/IROutliner/outline-memset.ll b/llvm/test/Transforms/IROutliner/outline-memset.ll
deleted file mode 100644
index 748256d74e736..0000000000000
--- a/llvm/test/Transforms/IROutliner/outline-memset.ll
+++ /dev/null
@@ -1,52 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --include-generated-funcs
-; RUN: opt -S -passes=verify,iroutliner -ir-outlining-no-cost < %s | FileCheck %s
-
-; This test checks that we successfully outline identical memset instructions.
-
-declare void @llvm.memset.p0.i64(ptr nocapture writeonly, i8, i64, i32, i1)
-
-define i64 @function1(i64 %x, i64 %z, i64 %n) {
-entry:
- %pool = alloca [59 x i64], align 4
- call void @llvm.memset.p0.i64(ptr nonnull %pool, i8 0, i64 236, i32 4, i1 false)
- %cmp3 = icmp eq i64 %n, 0
- %a = add i64 %x, %z
- %c = add i64 %x, %z
- ret i64 0
-}
-
-define i64 @function2(i64 %x, i64 %z, i64 %n) {
-entry:
- %pool = alloca [59 x i64], align 4
- call void @llvm.memset.p0.i64(ptr nonnull %pool, i8 0, i64 236, i32 4, i1 false)
- %cmp3 = icmp eq i64 %n, 0
- %a = add i64 %x, %z
- %c = add i64 %x, %z
- ret i64 0
-}
-; CHECK-LABEL: @function1(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[POOL:%.*]] = alloca [59 x i64], align 4
-; CHECK-NEXT: call void @outlined_ir_func_0(ptr [[POOL]], i64 [[N:%.*]], i64 [[X:%.*]], i64 [[Z:%.*]])
-; CHECK-NEXT: ret i64 0
-;
-;
-; CHECK-LABEL: @function2(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[POOL:%.*]] = alloca [59 x i64], align 4
-; CHECK-NEXT: call void @outlined_ir_func_0(ptr [[POOL]], i64 [[N:%.*]], i64 [[X:%.*]], i64 [[Z:%.*]])
-; CHECK-NEXT: ret i64 0
-;
-;
-; CHECK: define internal void @outlined_ir_func_0(
-; CHECK-NEXT: newFuncRoot:
-; CHECK-NEXT: br label [[ENTRY_TO_OUTLINE:%.*]]
-; CHECK: entry_to_outline:
-; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr nonnull align 4 [[TMP0:%.*]], i8 0, i64 236, i1 false)
-; CHECK-NEXT: [[CMP3:%.*]] = icmp eq i64 [[TMP1:%.*]], 0
-; CHECK-NEXT: [[A:%.*]] = add i64 [[TMP2:%.*]], [[TMP3:%.*]]
-; CHECK-NEXT: [[C:%.*]] = add i64 [[TMP2]], [[TMP3]]
-; CHECK-NEXT: br label [[ENTRY_AFTER_OUTLINE_EXITSTUB:%.*]]
-; CHECK: entry_after_outline.exitStub:
-; CHECK-NEXT: ret void
-;
diff --git a/llvm/test/Transforms/IROutliner/outline-vaarg-intrinsic.ll b/llvm/test/Transforms/IROutliner/outline-vaarg-intrinsic.ll
deleted file mode 100644
index 6a9cbca7dfddb..0000000000000
--- a/llvm/test/Transforms/IROutliner/outline-vaarg-intrinsic.ll
+++ /dev/null
@@ -1,95 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --include-generated-funcs
-; RUN: opt -S -passes=verify,iroutliner -ir-outlining-no-cost < %s | FileCheck %s
-
-; This test checks that we sucessfully outline identical memcpy var arg
-; intrinsics, but not the var arg instruction itself.
-
-declare void @llvm.va_start(ptr)
-declare void @llvm.va_copy(ptr, ptr)
-declare void @llvm.va_end(ptr)
-
-define i32 @func1(i32 %a, double %b, ptr %v, ...) nounwind {
-entry:
- %a.addr = alloca i32, align 4
- %b.addr = alloca double, align 8
- %ap = alloca ptr, align 4
- %c = alloca i32, align 4
- store i32 %a, ptr %a.addr, align 4
- store double %b, ptr %b.addr, align 8
- call void @llvm.va_start(ptr %ap)
- %0 = va_arg ptr %ap, i32
- call void @llvm.va_copy(ptr %v, ptr %ap)
- call void @llvm.va_end(ptr %ap)
- store i32 %0, ptr %c, align 4
- %tmp = load i32, ptr %c, align 4
- ret i32 %tmp
-}
-
-define i32 @func2(i32 %a, double %b, ptr %v, ...) nounwind {
-entry:
- %a.addr = alloca i32, align 4
- %b.addr = alloca double, align 8
- %ap = alloca ptr, align 4
- %c = alloca i32, align 4
- store i32 %a, ptr %a.addr, align 4
- store double %b, ptr %b.addr, align 8
- call void @llvm.va_start(ptr %ap)
- %0 = va_arg ptr %ap, i32
- call void @llvm.va_copy(ptr %v, ptr %ap)
- call void @llvm.va_end(ptr %ap)
- store i32 %0, ptr %c, align 4
- %tmp = load i32, ptr %c, align 4
- ret i32 %tmp
-}
-; CHECK-LABEL: define {{[^@]+}}@func1
-; CHECK-SAME: (i32 [[A:%.*]], double [[B:%.*]], ptr [[V:%.*]], ...) #[[ATTR1:[0-9]+]] {
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[TMP_LOC:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B_ADDR:%.*]] = alloca double, align 8
-; CHECK-NEXT: [[AP:%.*]] = alloca ptr, align 4
-; CHECK-NEXT: [[C:%.*]] = alloca i32, align 4
-; CHECK-NEXT: store i32 [[A]], ptr [[A_ADDR]], align 4
-; CHECK-NEXT: store double [[B]], ptr [[B_ADDR]], align 8
-; CHECK-NEXT: call void @llvm.va_start.p0(ptr [[AP]])
-; CHECK-NEXT: [[TMP0:%.*]] = va_arg ptr [[AP]], i32
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[TMP_LOC]])
-; CHECK-NEXT: call void @outlined_ir_func_0(ptr [[V]], ptr [[AP]], i32 [[TMP0]], ptr [[C]], ptr [[TMP_LOC]])
-; CHECK-NEXT: [[TMP_RELOAD:%.*]] = load i32, ptr [[TMP_LOC]], align 4
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[TMP_LOC]])
-; CHECK-NEXT: ret i32 [[TMP_RELOAD]]
-;
-;
-; CHECK-LABEL: define {{[^@]+}}@func2
-; CHECK-SAME: (i32 [[A:%.*]], double [[B:%.*]], ptr [[V:%.*]], ...) #[[ATTR1]] {
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[TMP_LOC:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B_ADDR:%.*]] = alloca double, align 8
-; CHECK-NEXT: [[AP:%.*]] = alloca ptr, align 4
-; CHECK-NEXT: [[C:%.*]] = alloca i32, align 4
-; CHECK-NEXT: store i32 [[A]], ptr [[A_ADDR]], align 4
-; CHECK-NEXT: store double [[B]], ptr [[B_ADDR]], align 8
-; CHECK-NEXT: call void @llvm.va_start.p0(ptr [[AP]])
-; CHECK-NEXT: [[TMP0:%.*]] = va_arg ptr [[AP]], i32
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[TMP_LOC]])
-; CHECK-NEXT: call void @outlined_ir_func_0(ptr [[V]], ptr [[AP]], i32 [[TMP0]], ptr [[C]], ptr [[TMP_LOC]])
-; CHECK-NEXT: [[TMP_RELOAD:%.*]] = load i32, ptr [[TMP_LOC]], align 4
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[TMP_LOC]])
-; CHECK-NEXT: ret i32 [[TMP_RELOAD]]
-;
-;
-; CHECK-LABEL: define {{[^@]+}}@outlined_ir_func_0
-; CHECK-SAME: (ptr [[TMP0:%.*]], ptr [[TMP1:%.*]], i32 [[TMP2:%.*]], ptr [[TMP3:%.*]], ptr [[TMP4:%.*]]) #[[ATTR3:[0-9]+]] {
-; CHECK-NEXT: newFuncRoot:
-; CHECK-NEXT: br label [[ENTRY_TO_OUTLINE:%.*]]
-; CHECK: entry_to_outline:
-; CHECK-NEXT: call void @llvm.va_copy.p0(ptr [[TMP0]], ptr [[TMP1]])
-; CHECK-NEXT: call void @llvm.va_end.p0(ptr [[TMP1]])
-; CHECK-NEXT: store i32 [[TMP2]], ptr [[TMP3]], align 4
-; CHECK-NEXT: [[TMP:%.*]] = load i32, ptr [[TMP3]], align 4
-; CHECK-NEXT: br label [[ENTRY_AFTER_OUTLINE_EXITSTUB:%.*]]
-; CHECK: entry_after_outline.exitStub:
-; CHECK-NEXT: store i32 [[TMP]], ptr [[TMP4]], align 4
-; CHECK-NEXT: ret void
-;
diff --git a/llvm/test/Transforms/IROutliner/outlining-across-branch.ll b/llvm/test/Transforms/IROutliner/outlining-across-branch.ll
deleted file mode 100644
index 4c1675908825c..0000000000000
--- a/llvm/test/Transforms/IROutliner/outlining-across-branch.ll
+++ /dev/null
@@ -1,77 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --include-generated-funcs
-; RUN: opt -S -passes=verify,iroutliner -ir-outlining-no-cost < %s | FileCheck %s
-
-; This checks that we are able to outline exactly the same branch structure
-; while also outlining similar items on either side of the branch.
-
-define void @outline_outputs1() #0 {
-entry:
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- %output = alloca i32, align 4
- %result = alloca i32, align 4
- %output2 = alloca i32, align 4
- %result2 = alloca i32, align 4
- store i32 2, ptr %a, align 4
- store i32 3, ptr %b, align 4
- br label %next
-next:
- store i32 2, ptr %output, align 4
- store i32 3, ptr %result, align 4
- ret void
-}
-
-define void @outline_outputs2() #0 {
-entry:
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- %output = alloca i32, align 4
- %result = alloca i32, align 4
- %output2 = alloca i32, align 4
- %result2 = alloca i32, align 4
- store i32 2, ptr %a, align 4
- store i32 3, ptr %b, align 4
- br label %next
-next:
- store i32 2, ptr %output, align 4
- store i32 3, ptr %result, align 4
- ret void
-}
-; CHECK-LABEL: @outline_outputs1(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[OUTPUT:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[RESULT:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[OUTPUT2:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[RESULT2:%.*]] = alloca i32, align 4
-; CHECK-NEXT: call void @outlined_ir_func_0(ptr [[A]], ptr [[B]], ptr [[OUTPUT]], ptr [[RESULT]])
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: @outline_outputs2(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[OUTPUT:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[RESULT:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[OUTPUT2:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[RESULT2:%.*]] = alloca i32, align 4
-; CHECK-NEXT: call void @outlined_ir_func_0(ptr [[A]], ptr [[B]], ptr [[OUTPUT]], ptr [[RESULT]])
-; CHECK-NEXT: ret void
-;
-;
-; CHECK: define internal void @outlined_ir_func_0(
-; CHECK: newFuncRoot:
-; CHECK-NEXT: br label [[ENTRY_TO_OUTLINE:%.*]]
-; CHECK: entry_to_outline:
-; CHECK-NEXT: store i32 2, ptr [[TMP0:%.*]], align 4
-; CHECK-NEXT: store i32 3, ptr [[TMP1:%.*]], align 4
-; CHECK-NEXT: br label [[NEXT:%.*]]
-; CHECK: next:
-; CHECK-NEXT: store i32 2, ptr [[TMP2:%.*]], align 4
-; CHECK-NEXT: store i32 3, ptr [[TMP3:%.*]], align 4
-; CHECK-NEXT: br label [[ENTRY_AFTER_OUTLINE_EXITSTUB:%.*]]
-; CHECK: entry_after_outline.exitStub:
-; CHECK-NEXT: ret void
-;
diff --git a/llvm/test/Transforms/IROutliner/outlining-address-taken.ll b/llvm/test/Transforms/IROutliner/outlining-address-taken.ll
deleted file mode 100644
index ce20e6d79b7f3..0000000000000
--- a/llvm/test/Transforms/IROutliner/outlining-address-taken.ll
+++ /dev/null
@@ -1,91 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt -S -passes=verify,iroutliner -ir-outlining-no-cost < %s | FileCheck %s
-
-; This test shows that we do not outline from basic blocks with their address
-; taken.
-
- at ba1 = constant ptr blockaddress (@dontoutline, %new_block)
-
-define void @outline_1() {
-; CHECK-LABEL: @outline_1(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[C:%.*]] = alloca i32, align 4
-; CHECK-NEXT: call void @[[FUNCTION_1:.*]](ptr [[A]], ptr [[B]], ptr [[C]])
-; CHECK-NEXT: ret void
-;
-entry:
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- %c = alloca i32, align 4
- store i32 2, ptr %a, align 4
- store i32 3, ptr %b, align 4
- store i32 4, ptr %c, align 4
- %al = load i32, ptr %a
- %bl = load i32, ptr %b
- %cl = load i32, ptr %c
- ret void
-}
-
-define void @outline_2() {
-; CHECK-LABEL: @outline_2(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[C:%.*]] = alloca i32, align 4
-; CHECK-NEXT: call void @[[FUNCTION_1]](ptr [[A]], ptr [[B]], ptr [[C]])
-; CHECK-NEXT: ret void
-;
-entry:
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- %c = alloca i32, align 4
- store i32 2, ptr %a, align 4
- store i32 3, ptr %b, align 4
- store i32 4, ptr %c, align 4
- %al = load i32, ptr %a
- %bl = load i32, ptr %b
- %cl = load i32, ptr %c
- ret void
-}
-
-define void @dontoutline() {
-; CHECK-LABEL: @dontoutline(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[C:%.*]] = alloca i32, align 4
-; CHECK-NEXT: br label [[NEW_BLOCK:%.*]]
-; CHECK: new_block:
-; CHECK-NEXT: store i32 2, ptr [[A]], align 4
-; CHECK-NEXT: store i32 3, ptr [[B]], align 4
-; CHECK-NEXT: store i32 4, ptr [[C]], align 4
-; CHECK-NEXT: [[AL:%.*]] = load i32, ptr [[A]], align 4
-; CHECK-NEXT: [[BL:%.*]] = load i32, ptr [[B]], align 4
-; CHECK-NEXT: [[CL:%.*]] = load i32, ptr [[C]], align 4
-; CHECK-NEXT: ret void
-;
-entry:
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- %c = alloca i32, align 4
- br label %new_block
-new_block:
- store i32 2, ptr %a, align 4
- store i32 3, ptr %b, align 4
- store i32 4, ptr %c, align 4
- %al = load i32, ptr %a
- %bl = load i32, ptr %b
- %cl = load i32, ptr %c
- ret void
-}
-
-; CHECK: define internal void @[[FUNCTION_1]](ptr [[ARG0:%.*]], ptr [[ARG1:%.*]], ptr [[ARG2:%.*]])
-; CHECK: entry_to_outline:
-; CHECK-NEXT: store i32 2, ptr [[ARG0]], align 4
-; CHECK-NEXT: store i32 3, ptr [[ARG1]], align 4
-; CHECK-NEXT: store i32 4, ptr [[ARG2]], align 4
-; CHECK-NEXT: [[AL:%.*]] = load i32, ptr [[ARG0]], align 4
-; CHECK-NEXT: [[BL:%.*]] = load i32, ptr [[ARG1]], align 4
-; CHECK-NEXT: [[CL:%.*]] = load i32, ptr [[ARG2]], align 4
diff --git a/llvm/test/Transforms/IROutliner/outlining-basic-branches.ll b/llvm/test/Transforms/IROutliner/outlining-basic-branches.ll
deleted file mode 100644
index 765c0b51c02ee..0000000000000
--- a/llvm/test/Transforms/IROutliner/outlining-basic-branches.ll
+++ /dev/null
@@ -1,50 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --include-generated-funcs
-; RUN: opt -S -passes=verify,iroutliner -ir-outlining-no-cost < %s | FileCheck %s
-
-; This checks that we are able to outline exactly the same structure without
-; any other items to outline.
-
-define void @outline_outputs1() #0 {
-entry:
- br label %next
-next:
- br label %next2
-next2:
- br label %next3
-next3:
- %a = alloca i32, align 4
- br label %next4
-next4:
- br label %next5
-next5:
- br label %next6
-next6:
- %b = alloca i32, align 4
- ret void
-}
-
-; CHECK-LABEL: @outline_outputs1(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: call void @outlined_ir_func_0()
-; CHECK-NEXT: br label [[NEXT3:%.*]]
-; CHECK: next3:
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: call void @outlined_ir_func_0()
-; CHECK-NEXT: br label [[NEXT6:%.*]]
-; CHECK: next6:
-; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
-; CHECK-NEXT: ret void
-;
-;
-; CHECK: define internal void @outlined_ir_func_0(
-; CHECK-NEXT: newFuncRoot:
-; CHECK-NEXT: br label [[ENTRY_TO_OUTLINE:%.*]]
-; CHECK: entry_to_outline:
-; CHECK-NEXT: br label [[NEXT:%.*]]
-; CHECK: next:
-; CHECK-NEXT: br label [[NEXT2:%.*]]
-; CHECK: next2:
-; CHECK-NEXT: br label [[NEXT3_EXITSTUB:%.*]]
-; CHECK: next3.exitStub:
-; CHECK-NEXT: ret void
-;
diff --git a/llvm/test/Transforms/IROutliner/outlining-bitcasts.ll b/llvm/test/Transforms/IROutliner/outlining-bitcasts.ll
deleted file mode 100644
index a8153a4fda446..0000000000000
--- a/llvm/test/Transforms/IROutliner/outlining-bitcasts.ll
+++ /dev/null
@@ -1,127 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --include-generated-funcs
-; RUN: opt -S -passes=verify,iroutliner -ir-outlining-no-cost < %s | FileCheck %s
-
-; This test ensures that an extra output is not added when there is a bitcast
-; that is relocated to outside of the extraction due to a starting lifetime
-; instruction outside of the extracted region.
-
-; Additionally, we check that the newly added bitcast instruction is excluded in
-; further extractions.
-
-declare void @llvm.lifetime.start.p0(ptr nocapture)
-declare void @llvm.lifetime.end.p0(ptr nocapture)
-
-define void @outline_bitcast_base() {
-entry:
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- %c = alloca i32, align 4
- %d = alloca i32, align 4
- store i32 2, ptr %a, align 4
- store i32 3, ptr %b, align 4
- store i32 4, ptr %c, align 4
- %al = load i32, ptr %a
- %bl = load i32, ptr %b
- %cl = load i32, ptr %c
- ret void
-}
-
-define void @outline_bitcast_removed() {
-entry:
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- %c = alloca i32, align 4
- %d = alloca i32, align 4
- store i32 2, ptr %a, align 4
- store i32 3, ptr %b, align 4
- store i32 4, ptr %c, align 4
- %al = load i32, ptr %a
- %bl = load i32, ptr %b
- %cl = load i32, ptr %c
- call void @llvm.lifetime.start.p0(ptr %d)
- %am = load i32, ptr %b
- %bm = load i32, ptr %a
- %cm = load i32, ptr %c
- call void @llvm.lifetime.end.p0(ptr %d)
- ret void
-}
-
-; The first bitcast is moved down to lifetime start, and, since the original
-; endpoint does not match the new endpoint, we cannot extract and outline the
-; second bitcast and set of adds. Outlining only occurs in this case due to
-; the lack of a cost model, as denoted by the debug command line argument.
-
-define void @outline_bitcast_base2(i32 %a, i32 %b, i32 %c) {
-entry:
- %d = alloca i32, align 4
- %al = add i32 %a, %b
- %bl = add i32 %b, %a
- %cl = add i32 %b, %c
- %buffer = mul i32 %a, %b
- %am = add i32 %a, %b
- %bm = add i32 %b, %a
- %cm = add i32 %b, %c
- call void @llvm.lifetime.start.p0(ptr %d)
- call void @llvm.lifetime.end.p0(ptr %d)
- ret void
-}
-
-; CHECK-LABEL: @outline_bitcast_base(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[C:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[D:%.*]] = alloca i32, align 4
-; CHECK-NEXT: call void @outlined_ir_func_0(ptr [[A]], ptr [[B]], ptr [[C]])
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: @outline_bitcast_removed(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[C:%.*]] = alloca i32, align 4
-; CHECK-NEXT: call void @outlined_ir_func_0(ptr [[A]], ptr [[B]], ptr [[C]])
-; CHECK-NEXT: [[AM:%.*]] = load i32, ptr [[B]], align 4
-; CHECK-NEXT: [[BM:%.*]] = load i32, ptr [[A]], align 4
-; CHECK-NEXT: [[CM:%.*]] = load i32, ptr [[C]], align 4
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: @outline_bitcast_base2(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: call void @outlined_ir_func_1(i32 [[A:%.*]], i32 [[B:%.*]], i32 [[C:%.*]])
-; CHECK-NEXT: [[BUFFER:%.*]] = mul i32 [[A]], [[B]]
-; CHECK-NEXT: call void @outlined_ir_func_1(i32 [[A]], i32 [[B]], i32 [[C]])
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: @outlined_ir_func_0(
-; CHECK-NEXT: newFuncRoot:
-; CHECK-NEXT: br label [[ENTRY_TO_OUTLINE:%.*]]
-; CHECK: entry_to_outline:
-; CHECK-NEXT: store i32 2, ptr [[TMP0:%.*]], align 4
-; CHECK-NEXT: store i32 3, ptr [[TMP1:%.*]], align 4
-; CHECK-NEXT: store i32 4, ptr [[TMP2:%.*]], align 4
-; CHECK-NEXT: [[AL:%.*]] = load i32, ptr [[TMP0]], align 4
-; CHECK-NEXT: [[BL:%.*]] = load i32, ptr [[TMP1]], align 4
-; CHECK-NEXT: [[CL:%.*]] = load i32, ptr [[TMP2]], align 4
-; CHECK-NEXT: br label [[ENTRY_AFTER_OUTLINE_EXITSTUB:%.*]]
-; CHECK: entry_after_outline.exitStub:
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: @outlined_ir_func_1(
-; CHECK-NEXT: newFuncRoot:
-; CHECK-NEXT: [[D:%.*]] = alloca i32, align 4
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[D]])
-; CHECK-NEXT: br label [[ENTRY_TO_OUTLINE:%.*]]
-; CHECK: entry_to_outline:
-; CHECK-NEXT: [[AL:%.*]] = add i32 [[TMP0:%.*]], [[TMP1:%.*]]
-; CHECK-NEXT: [[BL:%.*]] = add i32 [[TMP1]], [[TMP0]]
-; CHECK-NEXT: [[CL:%.*]] = add i32 [[TMP1]], [[TMP2:%.*]]
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[D]])
-; CHECK-NEXT: br label [[ENTRY_AFTER_OUTLINE_EXITSTUB:%.*]]
-; CHECK: entry_after_outline.exitStub:
-; CHECK-NEXT: ret void
-;
diff --git a/llvm/test/Transforms/IROutliner/outlining-branches-phi-nodes.ll b/llvm/test/Transforms/IROutliner/outlining-branches-phi-nodes.ll
deleted file mode 100644
index bb6bf8f2e1454..0000000000000
--- a/llvm/test/Transforms/IROutliner/outlining-branches-phi-nodes.ll
+++ /dev/null
@@ -1,171 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --include-generated-funcs
-; RUN: opt -S -passes=verify,iroutliner -ir-outlining-no-cost < %s | FileCheck %s
-
-; Here we have multiple exits, but the different sources, same outputs are
-; needed, this checks that they are compressed, and moved into the appropriate
-; output blocks.
-
-define void @outline_outputs1() #0 {
-entry:
- %output = alloca i32, align 4
- %result = alloca i32, align 4
- %output2 = alloca i32, align 4
- %result2 = alloca i32, align 4
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- br label %block_2
-block_1:
- %a2 = alloca i32, align 4
- %b2 = alloca i32, align 4
- br label %block_2
-block_2:
- %a2val = load i32, ptr %a
- %b2val = load i32, ptr %b
- %add2 = add i32 2, %a2val
- %mul2 = mul i32 2, %b2val
- br label %block_5
-block_3:
- %aval = load i32, ptr %a
- %bval = load i32, ptr %b
- %add = add i32 2, %aval
- %mul = mul i32 2, %bval
- br label %block_4
-block_4:
- store i32 %add, ptr %output, align 4
- store i32 %mul, ptr %result, align 4
- br label %block_6
-block_5:
- store i32 %add2, ptr %output, align 4
- store i32 %mul2, ptr %result, align 4
- br label %block_6
-dummy:
- ret void
-block_6:
- %diff = phi i32 [%aval, %block_4], [%a2val, %block_5]
- ret void
-}
-
-define void @outline_outputs2() #0 {
-entry:
- %output = alloca i32, align 4
- %result = alloca i32, align 4
- %output2 = alloca i32, align 4
- %result2 = alloca i32, align 4
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- br label %block_2
-block_1:
- %a2 = alloca i32, align 4
- %b2 = alloca i32, align 4
- br label %block_2
-block_2:
- %a2val = load i32, ptr %a
- %b2val = load i32, ptr %b
- %add2 = add i32 2, %a2val
- %mul2 = mul i32 2, %b2val
- br label %block_5
-block_3:
- %aval = load i32, ptr %a
- %bval = load i32, ptr %b
- %add = add i32 2, %aval
- %mul = mul i32 2, %bval
- br label %block_4
-block_4:
- store i32 %add, ptr %output, align 4
- store i32 %mul, ptr %result, align 4
- br label %block_6
-block_5:
- store i32 %add2, ptr %output, align 4
- store i32 %mul2, ptr %result, align 4
- br label %block_6
-dummy:
- ret void
-block_6:
- %diff = phi i32 [%aval, %block_4], [%a2val, %block_5]
- ret void
-}
-
-; CHECK-LABEL: @outline_outputs1(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[DIFF_CE_LOC:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[OUTPUT:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[RESULT:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[OUTPUT2:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[RESULT2:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
-; CHECK-NEXT: br label [[BLOCK_2:%.*]]
-; CHECK: block_1:
-; CHECK-NEXT: [[A2:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B2:%.*]] = alloca i32, align 4
-; CHECK-NEXT: br label [[BLOCK_2]]
-; CHECK: block_2:
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[DIFF_CE_LOC]])
-; CHECK-NEXT: call void @outlined_ir_func_0(ptr [[A]], ptr [[B]], ptr [[OUTPUT]], ptr [[RESULT]], ptr [[DIFF_CE_LOC]])
-; CHECK-NEXT: [[DIFF_CE_RELOAD:%.*]] = load i32, ptr [[DIFF_CE_LOC]], align 4
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[DIFF_CE_LOC]])
-; CHECK-NEXT: br label [[BLOCK_6:%.*]]
-; CHECK: dummy:
-; CHECK-NEXT: ret void
-; CHECK: block_6:
-; CHECK-NEXT: [[DIFF:%.*]] = phi i32 [ [[DIFF_CE_RELOAD]], [[BLOCK_2]] ]
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: @outline_outputs2(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[DIFF_CE_LOC:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[OUTPUT:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[RESULT:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[OUTPUT2:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[RESULT2:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
-; CHECK-NEXT: br label [[BLOCK_2:%.*]]
-; CHECK: block_1:
-; CHECK-NEXT: [[A2:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B2:%.*]] = alloca i32, align 4
-; CHECK-NEXT: br label [[BLOCK_2]]
-; CHECK: block_2:
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[DIFF_CE_LOC]])
-; CHECK-NEXT: call void @outlined_ir_func_0(ptr [[A]], ptr [[B]], ptr [[OUTPUT]], ptr [[RESULT]], ptr [[DIFF_CE_LOC]])
-; CHECK-NEXT: [[DIFF_CE_RELOAD:%.*]] = load i32, ptr [[DIFF_CE_LOC]], align 4
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[DIFF_CE_LOC]])
-; CHECK-NEXT: br label [[BLOCK_6:%.*]]
-; CHECK: dummy:
-; CHECK-NEXT: ret void
-; CHECK: block_6:
-; CHECK-NEXT: [[DIFF:%.*]] = phi i32 [ [[DIFF_CE_RELOAD]], [[BLOCK_2]] ]
-; CHECK-NEXT: ret void
-;
-;
-; CHECK: define internal void @outlined_ir_func_0(
-; CHECK-NEXT: newFuncRoot:
-; CHECK-NEXT: br label [[BLOCK_2_TO_OUTLINE:%.*]]
-; CHECK: block_2_to_outline:
-; CHECK-NEXT: [[A2VAL:%.*]] = load i32, ptr [[TMP0:%.*]], align 4
-; CHECK-NEXT: [[B2VAL:%.*]] = load i32, ptr [[TMP1:%.*]], align 4
-; CHECK-NEXT: [[ADD2:%.*]] = add i32 2, [[A2VAL]]
-; CHECK-NEXT: [[MUL2:%.*]] = mul i32 2, [[B2VAL]]
-; CHECK-NEXT: br label [[BLOCK_5:%.*]]
-; CHECK: block_3:
-; CHECK-NEXT: [[AVAL:%.*]] = load i32, ptr [[TMP0]], align 4
-; CHECK-NEXT: [[BVAL:%.*]] = load i32, ptr [[TMP1]], align 4
-; CHECK-NEXT: [[ADD:%.*]] = add i32 2, [[AVAL]]
-; CHECK-NEXT: [[MUL:%.*]] = mul i32 2, [[BVAL]]
-; CHECK-NEXT: br label [[BLOCK_4:%.*]]
-; CHECK: block_4:
-; CHECK-NEXT: store i32 [[ADD]], ptr [[TMP2:%.*]], align 4
-; CHECK-NEXT: store i32 [[MUL]], ptr [[TMP3:%.*]], align 4
-; CHECK-NEXT: br label [[BLOCK_6_SPLIT:%.*]]
-; CHECK: block_5:
-; CHECK-NEXT: store i32 [[ADD2]], ptr [[TMP2]], align 4
-; CHECK-NEXT: store i32 [[MUL2]], ptr [[TMP3]], align 4
-; CHECK-NEXT: br label [[BLOCK_6_SPLIT]]
-; CHECK: block_6.split:
-; CHECK-NEXT: [[DIFF_CE:%.*]] = phi i32 [ [[AVAL]], [[BLOCK_4]] ], [ [[A2VAL]], [[BLOCK_5]] ]
-; CHECK-NEXT: br label [[BLOCK_6_EXITSTUB:%.*]]
-; CHECK: block_6.exitStub:
-; CHECK-NEXT: store i32 [[DIFF_CE]], ptr [[TMP4:%.*]], align 4
-; CHECK-NEXT: ret void
-;
diff --git a/llvm/test/Transforms/IROutliner/outlining-call-and-indirect.ll b/llvm/test/Transforms/IROutliner/outlining-call-and-indirect.ll
deleted file mode 100644
index 2ba79cc9e6f90..0000000000000
--- a/llvm/test/Transforms/IROutliner/outlining-call-and-indirect.ll
+++ /dev/null
@@ -1,70 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --include-generated-funcs
-; RUN: opt -S -passes=verify,iroutliner -ir-outlining-no-cost < %s | FileCheck %s
-
-; This test checks that we do can outline indirect and regular function calls
-; when the type matches when it is not specified that the names must match.
-
-declare void @f1();
-
-define void @function1(ptr %func) {
-entry:
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- %c = alloca i32, align 4
- store i32 2, ptr %a, align 4
- store i32 3, ptr %b, align 4
- store i32 4, ptr %c, align 4
- call void %func()
- %al = load i32, ptr %a
- %bl = load i32, ptr %b
- %cl = load i32, ptr %c
- ret void
-}
-
-define void @function2() {
-entry:
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- %c = alloca i32, align 4
- store i32 2, ptr %a, align 4
- store i32 3, ptr %b, align 4
- store i32 4, ptr %c, align 4
- call void @f1()
- %al = load i32, ptr %a
- %bl = load i32, ptr %b
- %cl = load i32, ptr %c
- ret void
-}
-; CHECK-LABEL: @function1(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[C:%.*]] = alloca i32, align 4
-; CHECK-NEXT: call void @outlined_ir_func_0(ptr [[A]], ptr [[B]], ptr [[C]], ptr [[FUNC:%.*]])
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: @function2(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[C:%.*]] = alloca i32, align 4
-; CHECK-NEXT: call void @outlined_ir_func_0(ptr [[A]], ptr [[B]], ptr [[C]], ptr @f1)
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: define internal void @outlined_ir_func_0(
-; CHECK-NEXT: newFuncRoot:
-; CHECK-NEXT: br label [[ENTRY_TO_OUTLINE:%.*]]
-; CHECK: entry_to_outline:
-; CHECK-NEXT: store i32 2, ptr [[TMP0:%.*]], align 4
-; CHECK-NEXT: store i32 3, ptr [[TMP1:%.*]], align 4
-; CHECK-NEXT: store i32 4, ptr [[TMP2:%.*]], align 4
-; CHECK-NEXT: call void [[TMP3:%.*]]()
-; CHECK-NEXT: [[AL:%.*]] = load i32, ptr [[TMP0]], align 4
-; CHECK-NEXT: [[BL:%.*]] = load i32, ptr [[TMP1]], align 4
-; CHECK-NEXT: [[CL:%.*]] = load i32, ptr [[TMP2]], align 4
-; CHECK-NEXT: br label [[ENTRY_AFTER_OUTLINE_EXITSTUB:%.*]]
-; CHECK: entry_after_outline.exitStub:
-; CHECK-NEXT: ret void
-;
diff --git a/llvm/test/Transforms/IROutliner/outlining-calls-names-must-match.ll b/llvm/test/Transforms/IROutliner/outlining-calls-names-must-match.ll
deleted file mode 100644
index befc4896f7503..0000000000000
--- a/llvm/test/Transforms/IROutliner/outlining-calls-names-must-match.ll
+++ /dev/null
@@ -1,93 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt -S -passes=verify,iroutliner -ir-outlining-no-cost -ir-sim-calls-by-name < %s | FileCheck %s
-
-; This test checks that we do can outline calls, but only if they have the same
-; function type and the same name.
-
-declare void @f1(ptr, ptr);
-declare void @f2(ptr, ptr);
-
-define void @function1() {
-; CHECK-LABEL: @function1(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[C:%.*]] = alloca i32, align 4
-; CHECK-NEXT: call void @outlined_ir_func_0(ptr [[A]], ptr [[B]], ptr [[C]])
-; CHECK-NEXT: ret void
-;
-entry:
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- %c = alloca i32, align 4
- store i32 2, ptr %a, align 4
- store i32 3, ptr %b, align 4
- store i32 4, ptr %c, align 4
- call void @f1(ptr %a, ptr %b)
- %al = load i32, ptr %a
- %bl = load i32, ptr %b
- %cl = load i32, ptr %c
- ret void
-}
-
-define void @function2() {
-; CHECK-LABEL: @function2(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[C:%.*]] = alloca i32, align 4
-; CHECK-NEXT: call void @outlined_ir_func_0(ptr [[A]], ptr [[B]], ptr [[C]])
-; CHECK-NEXT: ret void
-;
-entry:
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- %c = alloca i32, align 4
- store i32 2, ptr %a, align 4
- store i32 3, ptr %b, align 4
- store i32 4, ptr %c, align 4
- call void @f1(ptr %a, ptr %b)
- %al = load i32, ptr %a
- %bl = load i32, ptr %b
- %cl = load i32, ptr %c
- ret void
-}
-
-define void @function3() {
-; CHECK-LABEL: @function3(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[C:%.*]] = alloca i32, align 4
-; CHECK-NEXT: store i32 2, ptr [[A]], align 4
-; CHECK-NEXT: store i32 3, ptr [[B]], align 4
-; CHECK-NEXT: store i32 4, ptr [[C]], align 4
-; CHECK-NEXT: call void @f2(ptr [[A]], ptr [[B]])
-; CHECK-NEXT: [[AL:%.*]] = load i32, ptr [[A]], align 4
-; CHECK-NEXT: [[BL:%.*]] = load i32, ptr [[B]], align 4
-; CHECK-NEXT: [[CL:%.*]] = load i32, ptr [[C]], align 4
-; CHECK-NEXT: ret void
-;
-entry:
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- %c = alloca i32, align 4
- store i32 2, ptr %a, align 4
- store i32 3, ptr %b, align 4
- store i32 4, ptr %c, align 4
- call void @f2(ptr %a, ptr %b)
- %al = load i32, ptr %a
- %bl = load i32, ptr %b
- %cl = load i32, ptr %c
- ret void
-}
-
-; CHECK: define internal void @outlined_ir_func_0(ptr [[ARG0:%.*]], ptr [[ARG1:%.*]], ptr [[ARG2:%.*]])
-; CHECK: entry_to_outline:
-; CHECK-NEXT: store i32 2, ptr [[ARG0]], align 4
-; CHECK-NEXT: store i32 3, ptr [[ARG1]], align 4
-; CHECK-NEXT: store i32 4, ptr [[ARG2]], align 4
-; CHECK-NEXT: call void @f1(ptr [[ARG0]], ptr [[ARG1]])
-; CHECK-NEXT: [[AL:%.*]] = load i32, ptr [[ARG0]], align 4
-; CHECK-NEXT: [[BL:%.*]] = load i32, ptr [[ARG1]], align 4
-; CHECK-NEXT: [[CL:%.*]] = load i32, ptr [[ARG2]], align 4
diff --git a/llvm/test/Transforms/IROutliner/outlining-calls.ll b/llvm/test/Transforms/IROutliner/outlining-calls.ll
deleted file mode 100644
index 8d4092727577a..0000000000000
--- a/llvm/test/Transforms/IROutliner/outlining-calls.ll
+++ /dev/null
@@ -1,96 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --include-generated-funcs
-; RUN: opt -S -passes=verify,iroutliner -ir-outlining-no-cost < %s | FileCheck %s
-
-; This test checks that we do can outline calls, but only if they have the same
-; function type and the same name.
-
-declare void @f1(ptr, ptr);
-declare void @f2(ptr, ptr);
-
-define void @function1() {
-entry:
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- %c = alloca i32, align 4
- store i32 2, ptr %a, align 4
- store i32 3, ptr %b, align 4
- store i32 4, ptr %c, align 4
- call void @f1(ptr %a, ptr %b)
- %al = load i32, ptr %a
- %bl = load i32, ptr %b
- %cl = load i32, ptr %c
- ret void
-}
-
-define void @function2() {
-entry:
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- %c = alloca i32, align 4
- store i32 2, ptr %a, align 4
- store i32 3, ptr %b, align 4
- store i32 4, ptr %c, align 4
- call void @f1(ptr %a, ptr %b)
- %al = load i32, ptr %a
- %bl = load i32, ptr %b
- %cl = load i32, ptr %c
- ret void
-}
-
-define void @function3() {
-entry:
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- %c = alloca i32, align 4
- store i32 2, ptr %a, align 4
- store i32 3, ptr %b, align 4
- store i32 4, ptr %c, align 4
- call void @f2(ptr %a, ptr %b)
- %al = load i32, ptr %a
- %bl = load i32, ptr %b
- %cl = load i32, ptr %c
- ret void
-}
-
-; CHECK-LABEL: @function1(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[C:%.*]] = alloca i32, align 4
-; CHECK-NEXT: call void @outlined_ir_func_0(ptr [[A]], ptr [[B]], ptr [[C]], ptr @f1)
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: @function2(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[C:%.*]] = alloca i32, align 4
-; CHECK-NEXT: call void @outlined_ir_func_0(ptr [[A]], ptr [[B]], ptr [[C]], ptr @f1)
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: @function3(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[C:%.*]] = alloca i32, align 4
-; CHECK-NEXT: call void @outlined_ir_func_0(ptr [[A]], ptr [[B]], ptr [[C]], ptr @f2)
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: define internal void @outlined_ir_func_0(
-; CHECK-NEXT: newFuncRoot:
-; CHECK-NEXT: br label [[ENTRY_TO_OUTLINE:%.*]]
-; CHECK: entry_to_outline:
-; CHECK-NEXT: store i32 2, ptr [[TMP0:%.*]], align 4
-; CHECK-NEXT: store i32 3, ptr [[TMP1:%.*]], align 4
-; CHECK-NEXT: store i32 4, ptr [[TMP2:%.*]], align 4
-; CHECK-NEXT: call void [[TMP3:%.*]](ptr [[TMP0]], ptr [[TMP1]])
-; CHECK-NEXT: [[AL:%.*]] = load i32, ptr [[TMP0]], align 4
-; CHECK-NEXT: [[BL:%.*]] = load i32, ptr [[TMP1]], align 4
-; CHECK-NEXT: [[CL:%.*]] = load i32, ptr [[TMP2]], align 4
-; CHECK-NEXT: br label [[ENTRY_AFTER_OUTLINE_EXITSTUB:%.*]]
-; CHECK: entry_after_outline.exitStub:
-; CHECK-NEXT: ret void
-;
diff --git a/llvm/test/Transforms/IROutliner/outlining-commutative-fp.ll b/llvm/test/Transforms/IROutliner/outlining-commutative-fp.ll
deleted file mode 100644
index 6b958b674bcb2..0000000000000
--- a/llvm/test/Transforms/IROutliner/outlining-commutative-fp.ll
+++ /dev/null
@@ -1,107 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt -S -passes=verify,iroutliner -ir-outlining-no-cost < %s | FileCheck %s
-
-; This test checks that floating point commutative instructions are not treated
-; as commutative. Even though an ffadd is technically commutative, the order
-; of operands still needs to be enforced since the process of fadding floating
-; point values requires the order to be the same.
-
-; We make sure that we outline the identical regions from the first two
-; functions, but not the third. this is because the operands are in a different
-; order in a floating point instruction in this section.
-
-define void @outline_from_fadd1() {
-; CHECK-LABEL: @outline_from_fadd1(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[A:%.*]] = alloca double, align 4
-; CHECK-NEXT: [[B:%.*]] = alloca double, align 4
-; CHECK-NEXT: [[C:%.*]] = alloca double, align 4
-; CHECK-NEXT: call void @outlined_ir_func_0(ptr [[A]], ptr [[B]], ptr [[C]])
-; CHECK-NEXT: ret void
-;
-entry:
- %a = alloca double, align 4
- %b = alloca double, align 4
- %c = alloca double, align 4
- store double 2.0, ptr %a, align 4
- store double 3.0, ptr %b, align 4
- store double 4.0, ptr %c, align 4
- %al = load double, ptr %a
- %bl = load double, ptr %b
- %cl = load double, ptr %c
- %0 = fadd double %al, %bl
- %1 = fadd double %al, %cl
- %2 = fadd double %bl, %cl
- ret void
-}
-
-define void @outline_from_fadd2.0() {
-; CHECK-LABEL: @outline_from_fadd2.0(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[A:%.*]] = alloca double, align 4
-; CHECK-NEXT: [[B:%.*]] = alloca double, align 4
-; CHECK-NEXT: [[C:%.*]] = alloca double, align 4
-; CHECK-NEXT: call void @outlined_ir_func_0(ptr [[A]], ptr [[B]], ptr [[C]])
-; CHECK-NEXT: ret void
-;
-entry:
- %a = alloca double, align 4
- %b = alloca double, align 4
- %c = alloca double, align 4
- store double 2.0, ptr %a, align 4
- store double 3.0, ptr %b, align 4
- store double 4.0, ptr %c, align 4
- %al = load double, ptr %a
- %bl = load double, ptr %b
- %cl = load double, ptr %c
- %0 = fadd double %al, %bl
- %1 = fadd double %al, %cl
- %2 = fadd double %bl, %cl
- ret void
-}
-
-define void @outline_from_flipped_fadd3.0() {
-; CHECK-LABEL: @outline_from_flipped_fadd3.0(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[A:%.*]] = alloca double, align 4
-; CHECK-NEXT: [[B:%.*]] = alloca double, align 4
-; CHECK-NEXT: [[C:%.*]] = alloca double, align 4
-; CHECK-NEXT: store double 2.000000e+00, ptr [[A]], align 4
-; CHECK-NEXT: store double 3.000000e+00, ptr [[B]], align 4
-; CHECK-NEXT: store double 4.000000e+00, ptr [[C]], align 4
-; CHECK-NEXT: [[AL:%.*]] = load double, ptr [[A]], align 8
-; CHECK-NEXT: [[BL:%.*]] = load double, ptr [[B]], align 8
-; CHECK-NEXT: [[CL:%.*]] = load double, ptr [[C]], align 8
-; CHECK-NEXT: [[TMP0:%.*]] = fadd double [[BL]], [[AL]]
-; CHECK-NEXT: [[TMP1:%.*]] = fadd double [[CL]], [[AL]]
-; CHECK-NEXT: [[TMP2:%.*]] = fadd double [[CL]], [[BL]]
-; CHECK-NEXT: ret void
-;
-entry:
- %a = alloca double, align 4
- %b = alloca double, align 4
- %c = alloca double, align 4
- store double 2.0, ptr %a, align 4
- store double 3.0, ptr %b, align 4
- store double 4.0, ptr %c, align 4
- %al = load double, ptr %a
- %bl = load double, ptr %b
- %cl = load double, ptr %c
- %0 = fadd double %bl, %al
- %1 = fadd double %cl, %al
- %2 = fadd double %cl, %bl
- ret void
-}
-
-; CHECK: define internal void @outlined_ir_func_0(ptr [[ARG0:%.*]], ptr [[ARG1:%.*]], ptr [[ARG2:%.*]]) #0 {
-; CHECK: entry_to_outline:
-; CHECK-NEXT: store double 2.000000e+00, ptr [[ARG0]], align 4
-; CHECK-NEXT: store double 3.000000e+00, ptr [[ARG1]], align 4
-; CHECK-NEXT: store double 4.000000e+00, ptr [[ARG2]], align 4
-; CHECK-NEXT: [[AL:%.*]] = load double, ptr [[ARG0]], align 8
-; CHECK-NEXT: [[BL:%.*]] = load double, ptr [[ARG1]], align 8
-; CHECK-NEXT: [[CL:%.*]] = load double, ptr [[ARG2]], align 8
-; CHECK-NEXT: [[TMP0:%.*]] = fadd double [[AL]], [[BL]]
-; CHECK-NEXT: [[TMP1:%.*]] = fadd double [[AL]], [[CL]]
-; CHECK-NEXT: [[TMP2:%.*]] = fadd double [[BL]], [[CL]]
-
diff --git a/llvm/test/Transforms/IROutliner/outlining-commutative-operands-opposite-order.ll b/llvm/test/Transforms/IROutliner/outlining-commutative-operands-opposite-order.ll
deleted file mode 100644
index 6eaa0ad8ef0f2..0000000000000
--- a/llvm/test/Transforms/IROutliner/outlining-commutative-operands-opposite-order.ll
+++ /dev/null
@@ -1,40 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals --include-generated-funcs
-; RUN: opt -S -passes=iroutliner -ir-outlining-no-cost < %s | FileCheck %s
-
-; This is a test to ensure that when the first instruction is a commutative
-; instruction, but the order of operands is reversed, we pass the arguments
-; in the correct order, such that we do not use the wrong arguments
-; later on in the computation.
-
-define void @fish(i32 %0, i32 %1, i32 %2) {
-entry:
- %3 = add nsw i32 %0, %1
- %4 = sub nsw i32 %1, %2
- %5 = sub nsw i32 %0, %2
- ret void
-}
-
-define void @turtle(i32 %0, i32 %1, i32 %2) {
- %4 = add nsw i32 %1, %0
- %5 = sub nsw i32 %1, %2
- %6 = sub nsw i32 %0, %2
- ret void
-}
-; CHECK-LABEL: @fish(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: call void @outlined_ir_func_0(i32 [[TMP0:%.*]], i32 [[TMP1:%.*]], i32 [[TMP2:%.*]])
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: @turtle(
-; CHECK-NEXT: call void @outlined_ir_func_0(i32 [[TMP0:%.*]], i32 [[TMP1:%.*]], i32 [[TMP2:%.*]])
-; CHECK-NEXT: ret void
-;
-;
-; CHECK: @outlined_ir_func_0(i32 [[TMP0:%.*]], i32 [[TMP1:%.*]], i32 [[TMP2:%.*]])
-; CHECK: entry_to_outline:
-; CHECK-NEXT: [[TMP3:%.*]] = add nsw i32 [[TMP0]], [[TMP1]]
-; CHECK-NEXT: [[TMP4:%.*]] = sub nsw i32 [[TMP1]], [[TMP2]]
-; CHECK-NEXT: [[TMP5:%.*]] = sub nsw i32 [[TMP0]], [[TMP2]]
-; CHECK-NEXT: br label [[ENTRY_AFTER_OUTLINE_EXITSTUB:%.*]]
-;
diff --git a/llvm/test/Transforms/IROutliner/outlining-commutative.ll b/llvm/test/Transforms/IROutliner/outlining-commutative.ll
deleted file mode 100644
index 8862dc295d435..0000000000000
--- a/llvm/test/Transforms/IROutliner/outlining-commutative.ll
+++ /dev/null
@@ -1,254 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt -S -passes=verify,iroutliner -ir-outlining-no-cost < %s | FileCheck %s
-
-; This test checks that commutative instructions where the operands are
-; swapped are outlined as the same function.
-
-; It also checks that non-commutative instructions outlined as different
-; functions when the operands are swapped;
-
-; These are identical functions, except that in the flipped functions,
-; the operands in the adds are commuted. However, since add instructions
-; are commutative, we should still outline from all four as the same
-; instruction.
-
-define void @outline_from_add1() {
-; CHECK-LABEL: @outline_from_add1(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[C:%.*]] = alloca i32, align 4
-; CHECK-NEXT: call void @outlined_ir_func_0(ptr [[A]], ptr [[B]], ptr [[C]])
-; CHECK-NEXT: ret void
-;
-entry:
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- %c = alloca i32, align 4
- store i32 2, ptr %a, align 4
- store i32 3, ptr %b, align 4
- store i32 4, ptr %c, align 4
- %al = load i32, ptr %a
- %bl = load i32, ptr %b
- %cl = load i32, ptr %c
- %0 = add i32 %al, %bl
- %1 = add i32 %al, %cl
- %2 = add i32 %bl, %cl
- ret void
-}
-
-define void @outline_from_add2() {
-; CHECK-LABEL: @outline_from_add2(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[C:%.*]] = alloca i32, align 4
-; CHECK-NEXT: call void @outlined_ir_func_0(ptr [[A]], ptr [[B]], ptr [[C]])
-; CHECK-NEXT: ret void
-;
-entry:
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- %c = alloca i32, align 4
- store i32 2, ptr %a, align 4
- store i32 3, ptr %b, align 4
- store i32 4, ptr %c, align 4
- %al = load i32, ptr %a
- %bl = load i32, ptr %b
- %cl = load i32, ptr %c
- %0 = add i32 %al, %bl
- %1 = add i32 %al, %cl
- %2 = add i32 %bl, %cl
- ret void
-}
-
-define void @outline_from_flipped_add3() {
-; CHECK-LABEL: @outline_from_flipped_add3(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[C:%.*]] = alloca i32, align 4
-; CHECK-NEXT: call void @outlined_ir_func_0(ptr [[A]], ptr [[B]], ptr [[C]])
-; CHECK-NEXT: ret void
-;
-entry:
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- %c = alloca i32, align 4
- store i32 2, ptr %a, align 4
- store i32 3, ptr %b, align 4
- store i32 4, ptr %c, align 4
- %al = load i32, ptr %a
- %bl = load i32, ptr %b
- %cl = load i32, ptr %c
- %0 = add i32 %bl, %al
- %1 = add i32 %cl, %al
- %2 = add i32 %cl, %bl
- ret void
-}
-
-define void @outline_from_flipped_add4() {
-; CHECK-LABEL: @outline_from_flipped_add4(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[C:%.*]] = alloca i32, align 4
-; CHECK-NEXT: call void @outlined_ir_func_0(ptr [[A]], ptr [[B]], ptr [[C]])
-; CHECK-NEXT: ret void
-;
-entry:
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- %c = alloca i32, align 4
- store i32 2, ptr %a, align 4
- store i32 3, ptr %b, align 4
- store i32 4, ptr %c, align 4
- %al = load i32, ptr %a
- %bl = load i32, ptr %b
- %cl = load i32, ptr %c
- %0 = add i32 %bl, %al
- %1 = add i32 %cl, %al
- %2 = add i32 %cl, %bl
- ret void
-}
-
-; These are identical functions, except that in the flipped functions,
-; the operands in the subtractions are commuted. Since subtraction
-; instructions are not commutative, we should outline the first two functions
-; differently than the second two functions.
-
-define void @outline_from_sub1() {
-; CHECK-LABEL: @outline_from_sub1(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[C:%.*]] = alloca i32, align 4
-; CHECK-NEXT: call void @outlined_ir_func_2(ptr [[A]], ptr [[B]], ptr [[C]])
-; CHECK-NEXT: ret void
-;
-entry:
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- %c = alloca i32, align 4
- store i32 2, ptr %a, align 4
- store i32 3, ptr %b, align 4
- store i32 4, ptr %c, align 4
- %al = load i32, ptr %a
- %bl = load i32, ptr %b
- %cl = load i32, ptr %c
- %0 = sub i32 %al, %bl
- %1 = sub i32 %al, %cl
- %2 = sub i32 %bl, %cl
- ret void
-}
-
-define void @outline_from_sub2() {
-; CHECK-LABEL: @outline_from_sub2(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[C:%.*]] = alloca i32, align 4
-; CHECK-NEXT: call void @outlined_ir_func_2(ptr [[A]], ptr [[B]], ptr [[C]])
-; CHECK-NEXT: ret void
-;
-entry:
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- %c = alloca i32, align 4
- store i32 2, ptr %a, align 4
- store i32 3, ptr %b, align 4
- store i32 4, ptr %c, align 4
- %al = load i32, ptr %a
- %bl = load i32, ptr %b
- %cl = load i32, ptr %c
- %0 = sub i32 %al, %bl
- %1 = sub i32 %al, %cl
- %2 = sub i32 %bl, %cl
- ret void
-}
-
-define void @dontoutline_from_flipped_sub3() {
-; CHECK-LABEL: @dontoutline_from_flipped_sub3(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[C:%.*]] = alloca i32, align 4
-; CHECK-NEXT: call void @outlined_ir_func_1(ptr [[A]], ptr [[B]], ptr [[C]])
-; CHECK-NEXT: ret void
-;
-entry:
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- %c = alloca i32, align 4
- store i32 2, ptr %a, align 4
- store i32 3, ptr %b, align 4
- store i32 4, ptr %c, align 4
- %al = load i32, ptr %a
- %bl = load i32, ptr %b
- %cl = load i32, ptr %c
- %0 = sub i32 %bl, %al
- %1 = sub i32 %cl, %al
- %2 = sub i32 %cl, %bl
- ret void
-}
-
-define void @dontoutline_from_flipped_sub4() {
-; CHECK-LABEL: @dontoutline_from_flipped_sub4(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[C:%.*]] = alloca i32, align 4
-; CHECK-NEXT: call void @outlined_ir_func_1(ptr [[A]], ptr [[B]], ptr [[C]])
-; CHECK-NEXT: ret void
-;
-entry:
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- %c = alloca i32, align 4
- store i32 2, ptr %a, align 4
- store i32 3, ptr %b, align 4
- store i32 4, ptr %c, align 4
- %al = load i32, ptr %a
- %bl = load i32, ptr %b
- %cl = load i32, ptr %c
- %0 = sub i32 %bl, %al
- %1 = sub i32 %cl, %al
- %2 = sub i32 %cl, %bl
- ret void
-}
-
-; CHECK: define internal void @outlined_ir_func_0(ptr [[ARG0:%.*]], ptr [[ARG1:%.*]], ptr [[ARG2:%.*]]) #0 {
-; CHECK: entry_to_outline:
-; CHECK-NEXT: store i32 2, ptr [[ARG0]], align 4
-; CHECK-NEXT: store i32 3, ptr [[ARG1]], align 4
-; CHECK-NEXT: store i32 4, ptr [[ARG2]], align 4
-; CHECK-NEXT: [[AL:%.*]] = load i32, ptr [[ARG0]], align 4
-; CHECK-NEXT: [[BL:%.*]] = load i32, ptr [[ARG1]], align 4
-; CHECK-NEXT: [[CL:%.*]] = load i32, ptr [[ARG2]], align 4
-; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[AL]], [[BL]]
-; CHECK-NEXT: [[TMP1:%.*]] = add i32 [[AL]], [[CL]]
-; CHECK-NEXT: [[TMP2:%.*]] = add i32 [[BL]], [[CL]]
-
-; CHECK: define internal void @outlined_ir_func_1(ptr [[ARG0:%.*]], ptr [[ARG1:%.*]], ptr [[ARG2:%.*]]) #0 {
-; CHECK: entry_to_outline:
-; CHECK-NEXT: store i32 2, ptr [[ARG0]], align 4
-; CHECK-NEXT: store i32 3, ptr [[ARG1]], align 4
-; CHECK-NEXT: store i32 4, ptr [[ARG2]], align 4
-; CHECK-NEXT: [[AL:%.*]] = load i32, ptr [[ARG0]], align 4
-; CHECK-NEXT: [[BL:%.*]] = load i32, ptr [[ARG1]], align 4
-; CHECK-NEXT: [[CL:%.*]] = load i32, ptr [[ARG2]], align 4
-; CHECK-NEXT: [[TMP0:%.*]] = sub i32 [[BL]], [[AL]]
-; CHECK-NEXT: [[TMP1:%.*]] = sub i32 [[CL]], [[AL]]
-; CHECK-NEXT: [[TMP2:%.*]] = sub i32 [[CL]], [[BL]]
-
-; CHECK: define internal void @outlined_ir_func_2(ptr [[ARG0:%.*]], ptr [[ARG1:%.*]], ptr [[ARG2:%.*]]) #0 {
-; CHECK: entry_to_outline:
-; CHECK-NEXT: store i32 2, ptr [[ARG0]], align 4
-; CHECK-NEXT: store i32 3, ptr [[ARG1]], align 4
-; CHECK-NEXT: store i32 4, ptr [[ARG2]], align 4
-; CHECK-NEXT: [[AL:%.*]] = load i32, ptr [[ARG0]], align 4
-; CHECK-NEXT: [[BL:%.*]] = load i32, ptr [[ARG1]], align 4
-; CHECK-NEXT: [[CL:%.*]] = load i32, ptr [[ARG2]], align 4
-; CHECK-NEXT: [[TMP0:%.*]] = sub i32 [[AL]], [[BL]]
-; CHECK-NEXT: [[TMP1:%.*]] = sub i32 [[AL]], [[CL]]
-; CHECK-NEXT: [[TMP2:%.*]] = sub i32 [[BL]], [[CL]]
diff --git a/llvm/test/Transforms/IROutliner/outlining-compatible-and-attribute-transfer.ll b/llvm/test/Transforms/IROutliner/outlining-compatible-and-attribute-transfer.ll
deleted file mode 100644
index f13c646c25017..0000000000000
--- a/llvm/test/Transforms/IROutliner/outlining-compatible-and-attribute-transfer.ll
+++ /dev/null
@@ -1,125 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt -S -passes=verify,iroutliner -ir-outlining-no-cost < %s | FileCheck %s
-
-; This has two compatible regions based on function attributes. We have
-; attributes that should be transferred only if it is on all of the regions.
-
-; This includes the attributes,
-; no-signed-zeros-fp-math, less-precise-fpmad, and
-; no-infs-fp-math. Only when each instance of similarity has these attributes
-; can we say that the outlined function can have these attributes since that
-; is the more general case for these attributes.
-
-define void @outline_attrs1() #0 {
-; CHECK-LABEL: @outline_attrs1(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[C:%.*]] = alloca i32, align 4
-; CHECK-NEXT: call void @outlined_ir_func_1(ptr [[A]], ptr [[B]], ptr [[C]])
-; CHECK-NEXT: ret void
-;
-entry:
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- %c = alloca i32, align 4
- store i32 2, ptr %a, align 4
- store i32 3, ptr %b, align 4
- store i32 4, ptr %c, align 4
- %al = load i32, ptr %a
- %bl = load i32, ptr %b
- %cl = load i32, ptr %c
- ret void
-}
-
-define void @outline_attrs2() #0 {
-; CHECK-LABEL: @outline_attrs2(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[C:%.*]] = alloca i32, align 4
-; CHECK-NEXT: call void @outlined_ir_func_1(ptr [[A]], ptr [[B]], ptr [[C]])
-; CHECK-NEXT: ret void
-;
-entry:
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- %c = alloca i32, align 4
- store i32 2, ptr %a, align 4
- store i32 3, ptr %b, align 4
- store i32 4, ptr %c, align 4
- %al = load i32, ptr %a
- %bl = load i32, ptr %b
- %cl = load i32, ptr %c
- ret void
-}
-
-define void @outline_attrs3() #0 {
-; CHECK-LABEL: @outline_attrs3(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[A:%.*]] = alloca float, align 4
-; CHECK-NEXT: [[B:%.*]] = alloca float, align 4
-; CHECK-NEXT: [[C:%.*]] = alloca float, align 4
-; CHECK-NEXT: call void @outlined_ir_func_0(ptr [[A]], ptr [[B]], ptr [[C]])
-; CHECK-NEXT: ret void
-;
-entry:
- %a = alloca float, align 4
- %b = alloca float, align 4
- %c = alloca float, align 4
- store float 2.0, ptr %a, align 4
- store float 3.0, ptr %b, align 4
- store float 4.0, ptr %c, align 4
- %al = load float, ptr %a
- %bl = load float, ptr %b
- %cl = load float, ptr %c
- %0 = fmul float %al, %bl
- ret void
-}
-
-define void @outline_attrs4() {
-; CHECK-LABEL: @outline_attrs4(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[A:%.*]] = alloca float, align 4
-; CHECK-NEXT: [[B:%.*]] = alloca float, align 4
-; CHECK-NEXT: [[C:%.*]] = alloca float, align 4
-; CHECK-NEXT: call void @outlined_ir_func_0(ptr [[A]], ptr [[B]], ptr [[C]])
-; CHECK-NEXT: ret void
-;
-entry:
- %a = alloca float, align 4
- %b = alloca float, align 4
- %c = alloca float, align 4
- store float 2.0, ptr %a, align 4
- store float 3.0, ptr %b, align 4
- store float 4.0, ptr %c, align 4
- %al = load float, ptr %a
- %bl = load float, ptr %b
- %cl = load float, ptr %c
- %0 = fmul float %al, %bl
- ret void
-}
-
-attributes #0 = { "no-signed-zeros-fp-math"="true" "less-precise-fpmad"="true" }
-
-; CHECK: define internal void @outlined_ir_func_0(ptr [[ARG0:%.*]], ptr [[ARG1:%.*]], ptr [[ARG2:%.*]]) [[ATTR1:#[0-9]+]] {
-; CHECK: entry_to_outline:
-; CHECK-NEXT: store float 2.000000e+00, ptr [[ARG0]], align 4
-; CHECK-NEXT: store float 3.000000e+00, ptr [[ARG1]], align 4
-; CHECK-NEXT: store float 4.000000e+00, ptr [[ARG2]], align 4
-; CHECK-NEXT: [[AL:%.*]] = load float, ptr [[ARG0]], align 4
-; CHECK-NEXT: [[BL:%.*]] = load float, ptr [[ARG1]], align 4
-; CHECK-NEXT: [[CL:%.*]] = load float, ptr [[ARG2]], align 4
-
-; CHECK: define internal void @outlined_ir_func_1(ptr [[ARG0:%.*]], ptr [[ARG1:%.*]], ptr [[ARG2:%.*]]) [[ATTR:#[0-9]+]] {
-; CHECK: entry_to_outline:
-; CHECK-NEXT: store i32 2, ptr [[ARG0]], align 4
-; CHECK-NEXT: store i32 3, ptr [[ARG1]], align 4
-; CHECK-NEXT: store i32 4, ptr [[ARG2]], align 4
-; CHECK-NEXT: [[AL:%.*]] = load i32, ptr [[ARG0]], align 4
-; CHECK-NEXT: [[BL:%.*]] = load i32, ptr [[ARG1]], align 4
-; CHECK-NEXT: [[CL:%.*]] = load i32, ptr [[ARG2]], align 4
-
-
-; CHECK: attributes [[ATTR1]] = { minsize optsize "less-precise-fpmad"="false" "no-signed-zeros-fp-math"="false" }
-; CHECK: attributes [[ATTR]] = { minsize optsize "less-precise-fpmad"="true" "no-signed-zeros-fp-math"="true" }
diff --git a/llvm/test/Transforms/IROutliner/outlining-compatible-and-never-transfer-riscv.ll b/llvm/test/Transforms/IROutliner/outlining-compatible-and-never-transfer-riscv.ll
deleted file mode 100644
index d2751e12f355e..0000000000000
--- a/llvm/test/Transforms/IROutliner/outlining-compatible-and-never-transfer-riscv.ll
+++ /dev/null
@@ -1,298 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --check-globals --include-generated-funcs
-; RUN: opt -mtriple=riscv32 -S -passes=verify,iroutliner -ir-outlining-no-cost < %s | FileCheck %s
-
-; REQUIRES: riscv-registered-target
-
-; This has two compatible regions based on function attributes. We have attributes
-; that should never be transferred to the outlined functions:
-; - `interrupt`=*
-
-; On RISC-V, the `interrupt` attribute only applies to the prolog and epilog of
-; the annotated function, and not any functions it calls. If this attribute is
-; preserved, there will be codegen errors because of restrictions on the
-; signatures of `interrupt` attributes.
-
-define void @outline_attrs1() #0 {
-entry:
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- %c = alloca i32, align 4
- store i32 2, ptr %a, align 4
- store i32 3, ptr %b, align 4
- store i32 4, ptr %c, align 4
- %al = load i32, ptr %a
- %bl = load i32, ptr %b
- %cl = load i32, ptr %c
- ret void
-}
-
-define void @outline_attrs2() #1 {
-entry:
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- %c = alloca i32, align 4
- store i32 2, ptr %a, align 4
- store i32 3, ptr %b, align 4
- store i32 4, ptr %c, align 4
- %al = load i32, ptr %a
- %bl = load i32, ptr %b
- %cl = load i32, ptr %c
- ret void
-}
-
-define void @outline_attrs3() {
-entry:
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- %c = alloca i32, align 4
- store i32 2, ptr %a, align 4
- store i32 3, ptr %b, align 4
- store i32 4, ptr %c, align 4
- %al = load i32, ptr %a
- %bl = load i32, ptr %b
- %cl = load i32, ptr %c
- ret void
-}
-
-define void @outline_outputs1() #0 {
-entry:
- %output = alloca i32, align 4
- %result = alloca i32, align 4
- %output2 = alloca i32, align 4
- %result2 = alloca i32, align 4
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- br label %block_2
-block_1:
- %a2 = alloca i32, align 4
- %b2 = alloca i32, align 4
- br label %block_2
-block_2:
- %a2val = load i32, ptr %a
- %b2val = load i32, ptr %b
- %add2 = add i32 2, %a2val
- %mul2 = mul i32 2, %b2val
- br label %block_5
-block_3:
- %aval = load i32, ptr %a
- %bval = load i32, ptr %b
- %add = add i32 2, %aval
- %mul = mul i32 2, %bval
- br label %block_4
-block_4:
- store i32 %add, ptr %output, align 4
- store i32 %mul, ptr %result, align 4
- br label %block_6
-block_5:
- store i32 %add2, ptr %output, align 4
- store i32 %mul2, ptr %result, align 4
- br label %block_7
-block_6:
- ret void
-block_7:
- ret void
-}
-
-define void @outline_outputs2() #1 {
-entry:
- %output = alloca i32, align 4
- %result = alloca i32, align 4
- %output2 = alloca i32, align 4
- %result2 = alloca i32, align 4
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- br label %block_2
-block_1:
- %a2 = alloca i32, align 4
- %b2 = alloca i32, align 4
- br label %block_2
-block_2:
- %a2val = load i32, ptr %a
- %b2val = load i32, ptr %b
- %add2 = add i32 2, %a2val
- %mul2 = mul i32 2, %b2val
- br label %block_5
-block_3:
- %aval = load i32, ptr %a
- %bval = load i32, ptr %b
- %add = add i32 2, %aval
- %mul = mul i32 2, %bval
- br label %block_4
-block_4:
- store i32 %add, ptr %output, align 4
- store i32 %mul, ptr %result, align 4
- br label %block_7
-block_5:
- store i32 %add2, ptr %output, align 4
- store i32 %mul2, ptr %result, align 4
- br label %block_6
-block_6:
- %diff = sub i32 %a2val, %b2val
- ret void
-block_7:
- %quot = udiv i32 %add, %mul
- ret void
-}
-
-attributes #0 = { "interrupt"="machine" optsize }
-attributes #1 = { "interrupt"="qci-nest" optsize }
-; CHECK-LABEL: define {{[^@]+}}@outline_attrs1
-; CHECK-SAME: () #[[ATTR0:[0-9]+]] {
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[C:%.*]] = alloca i32, align 4
-; CHECK-NEXT: call void @outlined_ir_func_1(ptr [[A]], ptr [[B]], ptr [[C]])
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: define {{[^@]+}}@outline_attrs2
-; CHECK-SAME: () #[[ATTR1:[0-9]+]] {
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[C:%.*]] = alloca i32, align 4
-; CHECK-NEXT: call void @outlined_ir_func_1(ptr [[A]], ptr [[B]], ptr [[C]])
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: define {{[^@]+}}@outline_attrs3() {
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[C:%.*]] = alloca i32, align 4
-; CHECK-NEXT: call void @outlined_ir_func_1(ptr [[A]], ptr [[B]], ptr [[C]])
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: define {{[^@]+}}@outline_outputs1
-; CHECK-SAME: () #[[ATTR0]] {
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[OUTPUT:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[RESULT:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[OUTPUT2:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[RESULT2:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
-; CHECK-NEXT: br label [[BLOCK_2:%.*]]
-; CHECK: block_1:
-; CHECK-NEXT: [[A2:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B2:%.*]] = alloca i32, align 4
-; CHECK-NEXT: br label [[BLOCK_2]]
-; CHECK: block_2:
-; CHECK-NEXT: [[TMP0:%.*]] = call i1 @outlined_ir_func_0(ptr [[A]], ptr [[B]], ptr [[OUTPUT]], ptr [[RESULT]], ptr null, ptr null, ptr null, ptr null, i32 -1)
-; CHECK-NEXT: br i1 [[TMP0]], label [[BLOCK_6:%.*]], label [[BLOCK_7:%.*]]
-; CHECK: block_6:
-; CHECK-NEXT: ret void
-; CHECK: block_7:
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: define {{[^@]+}}@outline_outputs2
-; CHECK-SAME: () #[[ATTR1]] {
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[MUL_LOC:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[ADD_LOC:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B2VAL_LOC:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[A2VAL_LOC:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[OUTPUT:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[RESULT:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[OUTPUT2:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[RESULT2:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
-; CHECK-NEXT: br label [[BLOCK_2:%.*]]
-; CHECK: block_1:
-; CHECK-NEXT: [[A2:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B2:%.*]] = alloca i32, align 4
-; CHECK-NEXT: br label [[BLOCK_2]]
-; CHECK: block_2:
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[A2VAL_LOC]])
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[B2VAL_LOC]])
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[ADD_LOC]])
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[MUL_LOC]])
-; CHECK-NEXT: [[TMP0:%.*]] = call i1 @outlined_ir_func_0(ptr [[A]], ptr [[B]], ptr [[OUTPUT]], ptr [[RESULT]], ptr [[A2VAL_LOC]], ptr [[B2VAL_LOC]], ptr [[ADD_LOC]], ptr [[MUL_LOC]], i32 0)
-; CHECK-NEXT: [[A2VAL_RELOAD:%.*]] = load i32, ptr [[A2VAL_LOC]], align 4
-; CHECK-NEXT: [[B2VAL_RELOAD:%.*]] = load i32, ptr [[B2VAL_LOC]], align 4
-; CHECK-NEXT: [[ADD_RELOAD:%.*]] = load i32, ptr [[ADD_LOC]], align 4
-; CHECK-NEXT: [[MUL_RELOAD:%.*]] = load i32, ptr [[MUL_LOC]], align 4
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[A2VAL_LOC]])
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[B2VAL_LOC]])
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[ADD_LOC]])
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[MUL_LOC]])
-; CHECK-NEXT: br i1 [[TMP0]], label [[BLOCK_7:%.*]], label [[BLOCK_6:%.*]]
-; CHECK: block_6:
-; CHECK-NEXT: [[DIFF:%.*]] = sub i32 [[A2VAL_RELOAD]], [[B2VAL_RELOAD]]
-; CHECK-NEXT: ret void
-; CHECK: block_7:
-; CHECK-NEXT: [[QUOT:%.*]] = udiv i32 [[ADD_RELOAD]], [[MUL_RELOAD]]
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: define {{[^@]+}}@outlined_ir_func_0
-; CHECK-SAME: (ptr [[TMP0:%.*]], ptr [[TMP1:%.*]], ptr [[TMP2:%.*]], ptr [[TMP3:%.*]], ptr [[TMP4:%.*]], ptr [[TMP5:%.*]], ptr [[TMP6:%.*]], ptr [[TMP7:%.*]], i32 [[TMP8:%.*]]) #[[ATTR3:[0-9]+]] {
-; CHECK-NEXT: newFuncRoot:
-; CHECK-NEXT: br label [[BLOCK_2_TO_OUTLINE:%.*]]
-; CHECK: block_2_to_outline:
-; CHECK-NEXT: [[A2VAL:%.*]] = load i32, ptr [[TMP0]], align 4
-; CHECK-NEXT: [[B2VAL:%.*]] = load i32, ptr [[TMP1]], align 4
-; CHECK-NEXT: [[ADD2:%.*]] = add i32 2, [[A2VAL]]
-; CHECK-NEXT: [[MUL2:%.*]] = mul i32 2, [[B2VAL]]
-; CHECK-NEXT: br label [[BLOCK_5:%.*]]
-; CHECK: block_3:
-; CHECK-NEXT: [[AVAL:%.*]] = load i32, ptr [[TMP0]], align 4
-; CHECK-NEXT: [[BVAL:%.*]] = load i32, ptr [[TMP1]], align 4
-; CHECK-NEXT: [[ADD:%.*]] = add i32 2, [[AVAL]]
-; CHECK-NEXT: [[MUL:%.*]] = mul i32 2, [[BVAL]]
-; CHECK-NEXT: br label [[BLOCK_4:%.*]]
-; CHECK: block_4:
-; CHECK-NEXT: store i32 [[ADD]], ptr [[TMP2]], align 4
-; CHECK-NEXT: store i32 [[MUL]], ptr [[TMP3]], align 4
-; CHECK-NEXT: br label [[BLOCK_6_EXITSTUB:%.*]]
-; CHECK: block_5:
-; CHECK-NEXT: store i32 [[ADD2]], ptr [[TMP2]], align 4
-; CHECK-NEXT: store i32 [[MUL2]], ptr [[TMP3]], align 4
-; CHECK-NEXT: br label [[BLOCK_7_EXITSTUB:%.*]]
-; CHECK: block_6.exitStub:
-; CHECK-NEXT: switch i32 [[TMP8]], label [[FINAL_BLOCK_1:%.*]] [
-; CHECK-NEXT: i32 0, label [[OUTPUT_BLOCK_1_1:%.*]]
-; CHECK-NEXT: ]
-; CHECK: block_7.exitStub:
-; CHECK-NEXT: switch i32 [[TMP8]], label [[FINAL_BLOCK_0:%.*]] [
-; CHECK-NEXT: i32 0, label [[OUTPUT_BLOCK_1_0:%.*]]
-; CHECK-NEXT: ]
-; CHECK: output_block_1_0:
-; CHECK-NEXT: store i32 [[A2VAL]], ptr [[TMP4]], align 4
-; CHECK-NEXT: store i32 [[B2VAL]], ptr [[TMP5]], align 4
-; CHECK-NEXT: br label [[FINAL_BLOCK_0]]
-; CHECK: output_block_1_1:
-; CHECK-NEXT: store i32 [[ADD]], ptr [[TMP6]], align 4
-; CHECK-NEXT: store i32 [[MUL]], ptr [[TMP7]], align 4
-; CHECK-NEXT: br label [[FINAL_BLOCK_1]]
-; CHECK: final_block_0:
-; CHECK-NEXT: ret i1 false
-; CHECK: final_block_1:
-; CHECK-NEXT: ret i1 true
-;
-;
-; CHECK-LABEL: define {{[^@]+}}@outlined_ir_func_1
-; CHECK-SAME: (ptr [[TMP0:%.*]], ptr [[TMP1:%.*]], ptr [[TMP2:%.*]]) #[[ATTR3]] {
-; CHECK-NEXT: newFuncRoot:
-; CHECK-NEXT: br label [[ENTRY_TO_OUTLINE:%.*]]
-; CHECK: entry_to_outline:
-; CHECK-NEXT: store i32 2, ptr [[TMP0]], align 4
-; CHECK-NEXT: store i32 3, ptr [[TMP1]], align 4
-; CHECK-NEXT: store i32 4, ptr [[TMP2]], align 4
-; CHECK-NEXT: [[AL:%.*]] = load i32, ptr [[TMP0]], align 4
-; CHECK-NEXT: [[BL:%.*]] = load i32, ptr [[TMP1]], align 4
-; CHECK-NEXT: [[CL:%.*]] = load i32, ptr [[TMP2]], align 4
-; CHECK-NEXT: br label [[ENTRY_AFTER_OUTLINE_EXITSTUB:%.*]]
-; CHECK: entry_after_outline.exitStub:
-; CHECK-NEXT: ret void
-;
-;.
-; CHECK: attributes #[[ATTR0]] = { optsize "interrupt"="machine" }
-; CHECK: attributes #[[ATTR1]] = { optsize "interrupt"="qci-nest" }
-; CHECK: attributes #[[ATTR2:[0-9]+]] = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) }
-; CHECK: attributes #[[ATTR3]] = { minsize optsize }
-;.
diff --git a/llvm/test/Transforms/IROutliner/outlining-compatible-or-attribute-transfer.ll b/llvm/test/Transforms/IROutliner/outlining-compatible-or-attribute-transfer.ll
deleted file mode 100644
index a8c5ed1d85b08..0000000000000
--- a/llvm/test/Transforms/IROutliner/outlining-compatible-or-attribute-transfer.ll
+++ /dev/null
@@ -1,67 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt -S -passes=verify,iroutliner -ir-outlining-no-cost < "%s" | FileCheck "%s"
-
-; This has two compatible regions. We have attributes that should be transferred
-; even if it is on only one of the regions.
-
-; This includes the attributes no-jump-tables, profile-sample-accurate,
-; speculative_load_hardening, and noimplicitfloat. When instance of similarity
-; has these attributes can we say that the outlined function can have these
-; attributes since that is the more general case.
-
-define void @outline_attrs1() #0 {
-; CHECK-LABEL: @outline_attrs1(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[C:%.*]] = alloca i32, align 4
-; CHECK-NEXT: call void @outlined_ir_func_0(ptr [[A]], ptr [[B]], ptr [[C]])
-; CHECK-NEXT: ret void
-;
-entry:
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- %c = alloca i32, align 4
- store i32 2, ptr %a, align 4
- store i32 3, ptr %b, align 4
- store i32 4, ptr %c, align 4
- %al = load i32, ptr %a
- %bl = load i32, ptr %b
- %cl = load i32, ptr %c
- ret void
-}
-
-define void @outline_attrs2() {
-; CHECK-LABEL: @outline_attrs2(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[C:%.*]] = alloca i32, align 4
-; CHECK-NEXT: call void @outlined_ir_func_0(ptr [[A]], ptr [[B]], ptr [[C]])
-; CHECK-NEXT: ret void
-;
-entry:
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- %c = alloca i32, align 4
- store i32 2, ptr %a, align 4
- store i32 3, ptr %b, align 4
- store i32 4, ptr %c, align 4
- %al = load i32, ptr %a
- %bl = load i32, ptr %b
- %cl = load i32, ptr %c
- ret void
-}
-
-attributes #0 = { "no-jump-tables"="true" "profile-sample-accurate"="true" "speculative_load_hardening" "noimplicitfloat"="true" "use-sample-profile"="true"}
-
-; CHECK: define internal void @outlined_ir_func_0(ptr [[ARG0:%.*]], ptr [[ARG1:%.*]], ptr [[ARG2:%.*]]) [[ATTR:#[0-9]+]] {
-; CHECK: entry_to_outline:
-; CHECK-NEXT: store i32 2, ptr [[ARG0]], align 4
-; CHECK-NEXT: store i32 3, ptr [[ARG1]], align 4
-; CHECK-NEXT: store i32 4, ptr [[ARG2]], align 4
-; CHECK-NEXT: [[AL:%.*]] = load i32, ptr [[ARG0]], align 4
-; CHECK-NEXT: [[BL:%.*]] = load i32, ptr [[ARG1]], align 4
-; CHECK-NEXT: [[CL:%.*]] = load i32, ptr [[ARG2]], align 4
-
-; CHECK: attributes [[ATTR]] = { minsize optsize "no-jump-tables"="true" "noimplicitfloat"="true" "profile-sample-accurate"="true" "speculative_load_hardening" "use-sample-profile"="true" }
diff --git a/llvm/test/Transforms/IROutliner/outlining-constants-vs-registers.ll b/llvm/test/Transforms/IROutliner/outlining-constants-vs-registers.ll
deleted file mode 100644
index a5a163ac548b4..0000000000000
--- a/llvm/test/Transforms/IROutliner/outlining-constants-vs-registers.ll
+++ /dev/null
@@ -1,82 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt -S -passes=verify,iroutliner -ir-outlining-no-cost < %s | FileCheck %s
-
-; This test looks at instances of constants in the different regions. If there
-; is a register in the same place as a constant in a similar region of code, we
-; do not outline those regions.
-
-; The first function tests that we do not outline with the register is
-; seen first, and the second function checks that we do not outline when the
-; constant is seen first.
-
-define void @function_registers_first(i32 %0, i32 %1, i32 %2) {
-; CHECK-LABEL: @function_registers_first(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[C:%.*]] = alloca i32, align 4
-; CHECK-NEXT: call void @outlined_ir_func_1(i32 [[TMP0:%.*]], ptr [[A]], i32 [[TMP1:%.*]], ptr [[B]], i32 [[TMP2:%.*]], ptr [[C]])
-; CHECK-NEXT: ret void
-; CHECK: next:
-; CHECK-NEXT: call void @outlined_ir_func_1(i32 2, ptr [[A]], i32 3, ptr [[B]], i32 4, ptr [[C]])
-; CHECK-NEXT: ret void
-;
-entry:
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- %c = alloca i32, align 4
- store i32 %0, ptr %a, align 4
- store i32 %1, ptr %b, align 4
- store i32 %2, ptr %c, align 4
- ret void
-next:
- store i32 2, ptr %a, align 4
- store i32 3, ptr %b, align 4
- store i32 4, ptr %c, align 4
- ret void
-}
-
-define void @function_with_constants_first(i32 %0, i32 %1, i32 %2) {
-; CHECK-LABEL: @function_with_constants_first(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[C:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[AL:%.*]] = load i32, ptr [[A]], align 4
-; CHECK-NEXT: [[BL:%.*]] = load i32, ptr [[B]], align 4
-; CHECK-NEXT: [[CL:%.*]] = load i32, ptr [[C]], align 4
-; CHECK-NEXT: call void @outlined_ir_func_0(i32 2, i32 [[AL]], i32 3, i32 [[BL]], i32 4, i32 [[CL]])
-; CHECK-NEXT: ret void
-; CHECK: next:
-; CHECK-NEXT: call void @outlined_ir_func_0(i32 [[TMP0:%.*]], i32 [[AL]], i32 [[TMP1:%.*]], i32 [[BL]], i32 [[TMP2:%.*]], i32 [[CL]])
-; CHECK-NEXT: ret void
-;
-entry:
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- %c = alloca i32, align 4
- %al = load i32, ptr %a
- %bl = load i32, ptr %b
- %cl = load i32, ptr %c
- %3 = add i32 2, %al
- %4 = add i32 3, %bl
- %5 = add i32 4, %cl
- ret void
-next:
- %6 = add i32 %0, %al
- %7 = add i32 %1, %bl
- %8 = add i32 %2, %cl
- ret void
-}
-
-; CHECK: define internal void @outlined_ir_func_0(i32 [[ARG0:%.*]], i32 [[ARG1:%.*]], i32 [[ARG2:%.*]], i32 [[ARG3:%.*]], i32 [[ARG4:%.*]], i32 [[ARG5:%.*]])
-; CHECK: entry_to_outline:
-; CHECK-NEXT: add i32 [[ARG0]], [[ARG1]]
-; CHECK-NEXT: add i32 [[ARG2]], [[ARG3]]
-; CHECK-NEXT: add i32 [[ARG4]], [[ARG5]]
-
-; CHECK: define internal void @outlined_ir_func_1(i32 [[ARG0:%.*]], ptr [[ARG1:%.*]], i32 [[ARG2:%.*]], ptr [[ARG3:%.*]], i32 [[ARG4:%.*]], ptr [[ARG5:%.*]])
-; CHECK: entry_to_outline:
-; CHECK-NEXT: store i32 [[ARG0]], ptr [[ARG1]]
-; CHECK-NEXT: store i32 [[ARG2]], ptr [[ARG3]]
-; CHECK-NEXT: store i32 [[ARG4]], ptr [[ARG5]]
diff --git a/llvm/test/Transforms/IROutliner/outlining-cost-model.ll b/llvm/test/Transforms/IROutliner/outlining-cost-model.ll
deleted file mode 100644
index bb3163a7941fe..0000000000000
--- a/llvm/test/Transforms/IROutliner/outlining-cost-model.ll
+++ /dev/null
@@ -1,187 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt -S -passes=verify,iroutliner < %s | FileCheck %s
-; RUN: opt -S -passes=verify,iroutliner -ir-outlining-no-cost < %s | FileCheck %s -check-prefix=NOCOST
-
-; This test checks that we have different results from when the cost model
-; is on versus when it is off. That is, if the number of instructions needed to
-; handle the arguments is greater than the number of instructions being added,
-; we do not outline.
-
-define void @function1() #0 {
-; CHECK-LABEL: @function1(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
-; CHECK-NEXT: call void @outlined_ir_func_0(ptr [[A]], ptr [[B]])
-; CHECK-NEXT: ret void
-;
-; NOCOST-LABEL: @function1(
-; NOCOST-NEXT: entry:
-; NOCOST-NEXT: [[A:%.*]] = alloca i32, align 4
-; NOCOST-NEXT: [[B:%.*]] = alloca i32, align 4
-; NOCOST-NEXT: call void @outlined_ir_func_0(ptr [[A]], ptr [[B]])
-; NOCOST-NEXT: ret void
-;
-entry:
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- %0 = load i32, ptr %a, align 4
- %1 = load i32, ptr %b, align 4
- %add = add i32 %0, %1
- %mul = mul i32 %0, %1
- %sub = sub i32 %0, %1
- %div = sdiv i32 %0, %1
- %add1 = add i32 %0, %1
- %mul1 = mul i32 %0, %1
- %sub1 = sub i32 %0, %1
- %div1 = sdiv i32 %0, %1
- %add2 = add i32 %0, %1
- %mul2 = mul i32 %0, %1
- %sub2 = sub i32 %0, %1
- %div2 = sdiv i32 %0, %1
- ret void
-}
-
-define void @function2() #0 {
-; CHECK-LABEL: @function2(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
-; CHECK-NEXT: call void @outlined_ir_func_0(ptr [[A]], ptr [[B]])
-; CHECK-NEXT: ret void
-;
-; NOCOST-LABEL: @function2(
-; NOCOST-NEXT: entry:
-; NOCOST-NEXT: [[A:%.*]] = alloca i32, align 4
-; NOCOST-NEXT: [[B:%.*]] = alloca i32, align 4
-; NOCOST-NEXT: call void @outlined_ir_func_0(ptr [[A]], ptr [[B]])
-; NOCOST-NEXT: ret void
-;
-entry:
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- %0 = load i32, ptr %a, align 4
- %1 = load i32, ptr %b, align 4
- %add = add i32 %0, %1
- %mul = mul i32 %0, %1
- %sub = sub i32 %0, %1
- %div = sdiv i32 %0, %1
- %add1 = add i32 %0, %1
- %mul1 = mul i32 %0, %1
- %sub1 = sub i32 %0, %1
- %div1 = sdiv i32 %0, %1
- %add2 = add i32 %0, %1
- %mul2 = mul i32 %0, %1
- %sub2 = sub i32 %0, %1
- %div2 = sdiv i32 %0, %1
- ret void
-}
-
-define void @function3() #0 {
-; CHECK-LABEL: @function3(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[OUTPUT:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[RESULT:%.*]] = alloca i32, align 4
-; CHECK-NEXT: store i32 2, ptr [[A]], align 4
-; CHECK-NEXT: store i32 3, ptr [[B]], align 4
-; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A]], align 4
-; CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[B]], align 4
-; CHECK-NEXT: [[ADD:%.*]] = add i32 [[TMP0]], [[TMP1]]
-; CHECK-NEXT: store i32 [[ADD]], ptr [[OUTPUT]], align 4
-; CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[OUTPUT]], align 4
-; CHECK-NEXT: [[TMP3:%.*]] = load i32, ptr [[OUTPUT]], align 4
-; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[TMP2]], [[ADD]]
-; CHECK-NEXT: store i32 [[MUL]], ptr [[RESULT]], align 4
-; CHECK-NEXT: ret void
-;
-; NOCOST-LABEL: @function3(
-; NOCOST-NEXT: entry:
-; NOCOST-NEXT: [[DOTLOC:%.*]] = alloca i32, align 4
-; NOCOST-NEXT: [[ADD_LOC:%.*]] = alloca i32, align 4
-; NOCOST-NEXT: [[A:%.*]] = alloca i32, align 4
-; NOCOST-NEXT: [[B:%.*]] = alloca i32, align 4
-; NOCOST-NEXT: [[OUTPUT:%.*]] = alloca i32, align 4
-; NOCOST-NEXT: [[RESULT:%.*]] = alloca i32, align 4
-; NOCOST-NEXT: call void @llvm.lifetime.start.p0(ptr [[ADD_LOC]])
-; NOCOST-NEXT: call void @llvm.lifetime.start.p0(ptr [[DOTLOC]])
-; NOCOST-NEXT: call void @outlined_ir_func_1(ptr [[A]], ptr [[B]], ptr [[OUTPUT]], ptr [[ADD_LOC]], ptr [[DOTLOC]])
-; NOCOST-NEXT: [[ADD_RELOAD:%.*]] = load i32, ptr [[ADD_LOC]], align 4
-; NOCOST-NEXT: [[DOTRELOAD:%.*]] = load i32, ptr [[DOTLOC]], align 4
-; NOCOST-NEXT: call void @llvm.lifetime.end.p0(ptr [[ADD_LOC]])
-; NOCOST-NEXT: call void @llvm.lifetime.end.p0(ptr [[DOTLOC]])
-; NOCOST-NEXT: [[TMP0:%.*]] = load i32, ptr [[OUTPUT]], align 4
-; NOCOST-NEXT: call void @outlined_ir_func_2(i32 [[DOTRELOAD]], i32 [[ADD_RELOAD]], ptr [[RESULT]])
-; NOCOST-NEXT: ret void
-;
-entry:
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- %output = alloca i32, align 4
- %result = alloca i32, align 4
- store i32 2, ptr %a, align 4
- store i32 3, ptr %b, align 4
- %0 = load i32, ptr %a, align 4
- %1 = load i32, ptr %b, align 4
- %add = add i32 %0, %1
- store i32 %add, ptr %output, align 4
- %2 = load i32, ptr %output, align 4
- %3 = load i32, ptr %output, align 4
- %mul = mul i32 %2, %add
- store i32 %mul, ptr %result, align 4
- ret void
-}
-
-define void @function4() #0 {
-; CHECK-LABEL: @function4(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[OUTPUT:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[RESULT:%.*]] = alloca i32, align 4
-; CHECK-NEXT: store i32 2, ptr [[A]], align 4
-; CHECK-NEXT: store i32 3, ptr [[B]], align 4
-; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A]], align 4
-; CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[B]], align 4
-; CHECK-NEXT: [[ADD:%.*]] = add i32 [[TMP0]], [[TMP1]]
-; CHECK-NEXT: store i32 [[ADD]], ptr [[OUTPUT]], align 4
-; CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[OUTPUT]], align 4
-; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[TMP2]], [[ADD]]
-; CHECK-NEXT: store i32 [[MUL]], ptr [[RESULT]], align 4
-; CHECK-NEXT: ret void
-;
-; NOCOST-LABEL: @function4(
-; NOCOST-NEXT: entry:
-; NOCOST-NEXT: [[DOTLOC:%.*]] = alloca i32, align 4
-; NOCOST-NEXT: [[ADD_LOC:%.*]] = alloca i32, align 4
-; NOCOST-NEXT: [[A:%.*]] = alloca i32, align 4
-; NOCOST-NEXT: [[B:%.*]] = alloca i32, align 4
-; NOCOST-NEXT: [[OUTPUT:%.*]] = alloca i32, align 4
-; NOCOST-NEXT: [[RESULT:%.*]] = alloca i32, align 4
-; NOCOST-NEXT: call void @llvm.lifetime.start.p0(ptr [[ADD_LOC]])
-; NOCOST-NEXT: call void @llvm.lifetime.start.p0(ptr [[DOTLOC]])
-; NOCOST-NEXT: call void @outlined_ir_func_1(ptr [[A]], ptr [[B]], ptr [[OUTPUT]], ptr [[ADD_LOC]], ptr [[DOTLOC]])
-; NOCOST-NEXT: [[ADD_RELOAD:%.*]] = load i32, ptr [[ADD_LOC]], align 4
-; NOCOST-NEXT: [[DOTRELOAD:%.*]] = load i32, ptr [[DOTLOC]], align 4
-; NOCOST-NEXT: call void @llvm.lifetime.end.p0(ptr [[ADD_LOC]])
-; NOCOST-NEXT: call void @llvm.lifetime.end.p0(ptr [[DOTLOC]])
-; NOCOST-NEXT: call void @outlined_ir_func_2(i32 [[DOTRELOAD]], i32 [[ADD_RELOAD]], ptr [[RESULT]])
-; NOCOST-NEXT: ret void
-;
-entry:
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- %output = alloca i32, align 4
- %result = alloca i32, align 4
- store i32 2, ptr %a, align 4
- store i32 3, ptr %b, align 4
- %0 = load i32, ptr %a, align 4
- %1 = load i32, ptr %b, align 4
- %add = add i32 %0, %1
- store i32 %add, ptr %output, align 4
- %2 = load i32, ptr %output, align 4
- %mul = mul i32 %2, %add
- store i32 %mul, ptr %result, align 4
- ret void
-}
diff --git a/llvm/test/Transforms/IROutliner/outlining-debug-statements.ll b/llvm/test/Transforms/IROutliner/outlining-debug-statements.ll
deleted file mode 100644
index c1140988fa916..0000000000000
--- a/llvm/test/Transforms/IROutliner/outlining-debug-statements.ll
+++ /dev/null
@@ -1,65 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt -S -passes=verify,iroutliner -ir-outlining-no-cost < %s | FileCheck %s
-
-; This test makes sure that we do not include debug statements in outlined
-; functions.
-
-define void @outline_dbg1() {
-; CHECK-LABEL: @outline_dbg1(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[C:%.*]] = alloca i32, align 4
-; CHECK-NEXT: call void @outlined_ir_func_0(ptr [[A]], ptr [[B]], ptr [[C]])
-; CHECK-NEXT: ret void
-;
-entry:
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- %c = alloca i32, align 4
- store i32 2, ptr %a, align 4
- store i32 3, ptr %b, align 4
- call void @llvm.dbg.value(metadata i64 0, metadata !14, metadata !DIExpression()), !dbg !15
- store i32 4, ptr %c, align 4
- %al = load i32, ptr %a
- %bl = load i32, ptr %b
- %cl = load i32, ptr %c
- ret void
-}
-
-declare void @llvm.dbg.value(metadata, metadata, metadata)
-
-define void @outline_dbg2() {
-; CHECK-LABEL: @outline_dbg2(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[C:%.*]] = alloca i32, align 4
-; CHECK-NEXT: call void @outlined_ir_func_0(ptr [[A]], ptr [[B]], ptr [[C]])
-; CHECK-NEXT: ret void
-;
-entry:
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- %c = alloca i32, align 4
- store i32 2, ptr %a, align 4
- store i32 3, ptr %b, align 4
- store i32 4, ptr %c, align 4
- %al = load i32, ptr %a
- %bl = load i32, ptr %b
- %cl = load i32, ptr %c
- ret void
-}
-
-; CHECK: entry_to_outline:
-
-!0 = !DIFile(filename: "foo.c", directory: "/tmp")
-!1 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
-!5 = distinct !DICompileUnit(language: DW_LANG_C, file: !0, producer: "My Compiler", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !6, retainedTypes: !6, globals: !7)
-!6 = !{}
-!7 = !{}
-!11 = distinct !DISubprogram(name: "func_5", scope: !0, file: !0, line: 117, type: !12, isLocal: true, isDefinition: true, scopeLine: 118, isOptimized: false, unit: !5, retainedNodes: !6)
-!12 = !DISubroutineType(types: !13)
-!13 = !{}
-!14 = !DILocalVariable(name: "p_6", arg: 1, scope: !11, line: 117, type: !1)
-!15 = !DILocation(line: 1, scope: !11)
diff --git a/llvm/test/Transforms/IROutliner/outlining-different-constants.ll b/llvm/test/Transforms/IROutliner/outlining-different-constants.ll
deleted file mode 100644
index 1d887b330d78d..0000000000000
--- a/llvm/test/Transforms/IROutliner/outlining-different-constants.ll
+++ /dev/null
@@ -1,58 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt -S -passes=verify,iroutliner -ir-outlining-no-cost < %s | FileCheck %s
-
-; This test looks at the constants in the regions, and if it they are the
-; differents it elevates the constants to arguments.
-
-define void @outline_constants1() {
-; CHECK-LABEL: @outline_constants1(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[C:%.*]] = alloca i32, align 4
-; CHECK-NEXT: call void @outlined_ir_func_0(i32 3, ptr [[A]], i32 4, ptr [[B]], i32 5, ptr [[C]])
-; CHECK-NEXT: ret void
-;
-entry:
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- %c = alloca i32, align 4
- store i32 3, ptr %a, align 4
- store i32 4, ptr %b, align 4
- store i32 5, ptr %c, align 4
- %al = load i32, ptr %a
- %bl = load i32, ptr %b
- %cl = load i32, ptr %c
- ret void
-}
-
-define void @outline_constants2() {
-; CHECK-LABEL: @outline_constants2(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[C:%.*]] = alloca i32, align 4
-; CHECK-NEXT: call void @outlined_ir_func_0(i32 2, ptr [[A]], i32 3, ptr [[B]], i32 4, ptr [[C]])
-; CHECK-NEXT: ret void
-;
-entry:
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- %c = alloca i32, align 4
- store i32 2, ptr %a, align 4
- store i32 3, ptr %b, align 4
- store i32 4, ptr %c, align 4
- %al = load i32, ptr %a
- %bl = load i32, ptr %b
- %cl = load i32, ptr %c
- ret void
-}
-
-; CHECK: define internal void @outlined_ir_func_0(i32 [[ARG0:%.*]], ptr [[ARG1:%.*]], i32 [[ARG2:%.*]], ptr [[ARG3:%.*]], i32 [[ARG4:%.*]], ptr [[ARG5:%.*]]) #0 {
-; CHECK: entry_to_outline:
-; CHECK-NEXT: store i32 [[ARG0]], ptr [[ARG1]], align 4
-; CHECK-NEXT: store i32 [[ARG2]], ptr [[ARG3]], align 4
-; CHECK-NEXT: store i32 [[ARG4]], ptr [[ARG5]], align 4
-; CHECK-NEXT: [[AL:%.*]] = load i32, ptr [[ARG1]], align 4
-; CHECK-NEXT: [[BL:%.*]] = load i32, ptr [[ARG3]], align 4
-; CHECK-NEXT: [[CL:%.*]] = load i32, ptr [[ARG5]], align 4
diff --git a/llvm/test/Transforms/IROutliner/outlining-different-globals.ll b/llvm/test/Transforms/IROutliner/outlining-different-globals.ll
deleted file mode 100644
index c4463be4b627f..0000000000000
--- a/llvm/test/Transforms/IROutliner/outlining-different-globals.ll
+++ /dev/null
@@ -1,42 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt -S -passes=verify,iroutliner -ir-outlining-no-cost < %s | FileCheck %s
-
-; This test looks at the globals in the regions, and makes sure they are not
-; outlined if they are different values.
-
- at global1 = global i32 1, align 4
- at global2 = global i32 2, align 4
- at global3 = global i32 3, align 4
- at global4 = global i32 4, align 4
-
-define void @outline_globals1() {
-; CHECK-LABEL: @outline_globals1(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: call void @outlined_ir_func_0(ptr @global1, ptr @global2)
-; CHECK-NEXT: ret void
-;
-entry:
- %0 = load i32, ptr @global1
- %1 = load i32, ptr @global2
- %2 = add i32 %0, %1
- ret void
-}
-
-define void @outline_globals2() {
-; CHECK-LABEL: @outline_globals2(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: call void @outlined_ir_func_0(ptr @global3, ptr @global4)
-; CHECK-NEXT: ret void
-;
-entry:
- %0 = load i32, ptr @global3
- %1 = load i32, ptr @global4
- %2 = add i32 %0, %1
- ret void
-}
-
-; CHECK: define internal void @outlined_ir_func_0(ptr [[ARG0:%.*]], ptr [[ARG1:%.*]])
-; CHECK: entry_to_outline:
-; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[ARG0]]
-; CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[ARG1]]
-; CHECK-NEXT: [[TMP2:%.*]] = add i32 [[TMP0]], [[TMP1]]
diff --git a/llvm/test/Transforms/IROutliner/outlining-different-output-blocks.ll b/llvm/test/Transforms/IROutliner/outlining-different-output-blocks.ll
deleted file mode 100644
index 64e87fcf7fb75..0000000000000
--- a/llvm/test/Transforms/IROutliner/outlining-different-output-blocks.ll
+++ /dev/null
@@ -1,106 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt -S -passes=iroutliner -ir-outlining-no-cost < %s | FileCheck %s
-
-; These functions are constructed slightly differently so that they require
-; different output blocks for the values used outside of the region. We are
-; checking that two output blocks are created with different values.
-
-define void @outline_outputs1() #0 {
-; CHECK-LABEL: @outline_outputs1(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[DOTLOC:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[ADD_LOC:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[OUTPUT:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[RESULT:%.*]] = alloca i32, align 4
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[ADD_LOC]])
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[DOTLOC]])
-; CHECK-NEXT: call void @outlined_ir_func_0(ptr [[A]], ptr [[B]], ptr [[OUTPUT]], ptr [[ADD_LOC]], ptr [[DOTLOC]], i32 0)
-; CHECK-NEXT: [[ADD_RELOAD:%.*]] = load i32, ptr [[ADD_LOC]], align 4
-; CHECK-NEXT: [[DOTRELOAD:%.*]] = load i32, ptr [[DOTLOC]], align 4
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[ADD_LOC]])
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[DOTLOC]])
-; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[OUTPUT]], align 4
-; CHECK-NEXT: call void @outlined_ir_func_1(i32 [[DOTRELOAD]], i32 [[ADD_RELOAD]], ptr [[RESULT]])
-; CHECK-NEXT: ret void
-;
-entry:
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- %output = alloca i32, align 4
- %result = alloca i32, align 4
- store i32 2, ptr %a, align 4
- store i32 3, ptr %b, align 4
- %0 = load i32, ptr %a, align 4
- %1 = load i32, ptr %b, align 4
- %add = add i32 %0, %1
- %sub = sub i32 %0, %1
- store i32 %add, ptr %output, align 4
- %2 = load i32, ptr %output, align 4
- %3 = load i32, ptr %output, align 4
- %mul = mul i32 %2, %add
- store i32 %mul, ptr %result, align 4
- ret void
-}
-
-define void @outline_outputs2() #0 {
-; CHECK-LABEL: @outline_outputs2(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[DOTLOC:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[SUB_LOC:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[OUTPUT:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[RESULT:%.*]] = alloca i32, align 4
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[SUB_LOC]])
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[DOTLOC]])
-; CHECK-NEXT: call void @outlined_ir_func_0(ptr [[A]], ptr [[B]], ptr [[OUTPUT]], ptr [[SUB_LOC]], ptr [[DOTLOC]], i32 1)
-; CHECK-NEXT: [[SUB_RELOAD:%.*]] = load i32, ptr [[SUB_LOC]], align 4
-; CHECK-NEXT: [[DOTRELOAD:%.*]] = load i32, ptr [[DOTLOC]], align 4
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[SUB_LOC]])
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[DOTLOC]])
-; CHECK-NEXT: call void @outlined_ir_func_1(i32 [[DOTRELOAD]], i32 [[SUB_RELOAD]], ptr [[RESULT]])
-; CHECK-NEXT: ret void
-;
-entry:
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- %output = alloca i32, align 4
- %result = alloca i32, align 4
- store i32 2, ptr %a, align 4
- store i32 3, ptr %b, align 4
- %0 = load i32, ptr %a, align 4
- %1 = load i32, ptr %b, align 4
- %add = add i32 %0, %1
- %sub = sub i32 %0, %1
- store i32 %add, ptr %output, align 4
- %2 = load i32, ptr %output, align 4
- %mul = mul i32 %2, %sub
- store i32 %mul, ptr %result, align 4
- ret void
-}
-
-; CHECK: define internal void @outlined_ir_func_0(ptr [[ARG0:%.*]], ptr [[ARG1:%.*]], ptr [[ARG2:%.*]], ptr [[ARG3:%.*]], ptr [[ARG4:%.*]], i32 [[ARG5:%.*]]) #1 {
-; CHECK: entry_to_outline:
-; CHECK-NEXT: store i32 2, ptr [[ARG0]], align 4
-; CHECK-NEXT: store i32 3, ptr [[ARG1]], align 4
-; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[ARG0]], align 4
-; CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[ARG1]], align 4
-; CHECK-NEXT: [[ADD:%.*]] = add i32 [[TMP0]], [[TMP1]]
-; CHECK-NEXT: [[SUB:%.*]] = sub i32 [[TMP0]], [[TMP1]]
-; CHECK-NEXT: store i32 [[ADD]], ptr [[ARG2]], align 4
-; CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[ARG2]], align 4
-
-; CHECK: _after_outline.exitStub:
-; CHECK-NEXT: switch i32 [[ARG5]], label [[BLOCK:%.*]] [
-; CHECK-NEXT: i32 0, label %[[BLOCK_0:.*]]
-; CHECK-NEXT: i32 1, label %[[BLOCK_1:.*]]
-
-; CHECK: [[BLOCK_0]]:
-; CHECK-NEXT: store i32 [[ADD]], ptr [[ARG3]], align 4
-; CHECK-NEXT: store i32 [[TMP2]], ptr [[ARG4]], align 4
-
-; CHECK: [[BLOCK_1]]:
-; CHECK-NEXT: store i32 [[SUB]], ptr [[ARG3]], align 4
-; CHECK-NEXT: store i32 [[TMP2]], ptr [[ARG4]], align 4
diff --git a/llvm/test/Transforms/IROutliner/outlining-different-structure.ll b/llvm/test/Transforms/IROutliner/outlining-different-structure.ll
deleted file mode 100644
index 45b33daa8e6c9..0000000000000
--- a/llvm/test/Transforms/IROutliner/outlining-different-structure.ll
+++ /dev/null
@@ -1,62 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt -S -passes=verify,iroutliner -ir-outlining-no-cost < %s | FileCheck %s
-
-; This is a negative case to show that when we have the same set of
-; instructions, but in a different order, they are not outlined in the same way.
-; In this case, the arguments passed into the function are in a different order.
-
-define void @outline_constants1() {
-; CHECK-LABEL: @outline_constants1(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[C:%.*]] = alloca i32, align 4
-; CHECK-NEXT: store i32 2, ptr [[A]], align 4
-; CHECK-NEXT: store i32 3, ptr [[B]], align 4
-; CHECK-NEXT: store i32 4, ptr [[C]], align 4
-; CHECK-NEXT: call void @[[FUNCTION_0:.*]](ptr [[A]], ptr [[C]], ptr [[B]])
-; CHECK-NEXT: ret void
-;
-entry:
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- %c = alloca i32, align 4
- store i32 2, ptr %a, align 4
- store i32 3, ptr %b, align 4
- store i32 4, ptr %c, align 4
- %al = load i32, ptr %a
- %cl = load i32, ptr %c
- %bl = load i32, ptr %b
- ret void
-}
-
-define void @outline_constants2() {
-; CHECK-LABEL: @outline_constants2(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[C:%.*]] = alloca i32, align 4
-; CHECK-NEXT: store i32 2, ptr [[A]], align 4
-; CHECK-NEXT: store i32 3, ptr [[B]], align 4
-; CHECK-NEXT: store i32 4, ptr [[C]], align 4
-; CHECK-NEXT: call void @[[FUNCTION_0]](ptr [[A]], ptr [[B]], ptr [[C]])
-; CHECK-NEXT: ret void
-;
-entry:
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- %c = alloca i32, align 4
- store i32 2, ptr %a, align 4
- store i32 3, ptr %b, align 4
- store i32 4, ptr %c, align 4
- %al = load i32, ptr %a
- %bl = load i32, ptr %b
- %cl = load i32, ptr %c
- ret void
-}
-
-; CHECK: define internal void @[[FUNCTION_0]](ptr [[ARG0:%.*]], ptr [[ARG1:%.*]], ptr [[ARG2:%.*]])
-; CHECK: entry_to_outline:
-; CHECK-NEXT: [[AL:%.*]] = load i32, ptr [[ARG0]], align 4
-; CHECK-NEXT: [[BL:%.*]] = load i32, ptr [[ARG1]], align 4
-; CHECK-NEXT: [[CL:%.*]] = load i32, ptr [[ARG2]], align 4
diff --git a/llvm/test/Transforms/IROutliner/outlining-exits-to-phi-node.ll b/llvm/test/Transforms/IROutliner/outlining-exits-to-phi-node.ll
deleted file mode 100644
index d901955caadfb..0000000000000
--- a/llvm/test/Transforms/IROutliner/outlining-exits-to-phi-node.ll
+++ /dev/null
@@ -1,92 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --include-generated-funcs
-; RUN: opt -S -passes=verify,iroutliner -ir-outlining-no-cost < %s | FileCheck %s
-
-; Show that we do not extract similar regions that would involve the splitting
-; of phi nodes on exit.
-
-define void @function1(ptr %a, ptr %b) {
-entry:
- %0 = alloca i32, align 4
- %c = load i32, ptr %0, align 4
- br label %test1
-test1:
- %e = load i32, ptr %0, align 4
- br label %first
-test:
- %d = load i32, ptr %0, align 4
- br label %first
-dummy:
- ret void
-first:
- %1 = phi i32 [ %c, %test ], [ %e, %test1 ]
- ret void
-}
-
-define void @function2(ptr %a, ptr %b) {
-entry:
- %0 = alloca i32, align 4
- %c = load i32, ptr %0, align 4
- br label %test1
-test1:
- %e = load i32, ptr %0, align 4
- br label %first
-test:
- %d = load i32, ptr %0, align 4
- br label %first
-dummy:
- ret void
-first:
- %1 = phi i32 [ %c, %test ], [ %e, %test1 ]
- ret void
-}
-; CHECK-LABEL: @function1(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[DOTCE_LOC:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[TMP0:%.*]] = alloca i32, align 4
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[DOTCE_LOC]])
-; CHECK-NEXT: call void @outlined_ir_func_0(ptr [[TMP0]], ptr [[DOTCE_LOC]])
-; CHECK-NEXT: [[DOTCE_RELOAD:%.*]] = load i32, ptr [[DOTCE_LOC]], align 4
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[DOTCE_LOC]])
-; CHECK-NEXT: br label [[FIRST:%.*]]
-; CHECK: dummy:
-; CHECK-NEXT: ret void
-; CHECK: first:
-; CHECK-NEXT: [[TMP1:%.*]] = phi i32 [ [[DOTCE_RELOAD]], [[ENTRY:%.*]] ]
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: @function2(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[DOTCE_LOC:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[TMP0:%.*]] = alloca i32, align 4
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[DOTCE_LOC]])
-; CHECK-NEXT: call void @outlined_ir_func_0(ptr [[TMP0]], ptr [[DOTCE_LOC]])
-; CHECK-NEXT: [[DOTCE_RELOAD:%.*]] = load i32, ptr [[DOTCE_LOC]], align 4
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[DOTCE_LOC]])
-; CHECK-NEXT: br label [[FIRST:%.*]]
-; CHECK: dummy:
-; CHECK-NEXT: ret void
-; CHECK: first:
-; CHECK-NEXT: [[TMP1:%.*]] = phi i32 [ [[DOTCE_RELOAD]], [[ENTRY:%.*]] ]
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: define internal void @outlined_ir_func_0(
-; CHECK-NEXT: newFuncRoot:
-; CHECK-NEXT: br label [[ENTRY_TO_OUTLINE:%.*]]
-; CHECK: entry_to_outline:
-; CHECK-NEXT: [[C:%.*]] = load i32, ptr [[TMP0:%.*]], align 4
-; CHECK-NEXT: br label [[TEST1:%.*]]
-; CHECK: test1:
-; CHECK-NEXT: [[E:%.*]] = load i32, ptr [[TMP0]], align 4
-; CHECK-NEXT: br label [[FIRST_SPLIT:%.*]]
-; CHECK: test:
-; CHECK-NEXT: [[D:%.*]] = load i32, ptr [[TMP0]], align 4
-; CHECK-NEXT: br label [[FIRST_SPLIT]]
-; CHECK: first.split:
-; CHECK-NEXT: [[DOTCE:%.*]] = phi i32 [ [[C]], [[TEST:%.*]] ], [ [[E]], [[TEST1]] ]
-; CHECK-NEXT: br label [[FIRST_EXITSTUB:%.*]]
-; CHECK: first.exitStub:
-; CHECK-NEXT: store i32 [[DOTCE]], ptr [[TMP1:%.*]], align 4
-; CHECK-NEXT: ret void
-;
diff --git a/llvm/test/Transforms/IROutliner/outlining-first-instruction.ll b/llvm/test/Transforms/IROutliner/outlining-first-instruction.ll
deleted file mode 100644
index 53803ddcc95e5..0000000000000
--- a/llvm/test/Transforms/IROutliner/outlining-first-instruction.ll
+++ /dev/null
@@ -1,67 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --include-generated-funcs
-; RUN: opt -S -passes=verify,iroutliner -ir-outlining-no-cost < %s | FileCheck %s
-
-; Make sure that we outline from all three of these functions, and that
-; the first instruction in the module is included when it is the only
-; instruction in the first basic block.
-
-define void @f1() {
-bb:
- br label %bb1
-bb1:
- br label %bb2
-bb2:
- ret void
-}
-
-define void @f2() {
-bb:
- br label %bb1
-bb1:
- br label %bb2
-bb2:
- ret void
-}
-
-define void @f3() {
-bb:
- br label %bb1
-bb1:
- br label %bb2
-bb2:
- ret void
-}
-; CHECK-LABEL: @f1(
-; CHECK-NEXT: bb:
-; CHECK-NEXT: call void @outlined_ir_func_0()
-; CHECK-NEXT: br label [[BB2:%.*]]
-; CHECK: bb2:
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: @f2(
-; CHECK-NEXT: bb:
-; CHECK-NEXT: call void @outlined_ir_func_0()
-; CHECK-NEXT: br label [[BB2:%.*]]
-; CHECK: bb2:
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: @f3(
-; CHECK-NEXT: bb:
-; CHECK-NEXT: call void @outlined_ir_func_0()
-; CHECK-NEXT: br label [[BB2:%.*]]
-; CHECK: bb2:
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: define internal void @outlined_ir_func_0(
-; CHECK-NEXT: newFuncRoot:
-; CHECK-NEXT: br label [[BB_TO_OUTLINE:%.*]]
-; CHECK: bb_to_outline:
-; CHECK-NEXT: br label [[BB1:%.*]]
-; CHECK: bb1:
-; CHECK-NEXT: br label [[BB2_EXITSTUB:%.*]]
-; CHECK: bb2.exitStub:
-; CHECK-NEXT: ret void
-;
diff --git a/llvm/test/Transforms/IROutliner/outlining-gep.ll b/llvm/test/Transforms/IROutliner/outlining-gep.ll
deleted file mode 100644
index 78e2e19a4b788..0000000000000
--- a/llvm/test/Transforms/IROutliner/outlining-gep.ll
+++ /dev/null
@@ -1,68 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt -S -passes=verify,iroutliner -ir-outlining-no-cost < %s | FileCheck %s
-
-; This test checks to make sure that we outline getelementptr instructions only
-; when all the operands after the first are the exact same. In this case, we
-; outline from the first two functions, but not the third.
-
-%struct.RT = type { i8, [10 x [20 x i32]], i8 }
-%struct.ST = type { i32, double, %struct.RT }
-
-define void @function1(ptr %s, i64 %t) {
-; CHECK-LABEL: @function1(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
-; CHECK-NEXT: call void @outlined_ir_func_0(ptr [[A]], ptr [[B]], ptr [[S:%.*]], i64 [[T:%.*]])
-; CHECK-NEXT: ret void
-;
-entry:
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- store i32 2, ptr %a, align 4
- store i32 3, ptr %b, align 4
- %0 = getelementptr inbounds %struct.ST, ptr %s, i64 %t, i32 1
- ret void
-}
-
-define void @function2(ptr %s, i64 %t) {
-; CHECK-LABEL: @function2(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
-; CHECK-NEXT: call void @outlined_ir_func_0(ptr [[A]], ptr [[B]], ptr [[S:%.*]], i64 [[T:%.*]])
-; CHECK-NEXT: ret void
-;
-entry:
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- store i32 2, ptr %a, align 4
- store i32 3, ptr %b, align 4
- %0 = getelementptr inbounds %struct.ST, ptr %s, i64 %t, i32 1
- ret void
-}
-
-define void @function3(ptr %s, i64 %t) {
-; CHECK-LABEL: @function3(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
-; CHECK-NEXT: store i32 2, ptr [[A]], align 4
-; CHECK-NEXT: store i32 3, ptr [[B]], align 4
-; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT_ST:%.*]], ptr [[S:%.*]], i64 [[T:%.*]], i32 0
-; CHECK-NEXT: ret void
-;
-entry:
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- store i32 2, ptr %a, align 4
- store i32 3, ptr %b, align 4
- %0 = getelementptr inbounds %struct.ST, ptr %s, i64 %t, i32 0
- ret void
-}
-
-; CHECK: define internal void @outlined_ir_func_0(ptr [[ARG0:%.*]], ptr [[ARG1:%.*]], ptr [[ARG2:%.*]], i64 [[ARG3:%.*]])
-; CHECK: entry_to_outline:
-; CHECK-NEXT: store i32 2, ptr [[ARG0]], align 4
-; CHECK-NEXT: store i32 3, ptr [[ARG1]], align 4
-; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds %struct.ST, ptr [[ARG2]], i64 [[ARG3]], i32 1
diff --git a/llvm/test/Transforms/IROutliner/outlining-isomorphic-predicates.ll b/llvm/test/Transforms/IROutliner/outlining-isomorphic-predicates.ll
deleted file mode 100644
index 2fe807e5d30c9..0000000000000
--- a/llvm/test/Transforms/IROutliner/outlining-isomorphic-predicates.ll
+++ /dev/null
@@ -1,170 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt -S -passes=verify,iroutliner -ir-outlining-no-cost < %s | FileCheck %s
-
-; This test checks the isomorphic comparisons can be outlined together into one
-; function.
-
-; The following three function are identical, except that in the third, the
-; operand order, and predicate are swapped, meaning it is structurally the same
-; and should be outlined together.
-
-define void @outline_slt1() {
-; CHECK-LABEL: @outline_slt1(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
-; CHECK-NEXT: call void @outlined_ir_func_1(ptr [[A]], ptr [[B]])
-; CHECK-NEXT: ret void
-;
-entry:
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- store i32 2, ptr %a, align 4
- store i32 3, ptr %b, align 4
- %al = load i32, ptr %a
- %bl = load i32, ptr %b
- %0 = icmp slt i32 %al, %bl
- ret void
-}
-
-define void @outline_slt2() {
-; CHECK-LABEL: @outline_slt2(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
-; CHECK-NEXT: call void @outlined_ir_func_1(ptr [[A]], ptr [[B]])
-; CHECK-NEXT: ret void
-;
-entry:
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- store i32 2, ptr %a, align 4
- store i32 3, ptr %b, align 4
- %al = load i32, ptr %a
- %bl = load i32, ptr %b
- %0 = icmp slt i32 %al, %bl
- ret void
-}
-
-define void @outline_sgt() {
-; CHECK-LABEL: @outline_sgt(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
-; CHECK-NEXT: call void @outlined_ir_func_1(ptr [[A]], ptr [[B]])
-; CHECK-NEXT: ret void
-;
-entry:
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- store i32 2, ptr %a, align 4
- store i32 3, ptr %b, align 4
- %al = load i32, ptr %a
- %bl = load i32, ptr %b
- %0 = icmp sgt i32 %bl, %al
- ret void
-}
-
-; This has a swapped predicate, but not swapped operands, so it cannot use
-; the same outlined function as the ones above.
-
-define void @dontoutline_sgt() {
-; CHECK-LABEL: @dontoutline_sgt(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
-; CHECK-NEXT: store i32 2, ptr [[A]], align 4
-; CHECK-NEXT: store i32 3, ptr [[B]], align 4
-; CHECK-NEXT: [[AL:%.*]] = load i32, ptr [[A]], align 4
-; CHECK-NEXT: [[BL:%.*]] = load i32, ptr [[B]], align 4
-; CHECK-NEXT: [[TMP0:%.*]] = icmp sgt i32 [[AL]], [[BL]]
-; CHECK-NEXT: ret void
-;
-entry:
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- store i32 2, ptr %a, align 4
- store i32 3, ptr %b, align 4
- %al = load i32, ptr %a
- %bl = load i32, ptr %b
- %0 = icmp sgt i32 %al, %bl
- ret void
-}
-
-; The below functions use a different kind of predicate that is not compatible
-; with the ones above, and should use a different outlined function.
-; The other difference here is that the predicate with swapped operands comes
-; first this time.
-
-define void @outline_ugt1() {
-; CHECK-LABEL: @outline_ugt1(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
-; CHECK-NEXT: call void @outlined_ir_func_0(ptr [[A]], ptr [[B]])
-; CHECK-NEXT: ret void
-;
-entry:
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- store i32 2, ptr %a, align 4
- store i32 3, ptr %b, align 4
- %al = load i32, ptr %a
- %bl = load i32, ptr %b
- %0 = icmp ugt i32 %al, %bl
- ret void
-}
-
-define void @outline_ugt2() {
-; CHECK-LABEL: @outline_ugt2(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
-; CHECK-NEXT: call void @outlined_ir_func_0(ptr [[A]], ptr [[B]])
-; CHECK-NEXT: ret void
-;
-entry:
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- store i32 2, ptr %a, align 4
- store i32 3, ptr %b, align 4
- %al = load i32, ptr %a
- %bl = load i32, ptr %b
- %0 = icmp ugt i32 %al, %bl
- ret void
-}
-
-define void @outline_ult() {
-; CHECK-LABEL: @outline_ult(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
-; CHECK-NEXT: call void @outlined_ir_func_0(ptr [[A]], ptr [[B]])
-; CHECK-NEXT: ret void
-;
-entry:
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- store i32 2, ptr %a, align 4
- store i32 3, ptr %b, align 4
- %al = load i32, ptr %a
- %bl = load i32, ptr %b
- %0 = icmp ult i32 %bl, %al
- ret void
-}
-
-; CHECK: define internal void @outlined_ir_func_0(ptr [[ARG0:%.*]], ptr [[ARG1:%.*]]) #0 {
-; CHECK: entry_to_outline:
-; CHECK-NEXT: store i32 2, ptr [[ARG0]], align 4
-; CHECK-NEXT: store i32 3, ptr [[ARG1]], align 4
-; CHECK-NEXT: [[AL:%.*]] = load i32, ptr [[ARG0]], align 4
-; CHECK-NEXT: [[BL:%.*]] = load i32, ptr [[ARG1]], align 4
-; CHECK-NEXT: [[TMP0:%.*]] = icmp ugt i32 [[AL]], [[BL]]
-
-; CHECK: define internal void @outlined_ir_func_1(ptr [[ARG0:%.*]], ptr [[ARG1:%.*]]) #0 {
-; CHECK: entry_to_outline:
-; CHECK-NEXT: store i32 2, ptr [[ARG0]], align 4
-; CHECK-NEXT: store i32 3, ptr [[ARG1]], align 4
-; CHECK-NEXT: [[AL:%.*]] = load i32, ptr [[ARG0]], align 4
-; CHECK-NEXT: [[BL:%.*]] = load i32, ptr [[ARG1]], align 4
-; CHECK-NEXT: [[TMP0:%.*]] = icmp slt i32 [[AL]], [[BL]]
diff --git a/llvm/test/Transforms/IROutliner/outlining-larger-size-commutative.ll b/llvm/test/Transforms/IROutliner/outlining-larger-size-commutative.ll
deleted file mode 100644
index 00098e6ba407d..0000000000000
--- a/llvm/test/Transforms/IROutliner/outlining-larger-size-commutative.ll
+++ /dev/null
@@ -1,89 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt -S -p iroutliner,verify -ir-outlining-no-cost < %s | FileCheck %s
-
-; This test checks that commutative instructions where the operands are
-; swapped are outlined as the same function.
-
-; It also checks that non-commutative instructions outlined as different
-; functions when the operands are swapped;
-
-; These are identical functions, except that in the flipped functions,
-; the operands in the adds are commuted. However, since add instructions
-; are commutative, we should still outline from all four as the same
-; instruction.
-
-define void @function1(i32 %a, i32 %b) {
-; CHECK-LABEL: @function1(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: br label [[BLOCK_1:%.*]]
-; CHECK: block_0:
-; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[A:%.*]], [[B:%.*]]
-; CHECK-NEXT: [[TMP1:%.*]] = add i32 [[TMP4:%.*]], 1
-; CHECK-NEXT: [[TMP2:%.*]] = add i32 [[TMP0]], [[TMP0]]
-; CHECK-NEXT: [[TMP3:%.*]] = icmp sgt i32 [[TMP0]], [[TMP0]]
-; CHECK-NEXT: br i1 [[TMP3]], label [[BLOCK_1]], label [[BLOCK_2:%.*]]
-; CHECK: block_1:
-; CHECK-NEXT: [[TMP4]] = phi i32 [ [[TMP1]], [[BLOCK_0:%.*]] ], [ 0, [[ENTRY:%.*]] ]
-; CHECK-NEXT: call void @outlined_ir_func_0(i32 [[B]])
-; CHECK-NEXT: br label [[BLOCK_0]]
-; CHECK: block_2:
-; CHECK-NEXT: [[TMP5:%.*]] = add i32 [[TMP2]], [[TMP2]]
-; CHECK-NEXT: ret void
-;
-entry:
- br label %block_1
-
-block_0:
- %0 = add i32 %a, %b
- %1 = add i32 %4, 1
- %2 = add i32 %0, %0
- %3 = icmp sgt i32 %0, %0
- br i1 %3, label %block_1, label %block_2
-
-block_1:
- %4 = phi i32 [ %1, %block_0 ], [ 0, %entry ]
- %5 = add i32 %b, %b
- br label %block_0
-
-block_2:
- %6 = add i32 %2, %2
- ret void
-}
-
-define void @function2(i32 %a, i32 %b) {
-; CHECK-LABEL: @function2(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: br label [[BLOCK_1:%.*]]
-; CHECK: block_0:
-; CHECK-NEXT: [[TMP0:%.*]] = sub i32 [[A:%.*]], [[B:%.*]]
-; CHECK-NEXT: [[TMP1:%.*]] = add i32 1, [[TMP4:%.*]]
-; CHECK-NEXT: [[TMP2:%.*]] = add i32 [[TMP0]], [[TMP0]]
-; CHECK-NEXT: [[TMP3:%.*]] = icmp sgt i32 [[TMP0]], [[TMP0]]
-; CHECK-NEXT: br i1 [[TMP3]], label [[BLOCK_1]], label [[BLOCK_2:%.*]]
-; CHECK: block_1:
-; CHECK-NEXT: [[TMP4]] = phi i32 [ [[TMP1]], [[BLOCK_0:%.*]] ], [ 0, [[ENTRY:%.*]] ]
-; CHECK-NEXT: call void @outlined_ir_func_0(i32 [[B]])
-; CHECK-NEXT: br label [[BLOCK_0]]
-; CHECK: block_2:
-; CHECK-NEXT: [[TMP5:%.*]] = sub i32 [[TMP2]], [[TMP2]]
-; CHECK-NEXT: ret void
-;
-entry:
- br label %block_1
-
-block_0:
- %0 = sub i32 %a, %b
- %1 = add i32 1, %4
- %2 = add i32 %0, %0
- %3 = icmp sgt i32 %0, %0
- br i1 %3, label %block_1, label %block_2
-
-block_1:
- %4 = phi i32 [ %1, %block_0 ], [ 0, %entry ]
- %5 = add i32 %b, %b
- br label %block_0
-
-block_2:
- %6 = sub i32 %2, %2
- ret void
-}
diff --git a/llvm/test/Transforms/IROutliner/outlining-multiple-exits-diff-outputs.ll b/llvm/test/Transforms/IROutliner/outlining-multiple-exits-diff-outputs.ll
deleted file mode 100644
index 9dbfa9ebd7e37..0000000000000
--- a/llvm/test/Transforms/IROutliner/outlining-multiple-exits-diff-outputs.ll
+++ /dev/null
@@ -1,221 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --include-generated-funcs
-; RUN: opt -S -passes=verify,iroutliner -ir-outlining-no-cost < %s | FileCheck %s
-
-; Here we have multiple exits, but the different sources, different outputs are
-; needed, this checks that they are handled by separate switch statements.
-
-define void @outline_outputs1() #0 {
-entry:
- %output = alloca i32, align 4
- %result = alloca i32, align 4
- %output2 = alloca i32, align 4
- %result2 = alloca i32, align 4
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- br label %block_2
-block_1:
- %a2 = alloca i32, align 4
- %b2 = alloca i32, align 4
- br label %block_2
-block_2:
- %a2val = load i32, ptr %a
- %b2val = load i32, ptr %b
- %add2 = add i32 2, %a2val
- %mul2 = mul i32 2, %b2val
- br label %block_5
-block_3:
- %aval = load i32, ptr %a
- %bval = load i32, ptr %b
- %add = add i32 2, %aval
- %mul = mul i32 2, %bval
- br label %block_4
-block_4:
- store i32 %add, ptr %output, align 4
- store i32 %mul, ptr %result, align 4
- br label %block_6
-block_5:
- store i32 %add2, ptr %output, align 4
- store i32 %mul2, ptr %result, align 4
- br label %block_7
-block_6:
- %div = udiv i32 %aval, %bval
- ret void
-block_7:
- %sub = sub i32 %a2val, %b2val
- ret void
-}
-
-define void @outline_outputs2() #0 {
-entry:
- %output = alloca i32, align 4
- %result = alloca i32, align 4
- %output2 = alloca i32, align 4
- %result2 = alloca i32, align 4
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- br label %block_2
-block_1:
- %a2 = alloca i32, align 4
- %b2 = alloca i32, align 4
- br label %block_2
-block_2:
- %a2val = load i32, ptr %a
- %b2val = load i32, ptr %b
- %add2 = add i32 2, %a2val
- %mul2 = mul i32 2, %b2val
- br label %block_5
-block_3:
- %aval = load i32, ptr %a
- %bval = load i32, ptr %b
- %add = add i32 2, %aval
- %mul = mul i32 2, %bval
- br label %block_4
-block_4:
- store i32 %add, ptr %output, align 4
- store i32 %mul, ptr %result, align 4
- br label %block_7
-block_5:
- store i32 %add2, ptr %output, align 4
- store i32 %mul2, ptr %result, align 4
- br label %block_6
-block_6:
- %diff = sub i32 %a2val, %b2val
- ret void
-block_7:
- %quot = udiv i32 %add, %mul
- ret void
-}
-; CHECK-LABEL: @outline_outputs1(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[BVAL_LOC:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[AVAL_LOC:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B2VAL_LOC:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[A2VAL_LOC:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[OUTPUT:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[RESULT:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[OUTPUT2:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[RESULT2:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
-; CHECK-NEXT: br label [[BLOCK_2:%.*]]
-; CHECK: block_1:
-; CHECK-NEXT: [[A2:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B2:%.*]] = alloca i32, align 4
-; CHECK-NEXT: br label [[BLOCK_2]]
-; CHECK: block_2:
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[A2VAL_LOC]])
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[B2VAL_LOC]])
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[AVAL_LOC]])
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[BVAL_LOC]])
-; CHECK-NEXT: [[TMP0:%.*]] = call i1 @outlined_ir_func_0(ptr [[A]], ptr [[B]], ptr [[OUTPUT]], ptr [[RESULT]], ptr [[A2VAL_LOC]], ptr [[B2VAL_LOC]], ptr [[AVAL_LOC]], ptr [[BVAL_LOC]], i32 0)
-; CHECK-NEXT: [[A2VAL_RELOAD:%.*]] = load i32, ptr [[A2VAL_LOC]], align 4
-; CHECK-NEXT: [[B2VAL_RELOAD:%.*]] = load i32, ptr [[B2VAL_LOC]], align 4
-; CHECK-NEXT: [[AVAL_RELOAD:%.*]] = load i32, ptr [[AVAL_LOC]], align 4
-; CHECK-NEXT: [[BVAL_RELOAD:%.*]] = load i32, ptr [[BVAL_LOC]], align 4
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[A2VAL_LOC]])
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[B2VAL_LOC]])
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[AVAL_LOC]])
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[BVAL_LOC]])
-; CHECK-NEXT: br i1 [[TMP0]], label [[BLOCK_6:%.*]], label [[BLOCK_7:%.*]]
-; CHECK: block_6:
-; CHECK-NEXT: [[DIV:%.*]] = udiv i32 [[AVAL_RELOAD]], [[BVAL_RELOAD]]
-; CHECK-NEXT: ret void
-; CHECK: block_7:
-; CHECK-NEXT: [[SUB:%.*]] = sub i32 [[A2VAL_RELOAD]], [[B2VAL_RELOAD]]
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: @outline_outputs2(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[MUL_LOC:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[ADD_LOC:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B2VAL_LOC:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[A2VAL_LOC:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[OUTPUT:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[RESULT:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[OUTPUT2:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[RESULT2:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
-; CHECK-NEXT: br label [[BLOCK_2:%.*]]
-; CHECK: block_1:
-; CHECK-NEXT: [[A2:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B2:%.*]] = alloca i32, align 4
-; CHECK-NEXT: br label [[BLOCK_2]]
-; CHECK: block_2:
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[A2VAL_LOC]])
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[B2VAL_LOC]])
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[ADD_LOC]])
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[MUL_LOC]])
-; CHECK-NEXT: [[TMP0:%.*]] = call i1 @outlined_ir_func_0(ptr [[A]], ptr [[B]], ptr [[OUTPUT]], ptr [[RESULT]], ptr [[A2VAL_LOC]], ptr [[B2VAL_LOC]], ptr [[ADD_LOC]], ptr [[MUL_LOC]], i32 1)
-; CHECK-NEXT: [[A2VAL_RELOAD:%.*]] = load i32, ptr [[A2VAL_LOC]], align 4
-; CHECK-NEXT: [[B2VAL_RELOAD:%.*]] = load i32, ptr [[B2VAL_LOC]], align 4
-; CHECK-NEXT: [[ADD_RELOAD:%.*]] = load i32, ptr [[ADD_LOC]], align 4
-; CHECK-NEXT: [[MUL_RELOAD:%.*]] = load i32, ptr [[MUL_LOC]], align 4
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[A2VAL_LOC]])
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[B2VAL_LOC]])
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[ADD_LOC]])
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[MUL_LOC]])
-; CHECK-NEXT: br i1 [[TMP0]], label [[BLOCK_7:%.*]], label [[BLOCK_6:%.*]]
-; CHECK: block_6:
-; CHECK-NEXT: [[DIFF:%.*]] = sub i32 [[A2VAL_RELOAD]], [[B2VAL_RELOAD]]
-; CHECK-NEXT: ret void
-; CHECK: block_7:
-; CHECK-NEXT: [[QUOT:%.*]] = udiv i32 [[ADD_RELOAD]], [[MUL_RELOAD]]
-; CHECK-NEXT: ret void
-;
-;
-; CHECK: define internal i1 @outlined_ir_func_0(
-; CHECK-NEXT: newFuncRoot:
-; CHECK-NEXT: br label [[BLOCK_2_TO_OUTLINE:%.*]]
-; CHECK: block_2_to_outline:
-; CHECK-NEXT: [[A2VAL:%.*]] = load i32, ptr [[TMP0:%.*]], align 4
-; CHECK-NEXT: [[B2VAL:%.*]] = load i32, ptr [[TMP1:%.*]], align 4
-; CHECK-NEXT: [[ADD2:%.*]] = add i32 2, [[A2VAL]]
-; CHECK-NEXT: [[MUL2:%.*]] = mul i32 2, [[B2VAL]]
-; CHECK-NEXT: br label [[BLOCK_5:%.*]]
-; CHECK: block_3:
-; CHECK-NEXT: [[AVAL:%.*]] = load i32, ptr [[TMP0]], align 4
-; CHECK-NEXT: [[BVAL:%.*]] = load i32, ptr [[TMP1]], align 4
-; CHECK-NEXT: [[ADD:%.*]] = add i32 2, [[AVAL]]
-; CHECK-NEXT: [[MUL:%.*]] = mul i32 2, [[BVAL]]
-; CHECK-NEXT: br label [[BLOCK_4:%.*]]
-; CHECK: block_4:
-; CHECK-NEXT: store i32 [[ADD]], ptr [[TMP2:%.*]], align 4
-; CHECK-NEXT: store i32 [[MUL]], ptr [[TMP3:%.*]], align 4
-; CHECK-NEXT: br label [[BLOCK_6_EXITSTUB:%.*]]
-; CHECK: block_5:
-; CHECK-NEXT: store i32 [[ADD2]], ptr [[TMP2]], align 4
-; CHECK-NEXT: store i32 [[MUL2]], ptr [[TMP3]], align 4
-; CHECK-NEXT: br label [[BLOCK_7_EXITSTUB:%.*]]
-; CHECK: block_6.exitStub:
-; CHECK-NEXT: switch i32 [[TMP8:%.*]], label [[FINAL_BLOCK_1:%.*]] [
-; CHECK-NEXT: i32 0, label [[OUTPUT_BLOCK_0_1:%.*]]
-; CHECK-NEXT: i32 1, label [[OUTPUT_BLOCK_1_1:%.*]]
-; CHECK-NEXT: ]
-; CHECK: block_7.exitStub:
-; CHECK-NEXT: switch i32 [[TMP8]], label [[FINAL_BLOCK_0:%.*]] [
-; CHECK-NEXT: i32 0, label [[OUTPUT_BLOCK_0_0:%.*]]
-; CHECK-NEXT: i32 1, label [[OUTPUT_BLOCK_1_0:%.*]]
-; CHECK-NEXT: ]
-; CHECK: output_block_0_0:
-; CHECK-NEXT: store i32 [[A2VAL]], ptr [[TMP4:%.*]], align 4
-; CHECK-NEXT: store i32 [[B2VAL]], ptr [[TMP5:%.*]], align 4
-; CHECK-NEXT: br label [[FINAL_BLOCK_0]]
-; CHECK: output_block_0_1:
-; CHECK-NEXT: store i32 [[AVAL]], ptr [[TMP6:%.*]], align 4
-; CHECK-NEXT: store i32 [[BVAL]], ptr [[TMP7:%.*]], align 4
-; CHECK-NEXT: br label [[FINAL_BLOCK_1]]
-; CHECK: output_block_1_0:
-; CHECK-NEXT: store i32 [[A2VAL]], ptr [[TMP4]], align 4
-; CHECK-NEXT: store i32 [[B2VAL]], ptr [[TMP5]], align 4
-; CHECK-NEXT: br label [[FINAL_BLOCK_0]]
-; CHECK: output_block_1_1:
-; CHECK-NEXT: store i32 [[ADD]], ptr [[TMP6]], align 4
-; CHECK-NEXT: store i32 [[MUL]], ptr [[TMP7]], align 4
-; CHECK-NEXT: br label [[FINAL_BLOCK_1]]
-; CHECK: final_block_0:
-; CHECK-NEXT: ret i1 false
-; CHECK: final_block_1:
-; CHECK-NEXT: ret i1 true
-;
diff --git a/llvm/test/Transforms/IROutliner/outlining-multiple-exits-one-output-set.ll b/llvm/test/Transforms/IROutliner/outlining-multiple-exits-one-output-set.ll
deleted file mode 100644
index f7897358a55bc..0000000000000
--- a/llvm/test/Transforms/IROutliner/outlining-multiple-exits-one-output-set.ll
+++ /dev/null
@@ -1,192 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --include-generated-funcs
-; RUN: opt -S -passes=verify,iroutliner -ir-outlining-no-cost < %s | FileCheck %s
-
-; Here we have multiple exits, but different sources, and only one has an
-; output set. We check to make sure that we do not generated extra output
-; blocks or entries in the switch statement.
-
-define void @outline_outputs1() #0 {
-entry:
- %output = alloca i32, align 4
- %result = alloca i32, align 4
- %output2 = alloca i32, align 4
- %result2 = alloca i32, align 4
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- br label %block_2
-block_1:
- %a2 = alloca i32, align 4
- %b2 = alloca i32, align 4
- br label %block_2
-block_2:
- %a2val = load i32, ptr %a
- %b2val = load i32, ptr %b
- %add2 = add i32 2, %a2val
- %mul2 = mul i32 2, %b2val
- br label %block_5
-block_3:
- %aval = load i32, ptr %a
- %bval = load i32, ptr %b
- %add = add i32 2, %aval
- %mul = mul i32 2, %bval
- br label %block_4
-block_4:
- store i32 %add, ptr %output, align 4
- store i32 %mul, ptr %result, align 4
- br label %block_6
-block_5:
- store i32 %add2, ptr %output, align 4
- store i32 %mul2, ptr %result, align 4
- br label %block_7
-block_6:
- ret void
-block_7:
- ret void
-}
-
-define void @outline_outputs2() #0 {
-entry:
- %output = alloca i32, align 4
- %result = alloca i32, align 4
- %output2 = alloca i32, align 4
- %result2 = alloca i32, align 4
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- br label %block_2
-block_1:
- %a2 = alloca i32, align 4
- %b2 = alloca i32, align 4
- br label %block_2
-block_2:
- %a2val = load i32, ptr %a
- %b2val = load i32, ptr %b
- %add2 = add i32 2, %a2val
- %mul2 = mul i32 2, %b2val
- br label %block_5
-block_3:
- %aval = load i32, ptr %a
- %bval = load i32, ptr %b
- %add = add i32 2, %aval
- %mul = mul i32 2, %bval
- br label %block_4
-block_4:
- store i32 %add, ptr %output, align 4
- store i32 %mul, ptr %result, align 4
- br label %block_7
-block_5:
- store i32 %add2, ptr %output, align 4
- store i32 %mul2, ptr %result, align 4
- br label %block_6
-block_6:
- %diff = sub i32 %a2val, %b2val
- ret void
-block_7:
- %quot = udiv i32 %add, %mul
- ret void
-}
-; CHECK-LABEL: @outline_outputs1(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[OUTPUT:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[RESULT:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[OUTPUT2:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[RESULT2:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
-; CHECK-NEXT: br label [[BLOCK_2:%.*]]
-; CHECK: block_1:
-; CHECK-NEXT: [[A2:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B2:%.*]] = alloca i32, align 4
-; CHECK-NEXT: br label [[BLOCK_2]]
-; CHECK: block_2:
-; CHECK-NEXT: [[TMP0:%.*]] = call i1 @outlined_ir_func_0(ptr [[A]], ptr [[B]], ptr [[OUTPUT]], ptr [[RESULT]], ptr null, ptr null, ptr null, ptr null, i32 -1)
-; CHECK-NEXT: br i1 [[TMP0]], label [[BLOCK_6:%.*]], label [[BLOCK_7:%.*]]
-; CHECK: block_6:
-; CHECK-NEXT: ret void
-; CHECK: block_7:
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: @outline_outputs2(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[MUL_LOC:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[ADD_LOC:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B2VAL_LOC:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[A2VAL_LOC:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[OUTPUT:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[RESULT:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[OUTPUT2:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[RESULT2:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
-; CHECK-NEXT: br label [[BLOCK_2:%.*]]
-; CHECK: block_1:
-; CHECK-NEXT: [[A2:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B2:%.*]] = alloca i32, align 4
-; CHECK-NEXT: br label [[BLOCK_2]]
-; CHECK: block_2:
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[A2VAL_LOC]])
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[B2VAL_LOC]])
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[ADD_LOC]])
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[MUL_LOC]])
-; CHECK-NEXT: [[TMP0:%.*]] = call i1 @outlined_ir_func_0(ptr [[A]], ptr [[B]], ptr [[OUTPUT]], ptr [[RESULT]], ptr [[A2VAL_LOC]], ptr [[B2VAL_LOC]], ptr [[ADD_LOC]], ptr [[MUL_LOC]], i32 0)
-; CHECK-NEXT: [[A2VAL_RELOAD:%.*]] = load i32, ptr [[A2VAL_LOC]], align 4
-; CHECK-NEXT: [[B2VAL_RELOAD:%.*]] = load i32, ptr [[B2VAL_LOC]], align 4
-; CHECK-NEXT: [[ADD_RELOAD:%.*]] = load i32, ptr [[ADD_LOC]], align 4
-; CHECK-NEXT: [[MUL_RELOAD:%.*]] = load i32, ptr [[MUL_LOC]], align 4
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[A2VAL_LOC]])
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[B2VAL_LOC]])
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[ADD_LOC]])
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[MUL_LOC]])
-; CHECK-NEXT: br i1 [[TMP0]], label [[BLOCK_7:%.*]], label [[BLOCK_6:%.*]]
-; CHECK: block_6:
-; CHECK-NEXT: [[DIFF:%.*]] = sub i32 [[A2VAL_RELOAD]], [[B2VAL_RELOAD]]
-; CHECK-NEXT: ret void
-; CHECK: block_7:
-; CHECK-NEXT: [[QUOT:%.*]] = udiv i32 [[ADD_RELOAD]], [[MUL_RELOAD]]
-; CHECK-NEXT: ret void
-;
-;
-; CHECK: define internal i1 @outlined_ir_func_0(
-; CHECK-NEXT: newFuncRoot:
-; CHECK-NEXT: br label [[BLOCK_2_TO_OUTLINE:%.*]]
-; CHECK: block_2_to_outline:
-; CHECK-NEXT: [[A2VAL:%.*]] = load i32, ptr [[TMP0:%.*]], align 4
-; CHECK-NEXT: [[B2VAL:%.*]] = load i32, ptr [[TMP1:%.*]], align 4
-; CHECK-NEXT: [[ADD2:%.*]] = add i32 2, [[A2VAL]]
-; CHECK-NEXT: [[MUL2:%.*]] = mul i32 2, [[B2VAL]]
-; CHECK-NEXT: br label [[BLOCK_5:%.*]]
-; CHECK: block_3:
-; CHECK-NEXT: [[AVAL:%.*]] = load i32, ptr [[TMP0]], align 4
-; CHECK-NEXT: [[BVAL:%.*]] = load i32, ptr [[TMP1]], align 4
-; CHECK-NEXT: [[ADD:%.*]] = add i32 2, [[AVAL]]
-; CHECK-NEXT: [[MUL:%.*]] = mul i32 2, [[BVAL]]
-; CHECK-NEXT: br label [[BLOCK_4:%.*]]
-; CHECK: block_4:
-; CHECK-NEXT: store i32 [[ADD]], ptr [[TMP2:%.*]], align 4
-; CHECK-NEXT: store i32 [[MUL]], ptr [[TMP3:%.*]], align 4
-; CHECK-NEXT: br label [[BLOCK_6_EXITSTUB:%.*]]
-; CHECK: block_5:
-; CHECK-NEXT: store i32 [[ADD2]], ptr [[TMP2]], align 4
-; CHECK-NEXT: store i32 [[MUL2]], ptr [[TMP3]], align 4
-; CHECK-NEXT: br label [[BLOCK_7_EXITSTUB:%.*]]
-; CHECK: block_6.exitStub:
-; CHECK-NEXT: switch i32 [[TMP8:%.*]], label [[FINAL_BLOCK_1:%.*]] [
-; CHECK-NEXT: i32 0, label [[OUTPUT_BLOCK_1_1:%.*]]
-; CHECK-NEXT: ]
-; CHECK: block_7.exitStub:
-; CHECK-NEXT: switch i32 [[TMP8]], label [[FINAL_BLOCK_0:%.*]] [
-; CHECK-NEXT: i32 0, label [[OUTPUT_BLOCK_1_0:%.*]]
-; CHECK-NEXT: ]
-; CHECK: output_block_1_0:
-; CHECK-NEXT: store i32 [[A2VAL]], ptr [[TMP4:%.*]], align 4
-; CHECK-NEXT: store i32 [[B2VAL]], ptr [[TMP5:%.*]], align 4
-; CHECK-NEXT: br label [[FINAL_BLOCK_0]]
-; CHECK: output_block_1_1:
-; CHECK-NEXT: store i32 [[ADD]], ptr [[TMP6:%.*]], align 4
-; CHECK-NEXT: store i32 [[MUL]], ptr [[TMP7:%.*]], align 4
-; CHECK-NEXT: br label [[FINAL_BLOCK_1]]
-; CHECK: final_block_0:
-; CHECK-NEXT: ret i1 false
-; CHECK: final_block_1:
-; CHECK-NEXT: ret i1 true
-;
diff --git a/llvm/test/Transforms/IROutliner/outlining-multiple-exits.ll b/llvm/test/Transforms/IROutliner/outlining-multiple-exits.ll
deleted file mode 100644
index 1de13ebc3bc3a..0000000000000
--- a/llvm/test/Transforms/IROutliner/outlining-multiple-exits.ll
+++ /dev/null
@@ -1,200 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --include-generated-funcs
-; RUN: opt -S -passes=verify,iroutliner -ir-outlining-no-cost < %s | FileCheck %s
-
-; Here we have multiple exits, but the different sources, same outputs are
-; needed, this checks that they are compressed, and moved into the appropriate
-; output blocks.
-
-define void @outline_outputs1() #0 {
-entry:
- %output = alloca i32, align 4
- %result = alloca i32, align 4
- %output2 = alloca i32, align 4
- %result2 = alloca i32, align 4
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- br label %block_2
-block_1:
- %a2 = alloca i32, align 4
- %b2 = alloca i32, align 4
- br label %block_2
-block_2:
- %a2val = load i32, ptr %a
- %b2val = load i32, ptr %b
- %add2 = add i32 2, %a2val
- %mul2 = mul i32 2, %b2val
- br label %block_5
-block_3:
- %aval = load i32, ptr %a
- %bval = load i32, ptr %b
- %add = add i32 2, %aval
- %mul = mul i32 2, %bval
- br label %block_4
-block_4:
- store i32 %add, ptr %output, align 4
- store i32 %mul, ptr %result, align 4
- br label %block_6
-block_5:
- store i32 %add2, ptr %output, align 4
- store i32 %mul2, ptr %result, align 4
- br label %block_7
-block_6:
- %div = udiv i32 %aval, %bval
- ret void
-block_7:
- %sub = sub i32 %a2val, %b2val
- ret void
-}
-
-define void @outline_outputs2() #0 {
-entry:
- %output = alloca i32, align 4
- %result = alloca i32, align 4
- %output2 = alloca i32, align 4
- %result2 = alloca i32, align 4
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- br label %block_2
-block_1:
- %a2 = alloca i32, align 4
- %b2 = alloca i32, align 4
- br label %block_2
-block_2:
- %a2val = load i32, ptr %a
- %b2val = load i32, ptr %b
- %add2 = add i32 2, %a2val
- %mul2 = mul i32 2, %b2val
- br label %block_5
-block_3:
- %aval = load i32, ptr %a
- %bval = load i32, ptr %b
- %add = add i32 2, %aval
- %mul = mul i32 2, %bval
- br label %block_4
-block_4:
- store i32 %add, ptr %output, align 4
- store i32 %mul, ptr %result, align 4
- br label %block_7
-block_5:
- store i32 %add2, ptr %output, align 4
- store i32 %mul2, ptr %result, align 4
- br label %block_6
-block_6:
- %diff = sub i32 %a2val, %b2val
- ret void
-block_7:
- %quot = udiv i32 %aval, %bval
- ret void
-}
-; CHECK-LABEL: @outline_outputs1(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[BVAL_LOC:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[AVAL_LOC:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B2VAL_LOC:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[A2VAL_LOC:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[OUTPUT:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[RESULT:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[OUTPUT2:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[RESULT2:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
-; CHECK-NEXT: br label [[BLOCK_2:%.*]]
-; CHECK: block_1:
-; CHECK-NEXT: [[A2:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B2:%.*]] = alloca i32, align 4
-; CHECK-NEXT: br label [[BLOCK_2]]
-; CHECK: block_2:
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[A2VAL_LOC]])
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[B2VAL_LOC]])
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[AVAL_LOC]])
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[BVAL_LOC]])
-; CHECK-NEXT: [[TARGETBLOCK:%.*]] = call i1 @outlined_ir_func_0(ptr [[A]], ptr [[B]], ptr [[OUTPUT]], ptr [[RESULT]], ptr [[A2VAL_LOC]], ptr [[B2VAL_LOC]], ptr [[AVAL_LOC]], ptr [[BVAL_LOC]])
-; CHECK-NEXT: [[A2VAL_RELOAD:%.*]] = load i32, ptr [[A2VAL_LOC]], align 4
-; CHECK-NEXT: [[B2VAL_RELOAD:%.*]] = load i32, ptr [[B2VAL_LOC]], align 4
-; CHECK-NEXT: [[AVAL_RELOAD:%.*]] = load i32, ptr [[AVAL_LOC]], align 4
-; CHECK-NEXT: [[BVAL_RELOAD:%.*]] = load i32, ptr [[BVAL_LOC]], align 4
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[A2VAL_LOC]])
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[B2VAL_LOC]])
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[AVAL_LOC]])
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[BVAL_LOC]])
-; CHECK-NEXT: br i1 [[TARGETBLOCK]], label [[BLOCK_6:%.*]], label [[BLOCK_7:%.*]]
-; CHECK: block_6:
-; CHECK-NEXT: [[DIV:%.*]] = udiv i32 [[AVAL_RELOAD]], [[BVAL_RELOAD]]
-; CHECK-NEXT: ret void
-; CHECK: block_7:
-; CHECK-NEXT: [[SUB:%.*]] = sub i32 [[A2VAL_RELOAD]], [[B2VAL_RELOAD]]
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: @outline_outputs2(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[BVAL_LOC:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[AVAL_LOC:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B2VAL_LOC:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[A2VAL_LOC:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[OUTPUT:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[RESULT:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[OUTPUT2:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[RESULT2:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
-; CHECK-NEXT: br label [[BLOCK_2:%.*]]
-; CHECK: block_1:
-; CHECK-NEXT: [[A2:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B2:%.*]] = alloca i32, align 4
-; CHECK-NEXT: br label [[BLOCK_2]]
-; CHECK: block_2:
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[A2VAL_LOC]])
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[B2VAL_LOC]])
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[AVAL_LOC]])
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[BVAL_LOC]])
-; CHECK-NEXT: [[TARGETBLOCK:%.*]] = call i1 @outlined_ir_func_0(ptr [[A]], ptr [[B]], ptr [[OUTPUT]], ptr [[RESULT]], ptr [[A2VAL_LOC]], ptr [[B2VAL_LOC]], ptr [[AVAL_LOC]], ptr [[BVAL_LOC]])
-; CHECK-NEXT: [[A2VAL_RELOAD:%.*]] = load i32, ptr [[A2VAL_LOC]], align 4
-; CHECK-NEXT: [[B2VAL_RELOAD:%.*]] = load i32, ptr [[B2VAL_LOC]], align 4
-; CHECK-NEXT: [[AVAL_RELOAD:%.*]] = load i32, ptr [[AVAL_LOC]], align 4
-; CHECK-NEXT: [[BVAL_RELOAD:%.*]] = load i32, ptr [[BVAL_LOC]], align 4
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[A2VAL_LOC]])
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[B2VAL_LOC]])
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[AVAL_LOC]])
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[BVAL_LOC]])
-; CHECK-NEXT: br i1 [[TARGETBLOCK]], label [[BLOCK_7:%.*]], label [[BLOCK_6:%.*]]
-; CHECK: block_6:
-; CHECK-NEXT: [[DIFF:%.*]] = sub i32 [[A2VAL_RELOAD]], [[B2VAL_RELOAD]]
-; CHECK-NEXT: ret void
-; CHECK: block_7:
-; CHECK-NEXT: [[QUOT:%.*]] = udiv i32 [[AVAL_RELOAD]], [[BVAL_RELOAD]]
-; CHECK-NEXT: ret void
-;
-;
-; CHECK: define internal i1 @outlined_ir_func_0(
-; CHECK-NEXT: newFuncRoot:
-; CHECK-NEXT: br label [[BLOCK_2_TO_OUTLINE:%.*]]
-; CHECK: block_2_to_outline:
-; CHECK-NEXT: [[A2VAL:%.*]] = load i32, ptr [[TMP0:%.*]], align 4
-; CHECK-NEXT: [[B2VAL:%.*]] = load i32, ptr [[TMP1:%.*]], align 4
-; CHECK-NEXT: [[ADD2:%.*]] = add i32 2, [[A2VAL]]
-; CHECK-NEXT: [[MUL2:%.*]] = mul i32 2, [[B2VAL]]
-; CHECK-NEXT: br label [[BLOCK_5:%.*]]
-; CHECK: block_3:
-; CHECK-NEXT: [[AVAL:%.*]] = load i32, ptr [[TMP0]], align 4
-; CHECK-NEXT: [[BVAL:%.*]] = load i32, ptr [[TMP1]], align 4
-; CHECK-NEXT: [[ADD:%.*]] = add i32 2, [[AVAL]]
-; CHECK-NEXT: [[MUL:%.*]] = mul i32 2, [[BVAL]]
-; CHECK-NEXT: br label [[BLOCK_4:%.*]]
-; CHECK: block_4:
-; CHECK-NEXT: store i32 [[ADD]], ptr [[TMP2:%.*]], align 4
-; CHECK-NEXT: store i32 [[MUL]], ptr [[TMP3:%.*]], align 4
-; CHECK-NEXT: br label [[BLOCK_6_EXITSTUB:%.*]]
-; CHECK: block_5:
-; CHECK-NEXT: store i32 [[ADD2]], ptr [[TMP2]], align 4
-; CHECK-NEXT: store i32 [[MUL2]], ptr [[TMP3]], align 4
-; CHECK-NEXT: br label [[BLOCK_7_EXITSTUB:%.*]]
-; CHECK: block_6.exitStub:
-; CHECK-NEXT: store i32 [[AVAL]], ptr [[TMP6:%.*]], align 4
-; CHECK-NEXT: store i32 [[BVAL]], ptr [[TMP7:%.*]], align 4
-; CHECK-NEXT: ret i1 true
-; CHECK: block_7.exitStub:
-; CHECK-NEXT: store i32 [[A2VAL]], ptr [[TMP4:%.*]], align 4
-; CHECK-NEXT: store i32 [[B2VAL]], ptr [[TMP5:%.*]], align 4
-; CHECK-NEXT: ret i1 false
-;
diff --git a/llvm/test/Transforms/IROutliner/outlining-musttail.ll b/llvm/test/Transforms/IROutliner/outlining-musttail.ll
deleted file mode 100644
index 39f48a096c170..0000000000000
--- a/llvm/test/Transforms/IROutliner/outlining-musttail.ll
+++ /dev/null
@@ -1,34 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --include-generated-funcs
-; RUN: opt -S -passes=verify,iroutliner -ir-outlining-no-cost < %s | FileCheck %s
-
-; Check that we do not outline musttail when swifttaill cc or tailcc
-; is not present.
-
-declare void @musttail()
-
-define void @f1() {
- %a = alloca i32, align 4
- store i32 2, ptr %a, align 4
- musttail call void @musttail()
- ret void
-}
-
-define void @f2() {
- %a = alloca i32, align 4
- store i32 2, ptr %a, align 4
- musttail call void @musttail()
- ret void
-}
-; CHECK-LABEL: @f1(
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: store i32 2, ptr [[A]], align 4
-; CHECK-NEXT: musttail call void @musttail()
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: @f2(
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: store i32 2, ptr [[A]], align 4
-; CHECK-NEXT: musttail call void @musttail()
-; CHECK-NEXT: ret void
-;
diff --git a/llvm/test/Transforms/IROutliner/outlining-no-return-functions.ll b/llvm/test/Transforms/IROutliner/outlining-no-return-functions.ll
deleted file mode 100644
index d2c41376f6b2c..0000000000000
--- a/llvm/test/Transforms/IROutliner/outlining-no-return-functions.ll
+++ /dev/null
@@ -1,54 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --include-generated-funcs
-; RUN: opt -S -passes=verify,iroutliner -ir-outlining-no-cost < %s | FileCheck %s
-
-; Make sure that we outline safely from functions with no return instructions.
-
-; The code extractor will insert return instructions in the outer function
-; due to assumptions about the contents of the outlined region.
-
-define void @f1() {
-bb:
- br label %bb1
-bb1:
- br label %bb1
-}
-
-define void @f2() {
-bb:
- br label %bb1
-bb1:
- br label %bb1
-}
-
-define void @f3() {
-bb:
- br label %bb1
-bb1:
- br label %bb1
-}
-; CHECK-LABEL: @f1(
-; CHECK-NEXT: bb:
-; CHECK-NEXT: call void @outlined_ir_func_0()
-; CHECK-NEXT: unreachable
-;
-;
-; CHECK-LABEL: @f2(
-; CHECK-NEXT: bb:
-; CHECK-NEXT: call void @outlined_ir_func_0()
-; CHECK-NEXT: unreachable
-;
-;
-; CHECK-LABEL: @f3(
-; CHECK-NEXT: bb:
-; CHECK-NEXT: call void @outlined_ir_func_0()
-; CHECK-NEXT: unreachable
-;
-;
-; CHECK-LABEL: define internal void @outlined_ir_func_0(
-; CHECK-NEXT: newFuncRoot:
-; CHECK-NEXT: br label [[BB_TO_OUTLINE:%.*]]
-; CHECK: bb_to_outline:
-; CHECK-NEXT: br label [[BB1:%.*]]
-; CHECK: bb1:
-; CHECK-NEXT: br label [[BB1]]
-;
diff --git a/llvm/test/Transforms/IROutliner/outlining-odr.ll b/llvm/test/Transforms/IROutliner/outlining-odr.ll
deleted file mode 100644
index 6d6277ab6424d..0000000000000
--- a/llvm/test/Transforms/IROutliner/outlining-odr.ll
+++ /dev/null
@@ -1,70 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt -S -passes=verify,iroutliner --ir-outlining-no-cost < %s | FileCheck %s
-; RUN: opt -S -passes=verify,iroutliner -enable-linkonceodr-ir-outlining --ir-outlining-no-cost < %s | FileCheck -check-prefix=ODR %s
-
-; This test looks at the constants in the regions, and if it they are the
-; same it outlines them as constants rather than elevating them to arguments.
-
-define linkonce_odr void @outline_odr1() {
-; ODR-LABEL: @outline_odr1(
-; ODR-NEXT: entry:
-; ODR-NEXT: [[A:%.*]] = alloca i32, align 4
-; ODR-NEXT: [[B:%.*]] = alloca i32, align 4
-; ODR-NEXT: [[C:%.*]] = alloca i32, align 4
-; ODR-NEXT: call void @outlined_ir_func_0(ptr [[A]], ptr [[B]], ptr [[C]])
-; ODR-NEXT: ret void
-; CHECK-LABEL: @outline_odr1(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[C:%.*]] = alloca i32, align 4
-; CHECK-NEXT: store i32 2, ptr [[A]], align 4
-; CHECK-NEXT: store i32 3, ptr [[B]], align 4
-; CHECK-NEXT: store i32 4, ptr [[C]], align 4
-; CHECK-NEXT: [[AL:%.*]] = load i32, ptr [[A]], align 4
-; CHECK-NEXT: [[BL:%.*]] = load i32, ptr [[B]], align 4
-; CHECK-NEXT: [[CL:%.*]] = load i32, ptr [[C]], align 4
-entry:
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- %c = alloca i32, align 4
- store i32 2, ptr %a, align 4
- store i32 3, ptr %b, align 4
- store i32 4, ptr %c, align 4
- %al = load i32, ptr %a
- %bl = load i32, ptr %b
- %cl = load i32, ptr %c
- ret void
-}
-
-define void @outline_odr2() {
-; ODR-LABEL: @outline_odr2(
-; ODR-NEXT: entry:
-; ODR-NEXT: [[A:%.*]] = alloca i32, align 4
-; ODR-NEXT: [[B:%.*]] = alloca i32, align 4
-; ODR-NEXT: [[C:%.*]] = alloca i32, align 4
-; ODR-NEXT: call void @outlined_ir_func_0(ptr [[A]], ptr [[B]], ptr [[C]])
-; ODR-NEXT: ret void
-; CHECK-LABEL: @outline_odr2(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[C:%.*]] = alloca i32, align 4
-; CHECK-NEXT: store i32 2, ptr [[A]], align 4
-; CHECK-NEXT: store i32 3, ptr [[B]], align 4
-; CHECK-NEXT: store i32 4, ptr [[C]], align 4
-; CHECK-NEXT: [[AL:%.*]] = load i32, ptr [[A]], align 4
-; CHECK-NEXT: [[BL:%.*]] = load i32, ptr [[B]], align 4
-; CHECK-NEXT: [[CL:%.*]] = load i32, ptr [[C]], align 4
-entry:
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- %c = alloca i32, align 4
- store i32 2, ptr %a, align 4
- store i32 3, ptr %b, align 4
- store i32 4, ptr %c, align 4
- %al = load i32, ptr %a
- %bl = load i32, ptr %b
- %cl = load i32, ptr %c
- ret void
-}
diff --git a/llvm/test/Transforms/IROutliner/outlining-remapped-outputs.ll b/llvm/test/Transforms/IROutliner/outlining-remapped-outputs.ll
deleted file mode 100644
index 77f17c3162131..0000000000000
--- a/llvm/test/Transforms/IROutliner/outlining-remapped-outputs.ll
+++ /dev/null
@@ -1,70 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt -S -passes=iroutliner -ir-outlining-no-cost < %s | FileCheck %s
-
-; This test tests that inputs that are replaced with the output of an outlined
-; function is still recognized as the same value.
-
-define void @outline_outputs1() #0 {
-; CHECK-LABEL: @outline_outputs1(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[DOTLOC2:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[ADD2_LOC:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[DOTLOC:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[ADD_LOC:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[OUTPUT:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[RESULT:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[OUTPUT2:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[RESULT2:%.*]] = alloca i32, align 4
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[ADD_LOC]])
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[DOTLOC]])
-; CHECK-NEXT: call void @outlined_ir_func_0(i32 2, ptr [[A]], ptr [[B]], ptr [[OUTPUT]], ptr [[ADD_LOC]], ptr [[DOTLOC]])
-; CHECK-NEXT: [[ADD_RELOAD:%.*]] = load i32, ptr [[ADD_LOC]], align 4
-; CHECK-NEXT: [[DOTRELOAD:%.*]] = load i32, ptr [[DOTLOC]], align 4
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[ADD_LOC]])
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[DOTLOC]])
-; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[OUTPUT]], align 4
-; CHECK-NEXT: call void @outlined_ir_func_1(i32 [[DOTRELOAD]], i32 [[ADD_RELOAD]], ptr [[RESULT]])
-; CHECK-NEXT: br label [[NEXT:%.*]]
-; CHECK: next:
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[ADD2_LOC]])
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[DOTLOC2]])
-; CHECK-NEXT: call void @outlined_ir_func_0(i32 [[ADD_RELOAD]], ptr [[OUTPUT]], ptr [[RESULT]], ptr [[OUTPUT2]], ptr [[ADD2_LOC]], ptr [[DOTLOC2]])
-; CHECK-NEXT: [[ADD2_RELOAD:%.*]] = load i32, ptr [[ADD2_LOC]], align 4
-; CHECK-NEXT: [[DOTRELOAD3:%.*]] = load i32, ptr [[DOTLOC2]], align 4
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[ADD2_LOC]])
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[DOTLOC2]])
-; CHECK-NEXT: call void @outlined_ir_func_1(i32 [[DOTRELOAD3]], i32 [[ADD2_RELOAD]], ptr [[RESULT2]])
-; CHECK-NEXT: ret void
-;
-entry:
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- %output = alloca i32, align 4
- %result = alloca i32, align 4
- %output2 = alloca i32, align 4
- %result2 = alloca i32, align 4
- store i32 2, ptr %a, align 4
- store i32 3, ptr %b, align 4
- %0 = load i32, ptr %a, align 4
- %1 = load i32, ptr %b, align 4
- %add = add i32 %0, %1
- store i32 %add, ptr %output, align 4
- %2 = load i32, ptr %output, align 4
- %3 = load i32, ptr %output, align 4
- %mul = mul i32 %2, %add
- store i32 %mul, ptr %result, align 4
- br label %next
-next:
- store i32 %add, ptr %output, align 4
- store i32 3, ptr %result, align 4
- %4 = load i32, ptr %output, align 4
- %5 = load i32, ptr %result, align 4
- %add2 = add i32 %4, %5
- store i32 %add2, ptr %output2, align 4
- %6 = load i32, ptr %output2, align 4
- %mul2 = mul i32 %6, %add2
- store i32 %mul2, ptr %result2, align 4
- ret void
-}
diff --git a/llvm/test/Transforms/IROutliner/outlining-same-constants.ll b/llvm/test/Transforms/IROutliner/outlining-same-constants.ll
deleted file mode 100644
index d2cf221865893..0000000000000
--- a/llvm/test/Transforms/IROutliner/outlining-same-constants.ll
+++ /dev/null
@@ -1,58 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt -S -passes=verify,iroutliner -ir-outlining-no-cost < %s | FileCheck %s
-
-; This test looks at the constants in the regions, and if it they are the
-; same it outlines them as constants rather than elevating them to arguments.
-
-define void @outline_constants1() {
-; CHECK-LABEL: @outline_constants1(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[C:%.*]] = alloca i32, align 4
-; CHECK-NEXT: call void @[[FUNCTION_0:.*]](ptr [[A]], ptr [[B]], ptr [[C]])
-; CHECK-NEXT: ret void
-;
-entry:
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- %c = alloca i32, align 4
- store i32 2, ptr %a, align 4
- store i32 3, ptr %b, align 4
- store i32 4, ptr %c, align 4
- %al = load i32, ptr %a
- %bl = load i32, ptr %b
- %cl = load i32, ptr %c
- ret void
-}
-
-define void @outline_constants2() {
-; CHECK-LABEL: @outline_constants2(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[C:%.*]] = alloca i32, align 4
-; CHECK-NEXT: call void @[[FUNCTION_0]](ptr [[A]], ptr [[B]], ptr [[C]])
-; CHECK-NEXT: ret void
-;
-entry:
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- %c = alloca i32, align 4
- store i32 2, ptr %a, align 4
- store i32 3, ptr %b, align 4
- store i32 4, ptr %c, align 4
- %al = load i32, ptr %a
- %bl = load i32, ptr %b
- %cl = load i32, ptr %c
- ret void
-}
-
-; CHECK: define internal void @[[FUNCTION_0]](ptr [[ARG0:%.*]], ptr [[ARG1:%.*]], ptr [[ARG2:%.*]])
-; CHECK: entry_to_outline:
-; CHECK-NEXT: store i32 2, ptr [[ARG0]], align 4
-; CHECK-NEXT: store i32 3, ptr [[ARG1]], align 4
-; CHECK-NEXT: store i32 4, ptr [[ARG2]], align 4
-; CHECK-NEXT: [[AL:%.*]] = load i32, ptr [[ARG0]], align 4
-; CHECK-NEXT: [[BL:%.*]] = load i32, ptr [[ARG1]], align 4
-; CHECK-NEXT: [[CL:%.*]] = load i32, ptr [[ARG2]], align 4
diff --git a/llvm/test/Transforms/IROutliner/outlining-same-globals.ll b/llvm/test/Transforms/IROutliner/outlining-same-globals.ll
deleted file mode 100644
index b16d743bbde20..0000000000000
--- a/llvm/test/Transforms/IROutliner/outlining-same-globals.ll
+++ /dev/null
@@ -1,41 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt -S -passes=verify,iroutliner -ir-outlining-no-cost < %s | FileCheck %s
-
- at global1 = global i32 1, align 4
- at global2 = global i32 2, align 4
-
-; This test looks at the globals in the regions, and if it they are the
-; same it outlines the region without elevating the globals to arguments.
-
-define void @outline_globals1() {
-; CHECK-LABEL: @outline_globals1(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: call void @outlined_ir_func_0()
-; CHECK-NEXT: ret void
-;
-entry:
- %0 = load i32, ptr @global1
- %1 = load i32, ptr @global2
- %2 = add i32 %0, %1
- ret void
-}
-
-define void @outline_globals2() {
-; CHECK-LABEL: @outline_globals2(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: call void @outlined_ir_func_0()
-; CHECK-NEXT: ret void
-;
-entry:
- %0 = load i32, ptr @global1
- %1 = load i32, ptr @global2
- %2 = add i32 %0, %1
- ret void
-}
-
-; CHECK: define internal void @outlined_ir_func_0()
-; CHECK: entry_to_outline:
-; CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr @global1, align 4
-; CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr @global2, align 4
-; CHECK-NEXT: [[ADD:%.*]] = add i32 [[TMP1]], [[TMP2]]
-
diff --git a/llvm/test/Transforms/IROutliner/outlining-same-output-blocks.ll b/llvm/test/Transforms/IROutliner/outlining-same-output-blocks.ll
deleted file mode 100644
index cc4f6ef6d7e07..0000000000000
--- a/llvm/test/Transforms/IROutliner/outlining-same-output-blocks.ll
+++ /dev/null
@@ -1,94 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt -S -passes=iroutliner -ir-outlining-no-cost < %s | FileCheck %s
-
-; These functions are constructed slightly differently so that they require
-; the same output blocks for the values used outside of the region. We are
-; checking that two output blocks are created with the same store instructions.
-
-define void @outline_outputs1() #0 {
-; CHECK-LABEL: @outline_outputs1(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[DOTLOC:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[ADD_LOC:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[OUTPUT:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[RESULT:%.*]] = alloca i32, align 4
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[ADD_LOC]])
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[DOTLOC]])
-; CHECK-NEXT: call void @outlined_ir_func_0(ptr [[A]], ptr [[B]], ptr [[OUTPUT]], ptr [[ADD_LOC]], ptr [[DOTLOC]])
-; CHECK-NEXT: [[ADD_RELOAD:%.*]] = load i32, ptr [[ADD_LOC]], align 4
-; CHECK-NEXT: [[DOTRELOAD:%.*]] = load i32, ptr [[DOTLOC]], align 4
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[ADD_LOC]])
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[DOTLOC]])
-; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[OUTPUT]], align 4
-; CHECK-NEXT: call void @outlined_ir_func_1(i32 [[DOTRELOAD]], i32 [[ADD_RELOAD]], ptr [[RESULT]])
-; CHECK-NEXT: ret void
-;
-entry:
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- %output = alloca i32, align 4
- %result = alloca i32, align 4
- store i32 2, ptr %a, align 4
- store i32 3, ptr %b, align 4
- %0 = load i32, ptr %a, align 4
- %1 = load i32, ptr %b, align 4
- %add = add i32 %0, %1
- store i32 %add, ptr %output, align 4
- %2 = load i32, ptr %output, align 4
- %3 = load i32, ptr %output, align 4
- %mul = mul i32 %2, %add
- store i32 %mul, ptr %result, align 4
- ret void
-}
-
-define void @outline_outputs2() #0 {
-; CHECK-LABEL: @outline_outputs2(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[DOTLOC:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[ADD_LOC:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[OUTPUT:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[RESULT:%.*]] = alloca i32, align 4
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[ADD_LOC]])
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[DOTLOC]])
-; CHECK-NEXT: call void @outlined_ir_func_0(ptr [[A]], ptr [[B]], ptr [[OUTPUT]], ptr [[ADD_LOC]], ptr [[DOTLOC]])
-; CHECK-NEXT: [[ADD_RELOAD:%.*]] = load i32, ptr [[ADD_LOC]], align 4
-; CHECK-NEXT: [[DOTRELOAD:%.*]] = load i32, ptr [[DOTLOC]], align 4
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[ADD_LOC]])
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[DOTLOC]])
-; CHECK-NEXT: call void @outlined_ir_func_1(i32 [[DOTRELOAD]], i32 [[ADD_RELOAD]], ptr [[RESULT]])
-; CHECK-NEXT: ret void
-;
-entry:
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- %output = alloca i32, align 4
- %result = alloca i32, align 4
- store i32 2, ptr %a, align 4
- store i32 3, ptr %b, align 4
- %0 = load i32, ptr %a, align 4
- %1 = load i32, ptr %b, align 4
- %add = add i32 %0, %1
- store i32 %add, ptr %output, align 4
- %2 = load i32, ptr %output, align 4
- %mul = mul i32 %2, %add
- store i32 %mul, ptr %result, align 4
- ret void
-}
-
-; CHECK: define internal void @outlined_ir_func_0(ptr [[ARG0:%.*]], ptr [[ARG1:%.*]], ptr [[ARG2:%.*]], ptr [[ARG3:%.*]], ptr [[ARG4:%.*]]) #1 {
-; CHECK: entry_to_outline:
-; CHECK-NEXT: store i32 2, ptr [[ARG0]], align 4
-; CHECK-NEXT: store i32 3, ptr [[ARG1]], align 4
-; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[ARG0]], align 4
-; CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[ARG1]], align 4
-; CHECK-NEXT: [[ADD:%.*]] = add i32 [[TMP0]], [[TMP1]]
-; CHECK-NEXT: store i32 [[ADD]], ptr [[ARG2]], align 4
-; CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[ARG2]], align 4
-
-; CHECK: entry_after_outline.exitStub:
-; CHECK-NEXT: store i32 [[ADD]], ptr [[ARG3]], align 4
-; CHECK-NEXT: store i32 [[TMP2]], ptr [[ARG4]], align 4
diff --git a/llvm/test/Transforms/IROutliner/outlining-special-state.ll b/llvm/test/Transforms/IROutliner/outlining-special-state.ll
deleted file mode 100644
index 9ceec51895351..0000000000000
--- a/llvm/test/Transforms/IROutliner/outlining-special-state.ll
+++ /dev/null
@@ -1,163 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --include-generated-funcs
-; RUN: opt -S -passes=verify,iroutliner -ir-outlining-no-cost < %s | FileCheck %s
-
-declare void @foo();
-
-define void @atomicrmw_base(ptr %p) {
-entry:
- %1 = atomicrmw add ptr %p, i32 1 acquire, align 8
- call void @foo()
- ret void
-}
-
-define void @atomicrmw_copy(ptr %p) {
-entry:
- %1 = atomicrmw add ptr %p, i32 1 acquire, align 8
- call void @foo()
- ret void
-}
-
-define void @atomicrmw_wrong_type(ptr %p) {
-entry:
- %1 = atomicrmw add ptr %p, i64 1 acquire, align 8
- call void @foo()
- ret void
-}
-
-define void @atomicrmw_wrong_align(ptr %p) {
-entry:
- %1 = atomicrmw add ptr %p, i32 1 acquire, align 4
- call void @foo()
- ret void
-}
-
-define void @atomicrmw_wrong_volatile(ptr %p) {
-entry:
- %1 = atomicrmw volatile add ptr %p, i32 1 acquire, align 8
- call void @foo()
- ret void
-}
-
-define void @cmpxchg_base(ptr %p) {
-entry:
- %1 = cmpxchg ptr %p, i32 0, i32 1 monotonic monotonic, align 8
- call void @foo()
- ret void
-}
-
-define void @cmpxchg_copy(ptr %p) {
-entry:
- %1 = cmpxchg ptr %p, i32 0, i32 1 monotonic monotonic, align 8
- call void @foo()
- ret void
-}
-
-define void @cmpxchg_wrong_type(ptr %p) {
-entry:
- %1 = cmpxchg ptr %p, i64 0, i64 1 monotonic monotonic, align 8
- call void @foo()
- ret void
-}
-
-define void @cmpxchg_wrong_align(ptr %p) {
-entry:
- %1 = cmpxchg ptr %p, i32 0, i32 1 monotonic monotonic, align 4
- call void @foo()
- ret void
-}
-
-define void @cmpxchg_wrong_volatile(ptr %p) {
-entry:
- %1 = cmpxchg volatile ptr %p, i32 0, i32 1 monotonic monotonic, align 8
- call void @foo()
- ret void
-}
-
-
-; CHECK-LABEL: @atomicrmw_base(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: call void @outlined_ir_func_1(ptr [[P:%.*]])
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: @atomicrmw_copy(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: call void @outlined_ir_func_1(ptr [[P:%.*]])
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: @atomicrmw_wrong_type(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[TMP0:%.*]] = atomicrmw add ptr [[P:%.*]], i64 1 acquire, align 8
-; CHECK-NEXT: call void @foo()
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: @atomicrmw_wrong_align(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[TMP0:%.*]] = atomicrmw add ptr [[P:%.*]], i32 1 acquire, align 4
-; CHECK-NEXT: call void @foo()
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: @atomicrmw_wrong_volatile(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[TMP0:%.*]] = atomicrmw volatile add ptr [[P:%.*]], i32 1 acquire, align 8
-; CHECK-NEXT: call void @foo()
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: @cmpxchg_base(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: call void @outlined_ir_func_0(ptr [[P:%.*]])
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: @cmpxchg_copy(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: call void @outlined_ir_func_0(ptr [[P:%.*]])
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: @cmpxchg_wrong_type(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[TMP0:%.*]] = cmpxchg ptr [[P:%.*]], i64 0, i64 1 monotonic monotonic, align 8
-; CHECK-NEXT: call void @foo()
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: @cmpxchg_wrong_align(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[TMP0:%.*]] = cmpxchg ptr [[P:%.*]], i32 0, i32 1 monotonic monotonic, align 4
-; CHECK-NEXT: call void @foo()
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: @cmpxchg_wrong_volatile(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[TMP0:%.*]] = cmpxchg volatile ptr [[P:%.*]], i32 0, i32 1 monotonic monotonic, align 8
-; CHECK-NEXT: call void @foo()
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: @outlined_ir_func_0(
-; CHECK-NEXT: newFuncRoot:
-; CHECK-NEXT: br label [[ENTRY_TO_OUTLINE:%.*]]
-; CHECK: entry_to_outline:
-; CHECK-NEXT: [[TMP1:%.*]] = cmpxchg ptr [[TMP0:%.*]], i32 0, i32 1 monotonic monotonic, align 8
-; CHECK-NEXT: call void @foo()
-; CHECK-NEXT: br label [[ENTRY_AFTER_OUTLINE_EXITSTUB:%.*]]
-; CHECK: entry_after_outline.exitStub:
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: @outlined_ir_func_1(
-; CHECK-NEXT: newFuncRoot:
-; CHECK-NEXT: br label [[ENTRY_TO_OUTLINE:%.*]]
-; CHECK: entry_to_outline:
-; CHECK-NEXT: [[TMP1:%.*]] = atomicrmw add ptr [[TMP0:%.*]], i32 1 acquire, align 8
-; CHECK-NEXT: call void @foo()
-; CHECK-NEXT: br label [[ENTRY_AFTER_OUTLINE_EXITSTUB:%.*]]
-; CHECK: entry_after_outline.exitStub:
-; CHECK-NEXT: ret void
-;
diff --git a/llvm/test/Transforms/IROutliner/outlining-strip-loop-info.ll b/llvm/test/Transforms/IROutliner/outlining-strip-loop-info.ll
deleted file mode 100644
index 47f3dae91a460..0000000000000
--- a/llvm/test/Transforms/IROutliner/outlining-strip-loop-info.ll
+++ /dev/null
@@ -1,78 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --include-generated-funcs
-; RUN: opt -S -passes=verify,iroutliner -ir-outlining-no-cost < %s | FileCheck %s
-
-; Make sure that we strip loop debug info from instructions that are outlined as
-; well as regular debug info.
-
-define void @ham(i64 %arg0, i64 %arg1) !dbg !1 {
-bb0:
- br label %bb1
-bb1:
- %phi = phi i64 [ 0, %bb0 ], [ %arg1, %bb1 ]
- %icmp = icmp ult i64 %phi, %arg0
- br i1 %icmp, label %bb1, label %bb2, !dbg !7, !llvm.loop !11
-
-bb2:
- ret void
-}
-
-define void @wombat(i64 %arg0, i64 %arg1) !dbg !13 {
-bb0:
- br label %bb1
-bb1:
- %phi = phi i64 [ 0, %bb0 ], [ %arg1, %bb1 ]
- %icmp = icmp ult i64 %phi, %arg0
- br i1 %icmp, label %bb1, label %bb2
-
-bb2:
- ret void
-}
-
-!llvm.module.flags = !{!0}
-!llvm.dbg.cu = !{}
-
-!0 = !{i32 2, !"Debug Info Version", i32 3}
-!1 = distinct !DISubprogram(name: "ham", scope: !2, file: !2, line: 160, type: !3, scopeLine: 161, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !5)
-!2 = !DIFile(filename: "file", directory: "dir")
-!3 = !DISubroutineType(types: !4)
-!4 = !{}
-!5 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !6, producer: "ver", isOptimized: true, runtimeVersion: 0, emissionKind: LineTablesOnly, splitDebugInlining: false, nameTableKind: None, sysroot: "sysroot", sdk: "sdk")
-!6 = !DIFile(filename: "file", directory: "dir")
-!7 = !DILocation(line: 354, column: 13, scope: !8, inlinedAt: !10)
-!8 = distinct !DISubprogram(name: "baz", scope: !9, file: !9, line: 345, type: !3, scopeLine: 346, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !5)
-!9 = !DIFile(filename: "file", directory: "dir")
-!10 = distinct !DILocation(line: 164, column: 15, scope: !1)
-!11 = distinct !{!11, !7, !12}
-!12 = !DILocation(line: 355, column: 37, scope: !8, inlinedAt: !10)
-!13 = distinct !DISubprogram(name: "wombat", scope: !2, file: !2, line: 172, type: !3, scopeLine: 173, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !5)
-!14 = distinct !DISubprogram(name: "bar", scope: !15, file: !15, line: 219, type: !3, scopeLine: 220, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !5)
-!15 = !DIFile(filename: "file", directory: "dir")
-
-; CHECK-LABEL: @ham(
-; CHECK-NEXT: bb0:
-; CHECK-NEXT: call void @outlined_ir_func_0(i64 [[ARG1:%.*]], i64 [[ARG0:%.*]]), !dbg [[DBG6:![0-9]+]]
-; CHECK-NEXT: br label [[BB2:%.*]]
-; CHECK: bb2:
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: @wombat(
-; CHECK-NEXT: bb0:
-; CHECK-NEXT: call void @outlined_ir_func_0(i64 [[ARG1:%.*]], i64 [[ARG0:%.*]]), !dbg [[DBG10:![0-9]+]]
-; CHECK-NEXT: br label [[BB2:%.*]]
-; CHECK: bb2:
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: define internal void @outlined_ir_func_0(
-; CHECK-NEXT: newFuncRoot:
-; CHECK-NEXT: br label [[BB0_TO_OUTLINE:%.*]]
-; CHECK: bb0_to_outline:
-; CHECK-NEXT: br label [[BB1:%.*]]
-; CHECK: bb1:
-; CHECK-NEXT: [[PHI:%.*]] = phi i64 [ 0, [[BB0_TO_OUTLINE]] ], [ [[TMP0:%.*]], [[BB1]] ]
-; CHECK-NEXT: [[ICMP:%.*]] = icmp ult i64 [[PHI]], [[TMP1:%.*]]
-; CHECK-NEXT: br i1 [[ICMP]], label [[BB1]], label [[BB2_EXITSTUB:%.*]], !llvm.loop [[LOOP12:![0-9]+]]
-; CHECK: bb2.exitStub:
-; CHECK-NEXT: ret void
-;
diff --git a/llvm/test/Transforms/IROutliner/outlining-swift-error.ll b/llvm/test/Transforms/IROutliner/outlining-swift-error.ll
deleted file mode 100644
index 68a87a1bc3cb4..0000000000000
--- a/llvm/test/Transforms/IROutliner/outlining-swift-error.ll
+++ /dev/null
@@ -1,44 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt -S -passes=verify,iroutliner -ir-outlining-no-cost < %s | FileCheck %s
-
-%swift.error = type opaque
-
-define void @outlining_swifterror1(ptr swifterror %err) {
-; CHECK-LABEL: @outlining_swifterror1(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[X:%.*]] = alloca i64, align 8
-; CHECK-NEXT: call void @outlined_ir_func_0(i64 5, ptr [[X]], ptr swifterror [[ERR:%.*]])
-; CHECK-NEXT: ret void
-;
-entry:
- %x = alloca i64
- %0 = mul i64 5, 5
- %1 = add i64 %0, %0
- store i64 %1, ptr %x
- store ptr %x, ptr %err
- ret void
-}
-
-define void @outlining_swifterror2(ptr swifterror %err) {
-; CHECK-LABEL: @outlining_swifterror2(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[X:%.*]] = alloca i64, align 8
-; CHECK-NEXT: call void @outlined_ir_func_0(i64 3, ptr [[X]], ptr swifterror [[ERR:%.*]])
-; CHECK-NEXT: ret void
-;
-entry:
- %x = alloca i64
- %0 = mul i64 3, 3
- %1 = add i64 %0, %0
- store i64 %1, ptr %x
- store ptr %x, ptr %err
- ret void
-}
-
-; CHECK: define internal void @outlined_ir_func_0(i64 [[ARG0:%.*]], ptr [[ARG1:%.*]], ptr swifterror [[ARG2:%.*]])
-; CHECK: entry_to_outline:
-; CHECK-NEXT: [[TMP0:%.*]] = mul i64 [[ARG0]], [[ARG0]]
-; CHECK-NEXT: [[TMP1:%.*]] = add i64 [[TMP0]], [[TMP0]]
-; CHECK-NEXT: store i64 [[TMP1]], ptr [[ARG1]], align 4
-; CHECK-NEXT: store ptr [[ARG1]], ptr [[ARG2]], align 8
-; CHECK-NEXT: br label %entry_after_outline.exitStub
diff --git a/llvm/test/Transforms/IROutliner/outlining-swifttailcc.ll b/llvm/test/Transforms/IROutliner/outlining-swifttailcc.ll
deleted file mode 100644
index 48cc128ad68de..0000000000000
--- a/llvm/test/Transforms/IROutliner/outlining-swifttailcc.ll
+++ /dev/null
@@ -1,33 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --include-generated-funcs
-; RUN: opt -S -passes=verify,iroutliner -ir-outlining-no-cost < %s | FileCheck %s
-
-; Check that we do not outline musttail calls when swifttailcc is present.
-
-declare swifttailcc void @musttail()
-
-define swifttailcc void @f1() {
- %a = alloca i32, align 4
- store i32 2, ptr %a, align 4
- musttail call swifttailcc void @musttail()
- ret void
-}
-
-define swifttailcc void @f2() {
- %a = alloca i32, align 4
- store i32 2, ptr %a, align 4
- musttail call swifttailcc void @musttail()
- ret void
-}
-; CHECK-LABEL: @f1(
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: store i32 2, ptr [[A]], align 4
-; CHECK-NEXT: musttail call swifttailcc void @musttail()
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: @f2(
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: store i32 2, ptr [[A]], align 4
-; CHECK-NEXT: musttail call swifttailcc void @musttail()
-; CHECK-NEXT: ret void
-;
diff --git a/llvm/test/Transforms/IROutliner/outlining-tailcc.ll b/llvm/test/Transforms/IROutliner/outlining-tailcc.ll
deleted file mode 100644
index 17ca8df4c67f0..0000000000000
--- a/llvm/test/Transforms/IROutliner/outlining-tailcc.ll
+++ /dev/null
@@ -1,33 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --include-generated-funcs
-; RUN: opt -S -passes=verify,iroutliner -ir-outlining-no-cost < %s | FileCheck %s
-
-; Check that we not do outline musttail calls when tailcc is present.
-
-declare tailcc void @musttail()
-
-define tailcc void @f1() {
- %a = alloca i32, align 4
- store i32 2, ptr %a, align 4
- musttail call tailcc void @musttail()
- ret void
-}
-
-define tailcc void @f2() {
- %a = alloca i32, align 4
- store i32 2, ptr %a, align 4
- musttail call tailcc void @musttail()
- ret void
-}
-; CHECK-LABEL: @f1(
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: store i32 2, ptr [[A]], align 4
-; CHECK-NEXT: musttail call tailcc void @musttail()
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: @f2(
-; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
-; CHECK-NEXT: store i32 2, ptr [[A]], align 4
-; CHECK-NEXT: musttail call tailcc void @musttail()
-; CHECK-NEXT: ret void
-;
diff --git a/llvm/test/Transforms/IROutliner/phi-node-exit-path-order.ll b/llvm/test/Transforms/IROutliner/phi-node-exit-path-order.ll
deleted file mode 100644
index 15d313a41bf7c..0000000000000
--- a/llvm/test/Transforms/IROutliner/phi-node-exit-path-order.ll
+++ /dev/null
@@ -1,120 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --include-generated-funcs
-; RUN: opt -S -passes=verify,iroutliner -ir-outlining-no-cost < %s | FileCheck %s
-
-; A PHINode defines the global value number of a split phi node for
-; an exit paths based on the canonical number for the incoming values, and
-; the canonical number for the basic block. This checks that we accurately
-; capture a different numbering for the same incoming value but with different
-; blocks.
-
-define void @func1(i32 %0, i32 %1) local_unnamed_addr #0 {
-bb1:
- br label %bb5
-
-bb2:
- %a = add i32 %0, %1
- %b = add i32 %0, %1
- %c = icmp eq i32 %b, 1
- br i1 %c, label %bb5, label %bb3
-
-bb3:
- %d = add i32 %0, %1
- br label %bb5
-
-bb4:
- %e = sub i32 %0, %1
- br label %bb2
-
-bb5:
- %f = phi i32 [ 0, %bb1 ], [ 1, %bb2 ], [ 1, %bb3 ]
- ret void
-}
-
-define void @func2(i32 %0, i32 %1) local_unnamed_addr #0 {
-bb1:
- br label %bb5
-
-bb2:
- %a = sub i32 %0, %1
- %b = add i32 %0, %1
- %c = icmp eq i32 %b, 1
- br i1 %c, label %bb5, label %bb3
-
-bb3:
- %d = add i32 %0, %1
- br label %bb5
-
-bb4:
- %e = add i32 %0, %1
- br label %bb2
-
-bb5:
- %f = phi i32 [ 0, %bb1 ], [ 1, %bb3 ], [ 1, %bb2 ]
- ret void
-}
-; CHECK-LABEL: @func1(
-; CHECK-NEXT: bb1:
-; CHECK-NEXT: [[F_CE_LOC:%.*]] = alloca i32, align 4
-; CHECK-NEXT: br label [[BB5:%.*]]
-; CHECK: bb2:
-; CHECK-NEXT: [[A:%.*]] = add i32 [[TMP0:%.*]], [[TMP1:%.*]]
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[F_CE_LOC]])
-; CHECK-NEXT: call void @outlined_ir_func_0(i32 [[TMP0]], i32 [[TMP1]], ptr [[F_CE_LOC]], i32 0)
-; CHECK-NEXT: [[F_CE_RELOAD:%.*]] = load i32, ptr [[F_CE_LOC]], align 4
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[F_CE_LOC]])
-; CHECK-NEXT: br label [[BB5]]
-; CHECK: bb4:
-; CHECK-NEXT: [[E:%.*]] = sub i32 [[TMP0]], [[TMP1]]
-; CHECK-NEXT: br label [[BB2:%.*]]
-; CHECK: bb5:
-; CHECK-NEXT: [[F:%.*]] = phi i32 [ 0, [[BB1:%.*]] ], [ [[F_CE_RELOAD]], [[BB2]] ]
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: @func2(
-; CHECK-NEXT: bb1:
-; CHECK-NEXT: [[F_CE_LOC:%.*]] = alloca i32, align 4
-; CHECK-NEXT: br label [[BB5:%.*]]
-; CHECK: bb2:
-; CHECK-NEXT: [[A:%.*]] = sub i32 [[TMP0:%.*]], [[TMP1:%.*]]
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[F_CE_LOC]])
-; CHECK-NEXT: call void @outlined_ir_func_0(i32 [[TMP0]], i32 [[TMP1]], ptr [[F_CE_LOC]], i32 1)
-; CHECK-NEXT: [[F_CE_RELOAD:%.*]] = load i32, ptr [[F_CE_LOC]], align 4
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[F_CE_LOC]])
-; CHECK-NEXT: br label [[BB5]]
-; CHECK: bb4:
-; CHECK-NEXT: [[E:%.*]] = add i32 [[TMP0]], [[TMP1]]
-; CHECK-NEXT: br label [[BB2:%.*]]
-; CHECK: bb5:
-; CHECK-NEXT: [[F:%.*]] = phi i32 [ 0, [[BB1:%.*]] ], [ [[F_CE_RELOAD]], [[BB2]] ]
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: define internal void @outlined_ir_func_0(
-; CHECK-NEXT: newFuncRoot:
-; CHECK-NEXT: br label [[BB2_TO_OUTLINE:%.*]]
-; CHECK: bb2_to_outline:
-; CHECK-NEXT: [[B:%.*]] = add i32 [[TMP0:%.*]], [[TMP1:%.*]]
-; CHECK-NEXT: [[C:%.*]] = icmp eq i32 [[B]], 1
-; CHECK-NEXT: br i1 [[C]], label [[BB5_SPLIT:%.*]], label [[BB3:%.*]]
-; CHECK: bb3:
-; CHECK-NEXT: [[D:%.*]] = add i32 [[TMP0]], [[TMP1]]
-; CHECK-NEXT: br label [[BB5_SPLIT]]
-; CHECK: bb5.split:
-; CHECK-NEXT: [[TMP4:%.*]] = phi i32 [ 1, [[BB3]] ], [ 1, [[BB2_TO_OUTLINE]] ]
-; CHECK-NEXT: [[F_CE:%.*]] = phi i32 [ 1, [[BB2_TO_OUTLINE]] ], [ 1, [[BB3]] ]
-; CHECK-NEXT: br label [[BB5_EXITSTUB:%.*]]
-; CHECK: bb5.exitStub:
-; CHECK-NEXT: switch i32 [[TMP3:%.*]], label [[FINAL_BLOCK_0:%.*]] [
-; CHECK-NEXT: i32 0, label [[OUTPUT_BLOCK_0_0:%.*]]
-; CHECK-NEXT: i32 1, label [[OUTPUT_BLOCK_1_0:%.*]]
-; CHECK-NEXT: ]
-; CHECK: output_block_0_0:
-; CHECK-NEXT: store i32 [[F_CE]], ptr [[TMP2:%.*]], align 4
-; CHECK-NEXT: br label [[FINAL_BLOCK_0]]
-; CHECK: output_block_1_0:
-; CHECK-NEXT: store i32 [[TMP4]], ptr [[TMP2]], align 4
-; CHECK-NEXT: br label [[FINAL_BLOCK_0]]
-; CHECK: final_block_0:
-; CHECK-NEXT: ret void
-;
diff --git a/llvm/test/Transforms/IROutliner/phi-nodes-non-constant.ll b/llvm/test/Transforms/IROutliner/phi-nodes-non-constant.ll
deleted file mode 100644
index 5fc8684e2bd88..0000000000000
--- a/llvm/test/Transforms/IROutliner/phi-nodes-non-constant.ll
+++ /dev/null
@@ -1,74 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --include-generated-funcs
-; RUN: opt -S -passes=verify,iroutliner -ir-outlining-no-cost < %s | FileCheck %s
-
-; Show that we do extract phi nodes from the regions.
-
-define void @function1(ptr %a, ptr %b) {
-entry:
- %0 = alloca i32, align 4
- %c = load i32, ptr %0, align 4
- br label %test1
-test1:
- %e = load i32, ptr %0, align 4
- br label %first
-test:
- %d = load i32, ptr %0, align 4
- br label %first
-first:
- %1 = phi i32 [ %c, %test ], [ %e, %test1 ]
- store i32 2, ptr %a, align 4
- store i32 3, ptr %b, align 4
- ret void
-}
-
-define void @function2(ptr %a, ptr %b) {
-entry:
- %0 = alloca i32, align 4
- %c = load i32, ptr %0, align 4
- br label %test1
-test1:
- %e = load i32, ptr %0, align 4
- br label %first
-test:
- %d = load i32, ptr %0, align 4
- br label %first
-first:
- %1 = phi i32 [ %c, %test ], [ %e, %test1 ]
- store i32 2, ptr %a, align 4
- store i32 3, ptr %b, align 4
- ret void
-}
-; CHECK-LABEL: @function1(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[TMP0:%.*]] = alloca i32, align 4
-; CHECK-NEXT: call void @outlined_ir_func_0(ptr [[TMP0]], ptr [[A:%.*]], ptr [[B:%.*]])
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: @function2(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[TMP0:%.*]] = alloca i32, align 4
-; CHECK-NEXT: call void @outlined_ir_func_0(ptr [[TMP0]], ptr [[A:%.*]], ptr [[B:%.*]])
-; CHECK-NEXT: ret void
-;
-;
-; CHECK: define internal void @outlined_ir_func_0(
-; CHECK-NEXT: newFuncRoot:
-; CHECK-NEXT: br label [[ENTRY_TO_OUTLINE:%.*]]
-; CHECK: entry_to_outline:
-; CHECK-NEXT: [[C:%.*]] = load i32, ptr [[TMP0:%.*]], align 4
-; CHECK-NEXT: br label [[TEST1:%.*]]
-; CHECK: test1:
-; CHECK-NEXT: [[E:%.*]] = load i32, ptr [[TMP0]], align 4
-; CHECK-NEXT: br label [[FIRST:%.*]]
-; CHECK: test:
-; CHECK-NEXT: [[D:%.*]] = load i32, ptr [[TMP0]], align 4
-; CHECK-NEXT: br label [[FIRST]]
-; CHECK: first:
-; CHECK-NEXT: [[TMP3:%.*]] = phi i32 [ [[C]], [[TEST:%.*]] ], [ [[E]], [[TEST1]] ]
-; CHECK-NEXT: store i32 2, ptr [[TMP1:%.*]], align 4
-; CHECK-NEXT: store i32 3, ptr [[TMP2:%.*]], align 4
-; CHECK-NEXT: br label [[ENTRY_AFTER_OUTLINE_EXITSTUB:%.*]]
-; CHECK: entry_after_outline.exitStub:
-; CHECK-NEXT: ret void
-;
diff --git a/llvm/test/Transforms/IROutliner/phi-nodes-output-overload.ll b/llvm/test/Transforms/IROutliner/phi-nodes-output-overload.ll
deleted file mode 100644
index 9e443abaaff50..0000000000000
--- a/llvm/test/Transforms/IROutliner/phi-nodes-output-overload.ll
+++ /dev/null
@@ -1,110 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --include-generated-funcs
-; RUN: opt -S -passes=verify,iroutliner -ir-outlining-no-cost < %s | FileCheck %s
-
-; Show that we do not extract similar regions that would involve the splitting
-; of phi nodes on exit.
-
-define void @function1(ptr %a, ptr %b) {
-entry:
- %0 = alloca i32, align 4
- %c = load i32, ptr %0, align 4
- br label %test1
-test1:
- %e = load i32, ptr %0, align 4
- br i1 true, label %first, label %next
-test:
- %d = load i32, ptr %0, align 4
- br i1 true, label %first, label %next
-first:
- %1 = phi i32 [ %c, %test ], [ %e, %test1 ]
- ret void
-next:
- ret void
-}
-
-define void @function2(ptr %a, ptr %b) {
-entry:
- %0 = alloca i32, align 4
- %c = load i32, ptr %0, align 4
- br label %test1
-test1:
- %e = load i32, ptr %0, align 4
- br i1 true, label %first, label %next
-test:
- %d = load i32, ptr %0, align 4
- br i1 true, label %first, label %next
-first:
- ret void
-next:
- %1 = phi i32 [ %c, %test ], [ %e, %test1 ]
- ret void
-}
-; CHECK-LABEL: @function1(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[DOTCE_LOC:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[TMP0:%.*]] = alloca i32, align 4
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[DOTCE_LOC]])
-; CHECK-NEXT: [[TMP1:%.*]] = call i1 @outlined_ir_func_0(ptr [[TMP0]], ptr [[DOTCE_LOC]], i32 0)
-; CHECK-NEXT: [[DOTCE_RELOAD:%.*]] = load i32, ptr [[DOTCE_LOC]], align 4
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[DOTCE_LOC]])
-; CHECK-NEXT: br i1 [[TMP1]], label [[FIRST:%.*]], label [[NEXT:%.*]]
-; CHECK: first:
-; CHECK-NEXT: [[TMP2:%.*]] = phi i32 [ [[DOTCE_RELOAD]], [[ENTRY:%.*]] ]
-; CHECK-NEXT: ret void
-; CHECK: next:
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: @function2(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[DOTCE_LOC:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[TMP0:%.*]] = alloca i32, align 4
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[DOTCE_LOC]])
-; CHECK-NEXT: [[TMP1:%.*]] = call i1 @outlined_ir_func_0(ptr [[TMP0]], ptr [[DOTCE_LOC]], i32 1)
-; CHECK-NEXT: [[DOTCE_RELOAD:%.*]] = load i32, ptr [[DOTCE_LOC]], align 4
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[DOTCE_LOC]])
-; CHECK-NEXT: br i1 [[TMP1]], label [[FIRST:%.*]], label [[NEXT:%.*]]
-; CHECK: first:
-; CHECK-NEXT: ret void
-; CHECK: next:
-; CHECK-NEXT: [[TMP2:%.*]] = phi i32 [ [[DOTCE_RELOAD]], [[ENTRY:%.*]] ]
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: define internal i1 @outlined_ir_func_0(
-; CHECK-NEXT: newFuncRoot:
-; CHECK-NEXT: br label [[ENTRY_TO_OUTLINE:%.*]]
-; CHECK: entry_to_outline:
-; CHECK-NEXT: [[C:%.*]] = load i32, ptr [[TMP0:%.*]], align 4
-; CHECK-NEXT: br label [[TEST1:%.*]]
-; CHECK: test1:
-; CHECK-NEXT: [[E:%.*]] = load i32, ptr [[TMP0]], align 4
-; CHECK-NEXT: br i1 true, label [[FIRST_SPLIT:%.*]], label [[PHI_BLOCK:%.*]]
-; CHECK: test:
-; CHECK-NEXT: [[D:%.*]] = load i32, ptr [[TMP0]], align 4
-; CHECK-NEXT: br i1 true, label [[FIRST_SPLIT]], label [[PHI_BLOCK]]
-; CHECK: first.split:
-; CHECK-NEXT: [[DOTCE:%.*]] = phi i32 [ [[C]], [[TEST:%.*]] ], [ [[E]], [[TEST1]] ]
-; CHECK-NEXT: br label [[FIRST_EXITSTUB:%.*]]
-; CHECK: first.exitStub:
-; CHECK-NEXT: switch i32 [[TMP2:%.*]], label [[FINAL_BLOCK_1:%.*]] [
-; CHECK-NEXT: i32 0, label [[OUTPUT_BLOCK_0_1:%.*]]
-; CHECK-NEXT: ]
-; CHECK: next.exitStub:
-; CHECK-NEXT: switch i32 [[TMP2]], label [[FINAL_BLOCK_0:%.*]] [
-; CHECK-NEXT: i32 0, label [[OUTPUT_BLOCK_1_0:%.*]]
-; CHECK-NEXT: ]
-; CHECK: output_block_0_1:
-; CHECK-NEXT: store i32 [[DOTCE]], ptr [[TMP1:%.*]], align 4
-; CHECK-NEXT: br label [[FINAL_BLOCK_1]]
-; CHECK: output_block_1_0:
-; CHECK-NEXT: store i32 [[TMP3:%.*]], ptr [[TMP1]], align 4
-; CHECK-NEXT: br label [[FINAL_BLOCK_0]]
-; CHECK: phi_block:
-; CHECK-NEXT: [[TMP3]] = phi i32 [ [[C]], [[TEST]] ], [ [[E]], [[TEST1]] ]
-; CHECK-NEXT: br label [[NEXT_EXITSTUB:%.*]]
-; CHECK: final_block_0:
-; CHECK-NEXT: ret i1 false
-; CHECK: final_block_1:
-; CHECK-NEXT: ret i1 true
-;
diff --git a/llvm/test/Transforms/IROutliner/phi-nodes-parent-block-referential.ll b/llvm/test/Transforms/IROutliner/phi-nodes-parent-block-referential.ll
deleted file mode 100644
index 02930d77be3a8..0000000000000
--- a/llvm/test/Transforms/IROutliner/phi-nodes-parent-block-referential.ll
+++ /dev/null
@@ -1,98 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --include-generated-funcs
-; RUN: opt -S -passes=verify,iroutliner -ir-outlining-no-cost < %s | FileCheck %s
-
-; Show that we do not outline when all of the phi nodes in the beginning
-; block are included not in the region.
-
-define void @function1(ptr %a, ptr %b) {
-entry:
- %0 = alloca i32, align 4
- %c = load i32, ptr %0, align 4
- %y = add i32 %c, %c
- br label %test1
-dummy:
- ret void
-test1:
- %1 = phi i32 [ %e, %test1 ], [ %y, %entry ]
- %2 = phi i32 [ %e, %test1 ], [ %y, %entry ]
- %e = load i32, ptr %0, align 4
- %3 = add i32 %c, %c
- %4 = sub i32 %c, %c
- br i1 true, label %first, label %test1
-first:
- ret void
-}
-
-define void @function2(ptr %a, ptr %b) {
-entry:
- %0 = alloca i32, align 4
- %c = load i32, ptr %0, align 4
- %y = mul i32 %c, %c
- br label %test1
-dummy:
- ret void
-test1:
- %1 = phi i32 [ %e, %test1 ], [ %y, %entry ]
- %2 = phi i32 [ %y, %entry ], [ %e, %test1 ]
- %e = load i32, ptr %0, align 4
- %3 = add i32 %c, %c
- %4 = mul i32 %c, %c
- br i1 true, label %first, label %test1
-first:
- ret void
-}
-; CHECK-LABEL: @function1(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[E_LOC:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[TMP0:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[C:%.*]] = load i32, ptr [[TMP0]], align 4
-; CHECK-NEXT: [[Y:%.*]] = add i32 [[C]], [[C]]
-; CHECK-NEXT: br label [[TEST1:%.*]]
-; CHECK: dummy:
-; CHECK-NEXT: ret void
-; CHECK: test1:
-; CHECK-NEXT: [[TMP1:%.*]] = phi i32 [ [[E_RELOAD:%.*]], [[TEST1]] ], [ [[Y]], [[ENTRY:%.*]] ]
-; CHECK-NEXT: [[TMP2:%.*]] = phi i32 [ [[E_RELOAD]], [[TEST1]] ], [ [[Y]], [[ENTRY]] ]
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[E_LOC]])
-; CHECK-NEXT: call void @outlined_ir_func_0(ptr [[TMP0]], i32 [[C]], ptr [[E_LOC]])
-; CHECK-NEXT: [[E_RELOAD]] = load i32, ptr [[E_LOC]], align 4
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[E_LOC]])
-; CHECK-NEXT: [[TMP3:%.*]] = sub i32 [[C]], [[C]]
-; CHECK-NEXT: br i1 true, label [[FIRST:%.*]], label [[TEST1]]
-; CHECK: first:
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: @function2(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[E_LOC:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[TMP0:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[C:%.*]] = load i32, ptr [[TMP0]], align 4
-; CHECK-NEXT: [[Y:%.*]] = mul i32 [[C]], [[C]]
-; CHECK-NEXT: br label [[TEST1:%.*]]
-; CHECK: dummy:
-; CHECK-NEXT: ret void
-; CHECK: test1:
-; CHECK-NEXT: [[TMP1:%.*]] = phi i32 [ [[E_RELOAD:%.*]], [[TEST1]] ], [ [[Y]], [[ENTRY:%.*]] ]
-; CHECK-NEXT: [[TMP2:%.*]] = phi i32 [ [[Y]], [[ENTRY]] ], [ [[E_RELOAD]], [[TEST1]] ]
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[E_LOC]])
-; CHECK-NEXT: call void @outlined_ir_func_0(ptr [[TMP0]], i32 [[C]], ptr [[E_LOC]])
-; CHECK-NEXT: [[E_RELOAD]] = load i32, ptr [[E_LOC]], align 4
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[E_LOC]])
-; CHECK-NEXT: [[TMP3:%.*]] = mul i32 [[C]], [[C]]
-; CHECK-NEXT: br i1 true, label [[FIRST:%.*]], label [[TEST1]]
-; CHECK: first:
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: define internal void @outlined_ir_func_0(
-; CHECK-NEXT: newFuncRoot:
-; CHECK-NEXT: br label [[TEST1_TO_OUTLINE:%.*]]
-; CHECK: test1_to_outline:
-; CHECK-NEXT: [[E:%.*]] = load i32, ptr [[TMP0:%.*]], align 4
-; CHECK-NEXT: [[TMP3:%.*]] = add i32 [[TMP1:%.*]], [[TMP1]]
-; CHECK-NEXT: br label [[TEST1_AFTER_OUTLINE_EXITSTUB:%.*]]
-; CHECK: test1_after_outline.exitStub:
-; CHECK-NEXT: store i32 [[E]], ptr [[TMP2:%.*]], align 4
-; CHECK-NEXT: ret void
-;
diff --git a/llvm/test/Transforms/IROutliner/phi-nodes-simple.ll b/llvm/test/Transforms/IROutliner/phi-nodes-simple.ll
deleted file mode 100644
index 31cfe2ccea952..0000000000000
--- a/llvm/test/Transforms/IROutliner/phi-nodes-simple.ll
+++ /dev/null
@@ -1,56 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --include-generated-funcs
-; RUN: opt -S -passes=verify,iroutliner -ir-outlining-no-cost < %s | FileCheck %s
-
-; Show that we are able to outline the simple phi node case of constants when
-; the corresponding labels match.
-
-define void @function1(ptr %a, ptr %b) {
-entry:
- br label %test
-test:
- br label %first
-first:
- %0 = phi i32 [ 0, %test ]
- store i32 2, ptr %a, align 4
- store i32 3, ptr %b, align 4
- ret void
-}
-
-define void @function2(ptr %a, ptr %b) {
-entry:
- br label %test
-test:
- br label %first
-first:
- %0 = phi i32 [ 0, %test ]
- store i32 2, ptr %a, align 4
- store i32 3, ptr %b, align 4
- ret void
-}
-; CHECK-LABEL: @function1(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: call void @outlined_ir_func_0(ptr [[A:%.*]], ptr [[B:%.*]])
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: @function2(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: call void @outlined_ir_func_0(ptr [[A:%.*]], ptr [[B:%.*]])
-; CHECK-NEXT: ret void
-;
-;
-; CHECK: define internal void @outlined_ir_func_0(
-; CHECK-NEXT: newFuncRoot:
-; CHECK-NEXT: br label [[ENTRY_TO_OUTLINE:%.*]]
-; CHECK: entry_to_outline:
-; CHECK-NEXT: br label [[TEST:%.*]]
-; CHECK: test:
-; CHECK-NEXT: br label [[FIRST:%.*]]
-; CHECK: first:
-; CHECK-NEXT: [[TMP2:%.*]] = phi i32 [ 0, [[TEST]] ]
-; CHECK-NEXT: store i32 2, ptr [[TMP0:%.*]], align 4
-; CHECK-NEXT: store i32 3, ptr [[TMP1:%.*]], align 4
-; CHECK-NEXT: br label [[ENTRY_AFTER_OUTLINE_EXITSTUB:%.*]]
-; CHECK: entry_after_outline.exitStub:
-; CHECK-NEXT: ret void
-;
diff --git a/llvm/test/Transforms/IROutliner/region-end-of-module.ll b/llvm/test/Transforms/IROutliner/region-end-of-module.ll
deleted file mode 100644
index 2ad16078eed27..0000000000000
--- a/llvm/test/Transforms/IROutliner/region-end-of-module.ll
+++ /dev/null
@@ -1,112 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --include-generated-funcs
-; RUN: opt -S -passes=verify,iroutliner -ir-outlining-no-cost < %s | FileCheck %s
-
-; This test checks that we do not fail when there is a similarity group with
-; an ending instruction that is also the end of the module.
-
- at a = global ptr null
-
-define void @foo() {
-entry:
- br label %for.cond1
-
-for.cond1:
- br label %for.body
-
-for.body:
- %inc = add nsw i32 2, 1
- br label %for.cond1
-
-for.end:
- %inc3 = add nsw i32 2, 1
- br label %for.cond1
-}
-
-; These are for testing if return instructions or unreachable instructions are
-; matched for similarity.
-define void @foo1() {
-entry:
- br label %for.cond1
-
-for.cond1:
- br label %for.body
-
-for.body:
- %inc = add nsw i32 2, 1
- ret void
-
-for.end:
- %inc3 = add nsw i32 2, 1
- ret void
-}
-
-define void @foo2() {
-entry:
- br label %for.cond1
-
-for.cond1:
- br label %for.body
-
-for.body:
- %inc = add nsw i32 2, 1
- unreachable
-
-for.end:
- %inc3 = add nsw i32 2, 1
- unreachable
-}
-
-; CHECK-LABEL: @foo(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: br label [[FOR_COND1:%.*]]
-; CHECK: for.cond1:
-; CHECK-NEXT: br label [[FOR_BODY:%.*]]
-; CHECK: for.body:
-; CHECK-NEXT: call void @outlined_ir_func_1()
-; CHECK-NEXT: br label [[FOR_COND1]]
-; CHECK: for.end:
-; CHECK-NEXT: call void @outlined_ir_func_1()
-; CHECK-NEXT: br label [[FOR_COND1]]
-;
-;
-; CHECK-LABEL: @foo1(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: call void @outlined_ir_func_0()
-; CHECK-NEXT: ret void
-; CHECK: for.end:
-; CHECK-NEXT: [[INC3:%.*]] = add nsw i32 2, 1
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: @foo2(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: call void @outlined_ir_func_0()
-; CHECK-NEXT: unreachable
-; CHECK: for.end:
-; CHECK-NEXT: [[INC3:%.*]] = add nsw i32 2, 1
-; CHECK-NEXT: unreachable
-;
-;
-; CHECK: define internal void @outlined_ir_func_0(
-; CHECK-NEXT: newFuncRoot:
-; CHECK-NEXT: br label [[ENTRY_TO_OUTLINE:%.*]]
-; CHECK: entry_to_outline:
-; CHECK-NEXT: br label [[FOR_COND1:%.*]]
-; CHECK: for.cond1:
-; CHECK-NEXT: br label [[FOR_BODY:%.*]]
-; CHECK: for.body:
-; CHECK-NEXT: [[INC:%.*]] = add nsw i32 2, 1
-; CHECK-NEXT: br label [[ENTRY_AFTER_OUTLINE_EXITSTUB:%.*]]
-; CHECK: entry_after_outline.exitStub:
-; CHECK-NEXT: ret void
-;
-;
-; CHECK: define internal void @outlined_ir_func_1(
-; CHECK-NEXT: newFuncRoot:
-; CHECK-NEXT: br label [[FOR_BODY_TO_OUTLINE:%.*]]
-; CHECK: for.body_to_outline:
-; CHECK-NEXT: [[INC:%.*]] = add nsw i32 2, 1
-; CHECK-NEXT: br label [[FOR_COND1_EXITSTUB:%.*]]
-; CHECK: for.cond1.exitStub:
-; CHECK-NEXT: ret void
-;
diff --git a/llvm/test/Transforms/IROutliner/region-inputs-in-phi-nodes.ll b/llvm/test/Transforms/IROutliner/region-inputs-in-phi-nodes.ll
deleted file mode 100644
index 25b1e8ee29f3c..0000000000000
--- a/llvm/test/Transforms/IROutliner/region-inputs-in-phi-nodes.ll
+++ /dev/null
@@ -1,110 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --include-generated-funcs
-; RUN: opt -S -passes=verify,iroutliner -ir-outlining-no-cost < %s | FileCheck %s
-
-; Show that we are able to propagate inputs to the region into the split PHINode
-; outside of the region if necessary.
-
-define void @function1(ptr %a, ptr %b) {
-entry:
- %0 = alloca i32, align 4
- %c = load i32, ptr %0, align 4
- %z = add i32 %c, %c
- br i1 true, label %test1, label %first
-test1:
- %e = load i32, ptr %0, align 4
- %1 = add i32 %c, %c
- br i1 true, label %first, label %test
-test:
- %d = load i32, ptr %0, align 4
- br i1 true, label %first, label %next
-dummy:
- ret void
-first:
- %2 = phi i32 [ %d, %test ], [ %e, %test1 ], [ %c, %entry ]
- ret void
-next:
- ret void
-}
-
-define void @function2(ptr %a, ptr %b) {
-entry:
- %0 = alloca i32, align 4
- %c = load i32, ptr %0, align 4
- %z = mul i32 %c, %c
- br i1 true, label %test1, label %first
-test1:
- %e = load i32, ptr %0, align 4
- %1 = add i32 %c, %c
- br i1 true, label %first, label %test
-test:
- %d = load i32, ptr %0, align 4
- br i1 true, label %first, label %next
-dummy:
- ret void
-first:
- %2 = phi i32 [ %d, %test ], [ %e, %test1 ], [ %c, %entry ]
- ret void
-next:
- ret void
-}
-; CHECK-LABEL: @function1(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[DOTCE_LOC:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[TMP0:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[C:%.*]] = load i32, ptr [[TMP0]], align 4
-; CHECK-NEXT: [[Z:%.*]] = add i32 [[C]], [[C]]
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[DOTCE_LOC]])
-; CHECK-NEXT: [[TARGETBLOCK:%.*]] = call i1 @outlined_ir_func_0(ptr [[TMP0]], i32 [[C]], ptr [[DOTCE_LOC]])
-; CHECK-NEXT: [[DOTCE_RELOAD:%.*]] = load i32, ptr [[DOTCE_LOC]], align 4
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[DOTCE_LOC]])
-; CHECK-NEXT: br i1 [[TARGETBLOCK]], label [[FIRST:%.*]], label [[NEXT:%.*]]
-; CHECK: dummy:
-; CHECK-NEXT: ret void
-; CHECK: first:
-; CHECK-NEXT: [[TMP1:%.*]] = phi i32 [ [[DOTCE_RELOAD]], [[ENTRY:%.*]] ]
-; CHECK-NEXT: ret void
-; CHECK: next:
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: @function2(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[DOTCE_LOC:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[TMP0:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[C:%.*]] = load i32, ptr [[TMP0]], align 4
-; CHECK-NEXT: [[Z:%.*]] = mul i32 [[C]], [[C]]
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[DOTCE_LOC]])
-; CHECK-NEXT: [[TARGETBLOCK:%.*]] = call i1 @outlined_ir_func_0(ptr [[TMP0]], i32 [[C]], ptr [[DOTCE_LOC]])
-; CHECK-NEXT: [[DOTCE_RELOAD:%.*]] = load i32, ptr [[DOTCE_LOC]], align 4
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[DOTCE_LOC]])
-; CHECK-NEXT: br i1 [[TARGETBLOCK]], label [[FIRST:%.*]], label [[NEXT:%.*]]
-; CHECK: dummy:
-; CHECK-NEXT: ret void
-; CHECK: first:
-; CHECK-NEXT: [[TMP1:%.*]] = phi i32 [ [[DOTCE_RELOAD]], [[ENTRY:%.*]] ]
-; CHECK-NEXT: ret void
-; CHECK: next:
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: define internal i1 @outlined_ir_func_0(
-; CHECK-NEXT: newFuncRoot:
-; CHECK-NEXT: br label [[ENTRY_TO_OUTLINE:%.*]]
-; CHECK: entry_to_outline:
-; CHECK-NEXT: br i1 true, label [[TEST1:%.*]], label [[FIRST_SPLIT:%.*]]
-; CHECK: test1:
-; CHECK-NEXT: [[E:%.*]] = load i32, ptr [[TMP0:%.*]], align 4
-; CHECK-NEXT: [[TMP3:%.*]] = add i32 [[TMP1:%.*]], [[TMP1]]
-; CHECK-NEXT: br i1 true, label [[FIRST_SPLIT]], label [[TEST:%.*]]
-; CHECK: test:
-; CHECK-NEXT: [[D:%.*]] = load i32, ptr [[TMP0]], align 4
-; CHECK-NEXT: br i1 true, label [[FIRST_SPLIT]], label [[NEXT_EXITSTUB:%.*]]
-; CHECK: first.split:
-; CHECK-NEXT: [[DOTCE:%.*]] = phi i32 [ [[D]], [[TEST]] ], [ [[E]], [[TEST1]] ], [ [[TMP1]], [[ENTRY_TO_OUTLINE]] ]
-; CHECK-NEXT: br label [[FIRST_EXITSTUB:%.*]]
-; CHECK: first.exitStub:
-; CHECK-NEXT: store i32 [[DOTCE]], ptr [[TMP2:%.*]], align 4
-; CHECK-NEXT: ret i1 true
-; CHECK: next.exitStub:
-; CHECK-NEXT: ret i1 false
-;
diff --git a/llvm/test/lit.cfg.py b/llvm/test/lit.cfg.py
index f48c3a57a89aa..6f04a855d8cb8 100644
--- a/llvm/test/lit.cfg.py
+++ b/llvm/test/lit.cfg.py
@@ -68,7 +68,6 @@
config.excludes.extend(
[
"Attributor",
- "IROutliner",
"BlockExtractor",
"CodeExtractor",
"HotColdSplit",
@@ -296,7 +295,6 @@ def get_asan_rtlib():
"llvm-readelf",
"llvm-readobj",
"llvm-rtdyld",
- "llvm-sim",
"llvm-size",
"llvm-split",
"llvm-stress",
diff --git a/llvm/test/tools/llvm-sim/Inputs/sim1.ll b/llvm/test/tools/llvm-sim/Inputs/sim1.ll
deleted file mode 100644
index 19cfe2fd6f298..0000000000000
--- a/llvm/test/tools/llvm-sim/Inputs/sim1.ll
+++ /dev/null
@@ -1,27 +0,0 @@
-define void @similar_func1() {
-entry:
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- %c = alloca i32, align 4
- store i32 2, ptr %a, align 4
- store i32 3, ptr %b, align 4
- store i32 4, ptr %c, align 4
- %al = load i32, ptr %a
- %bl = load i32, ptr %b
- %cl = load i32, ptr %c
- ret void
-}
-
-define void @similar_func2() {
-entry:
- %a = alloca i32, align 4
- %b = alloca i32, align 4
- %c = alloca i32, align 4
- store i32 2, ptr %a, align 4
- store i32 3, ptr %b, align 4
- store i32 4, ptr %c, align 4
- %al = load i32, ptr %a
- %bl = load i32, ptr %b
- %cl = load i32, ptr %c
- ret void
-}
diff --git a/llvm/test/tools/llvm-sim/fail-cases.test b/llvm/test/tools/llvm-sim/fail-cases.test
deleted file mode 100644
index 8de658abe3ef0..0000000000000
--- a/llvm/test/tools/llvm-sim/fail-cases.test
+++ /dev/null
@@ -1,8 +0,0 @@
-# RUN: not llvm-sim %s 2>&1 | FileCheck %s
-# RUN: not llvm-sim %s.2 2>&1 | FileCheck -DMSG=%errc_ENOENT %s --check-prefix=EXIST
-
-# File reading error messaging tests.
-
-# CHECK: error: expected top-level entity
-
-# EXIST: error: Could not open input file: [[MSG]]
diff --git a/llvm/test/tools/llvm-sim/single-sim-file.test b/llvm/test/tools/llvm-sim/single-sim-file.test
deleted file mode 100644
index cef14b3608500..0000000000000
--- a/llvm/test/tools/llvm-sim/single-sim-file.test
+++ /dev/null
@@ -1,57 +0,0 @@
-# RUN: llvm-sim -o %t %S/Inputs/sim1.ll
-# RUN: FileCheck %s < %t
-
-# Checking the output of a single module test.
-
-# CHECK: {
-# CHECK-NEXT: "1": [
-# CHECK-NEXT: {
-# CHECK-NEXT: "start": 14,
-# CHECK-NEXT: "end": 19
-# CHECK-NEXT: },
-# CHECK-NEXT: {
-# CHECK-NEXT: "start": 4,
-# CHECK-NEXT: "end": 9
-# CHECK-NEXT: }
-# CHECK-NEXT: ],
-# CHECK-NEXT: "2": [
-# CHECK-NEXT: {
-# CHECK-NEXT: "start": 15,
-# CHECK-NEXT: "end": 19
-# CHECK-NEXT: },
-# CHECK-NEXT: {
-# CHECK-NEXT: "start": 5,
-# CHECK-NEXT: "end": 9
-# CHECK-NEXT: }
-# CHECK-NEXT: ],
-# CHECK-NEXT: "3": [
-# CHECK-NEXT: {
-# CHECK-NEXT: "start": 16,
-# CHECK-NEXT: "end": 19
-# CHECK-NEXT: },
-# CHECK-NEXT: {
-# CHECK-NEXT: "start": 6,
-# CHECK-NEXT: "end": 9
-# CHECK-NEXT: }
-# CHECK-NEXT: ],
-# CHECK-NEXT: "4": [
-# CHECK-NEXT: {
-# CHECK-NEXT: "start": 17,
-# CHECK-NEXT: "end": 19
-# CHECK-NEXT: },
-# CHECK-NEXT: {
-# CHECK-NEXT: "start": 7,
-# CHECK-NEXT: "end": 9
-# CHECK-NEXT: }
-# CHECK-NEXT: ],
-# CHECK-NEXT: "5": [
-# CHECK-NEXT: {
-# CHECK-NEXT: "start": 18,
-# CHECK-NEXT: "end": 19
-# CHECK-NEXT: },
-# CHECK-NEXT: {
-# CHECK-NEXT: "start": 8,
-# CHECK-NEXT: "end": 9
-# CHECK-NEXT: }
-# CHECK-NEXT: ]
-# CHECK-NEXT:}
diff --git a/llvm/test/tools/llvm-sim/single-sim.test b/llvm/test/tools/llvm-sim/single-sim.test
deleted file mode 100644
index 0095ec6acbc58..0000000000000
--- a/llvm/test/tools/llvm-sim/single-sim.test
+++ /dev/null
@@ -1,56 +0,0 @@
-# RUN: llvm-sim -o - %S/Inputs/sim1.ll | FileCheck %s
-
-# Checking the output of a single module test.
-
-# CHECK: {
-# CHECK-NEXT: "1": [
-# CHECK-NEXT: {
-# CHECK-NEXT: "start": 14,
-# CHECK-NEXT: "end": 19
-# CHECK-NEXT: },
-# CHECK-NEXT: {
-# CHECK-NEXT: "start": 4,
-# CHECK-NEXT: "end": 9
-# CHECK-NEXT: }
-# CHECK-NEXT: ],
-# CHECK-NEXT: "2": [
-# CHECK-NEXT: {
-# CHECK-NEXT: "start": 15,
-# CHECK-NEXT: "end": 19
-# CHECK-NEXT: },
-# CHECK-NEXT: {
-# CHECK-NEXT: "start": 5,
-# CHECK-NEXT: "end": 9
-# CHECK-NEXT: }
-# CHECK-NEXT: ],
-# CHECK-NEXT: "3": [
-# CHECK-NEXT: {
-# CHECK-NEXT: "start": 16,
-# CHECK-NEXT: "end": 19
-# CHECK-NEXT: },
-# CHECK-NEXT: {
-# CHECK-NEXT: "start": 6,
-# CHECK-NEXT: "end": 9
-# CHECK-NEXT: }
-# CHECK-NEXT: ],
-# CHECK-NEXT: "4": [
-# CHECK-NEXT: {
-# CHECK-NEXT: "start": 17,
-# CHECK-NEXT: "end": 19
-# CHECK-NEXT: },
-# CHECK-NEXT: {
-# CHECK-NEXT: "start": 7,
-# CHECK-NEXT: "end": 9
-# CHECK-NEXT: }
-# CHECK-NEXT: ],
-# CHECK-NEXT: "5": [
-# CHECK-NEXT: {
-# CHECK-NEXT: "start": 18,
-# CHECK-NEXT: "end": 19
-# CHECK-NEXT: },
-# CHECK-NEXT: {
-# CHECK-NEXT: "start": 8,
-# CHECK-NEXT: "end": 9
-# CHECK-NEXT: }
-# CHECK-NEXT: ]
-# CHECK-NEXT:}
diff --git a/llvm/tools/llvm-sim/CMakeLists.txt b/llvm/tools/llvm-sim/CMakeLists.txt
deleted file mode 100644
index 76299050392a2..0000000000000
--- a/llvm/tools/llvm-sim/CMakeLists.txt
+++ /dev/null
@@ -1,9 +0,0 @@
-set(LLVM_LINK_COMPONENTS
- Core
- Support
- Analysis
- IRReader)
-
-add_llvm_tool(llvm-sim
- llvm-sim.cpp
-)
diff --git a/llvm/tools/llvm-sim/llvm-sim.cpp b/llvm/tools/llvm-sim/llvm-sim.cpp
deleted file mode 100644
index 6e86714ed4acd..0000000000000
--- a/llvm/tools/llvm-sim/llvm-sim.cpp
+++ /dev/null
@@ -1,148 +0,0 @@
-//===-- llvm-sim.cpp - Find similar sections of programs -------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache 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 program finds similar sections of a Module, and exports them as a JSON
-// file.
-//
-// To find similarities contained across multiple modules, please use llvm-link
-// first to merge the modules.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Analysis/IRSimilarityIdentifier.h"
-#include "llvm/IRReader/IRReader.h"
-#include "llvm/Support/CommandLine.h"
-#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/InitLLVM.h"
-#include "llvm/Support/JSON.h"
-#include "llvm/Support/SourceMgr.h"
-#include "llvm/Support/ToolOutputFile.h"
-
-using namespace llvm;
-using namespace IRSimilarity;
-
-static cl::opt<std::string> OutputFilename("o", cl::desc("Output Filename"),
- cl::init("-"),
- cl::value_desc("filename"));
-
-static cl::opt<std::string> InputSourceFile(cl::Positional,
- cl::desc("<Source file>"),
- cl::init("-"),
- cl::value_desc("filename"));
-
-/// Retrieve the unique number \p I was mapped to in parseBitcodeFile.
-///
-/// \param I - The Instruction to find the instruction number for.
-/// \param LLVMInstNum - The mapping of Instructions to their location in the
-/// module represented by an unsigned integer.
-/// \returns The instruction number for \p I if it exists.
-std::optional<unsigned>
-getPositionInModule(const Instruction *I,
- const DenseMap<Instruction *, unsigned> &LLVMInstNum) {
- assert(I && "Instruction is nullptr!");
- auto It = LLVMInstNum.find(I);
- if (It == LLVMInstNum.end())
- return std::nullopt;
- return It->second;
-}
-
-/// Exports the given SimilarityGroups to a JSON file at \p FilePath.
-///
-/// \param FilePath - The path to the output location.
-/// \param SimSections - The similarity groups to process.
-/// \param LLVMInstNum - The mapping of Instructions to their location in the
-/// module represented by an unsigned integer.
-/// \returns A nonzero error code if there was a failure creating the file.
-std::error_code
-exportToFile(const StringRef FilePath,
- const SimilarityGroupList &SimSections,
- const DenseMap<Instruction *, unsigned> &LLVMInstNum) {
- std::error_code EC;
- std::unique_ptr<ToolOutputFile> Out(
- new ToolOutputFile(FilePath, EC, sys::fs::OF_None));
- if (EC)
- return EC;
-
- json::OStream J(Out->os(), 1);
- J.objectBegin();
-
- unsigned SimOption = 1;
- // Process each list of SimilarityGroups organized by the Module.
- for (const SimilarityGroup &G : SimSections) {
- std::string SimOptionStr = std::to_string(SimOption);
- J.attributeBegin(SimOptionStr);
- J.arrayBegin();
- // For each file there is a list of the range where the similarity
- // exists.
- for (const IRSimilarityCandidate &C : G) {
- std::optional<unsigned> Start =
- getPositionInModule((*C.front()).Inst, LLVMInstNum);
- std::optional<unsigned> End =
- getPositionInModule((*C.back()).Inst, LLVMInstNum);
-
- assert(Start &&
- "Could not find instruction number for first instruction");
- assert(End && "Could not find instruction number for last instruction");
-
- J.object([&] {
- J.attribute("start", *Start);
- J.attribute("end", *End);
- });
- }
- J.arrayEnd();
- J.attributeEnd();
- SimOption++;
- }
- J.objectEnd();
-
- Out->keep();
-
- return EC;
-}
-
-int main(int argc, const char *argv[]) {
- InitLLVM X(argc, argv);
-
- cl::ParseCommandLineOptions(argc, argv, "LLVM IR Similarity Visualizer\n");
-
- LLVMContext CurrContext;
- SMDiagnostic Err;
- std::unique_ptr<Module> ModuleToAnalyze =
- parseIRFile(InputSourceFile, Err, CurrContext);
-
- if (!ModuleToAnalyze) {
- Err.print(argv[0], errs());
- return 1;
- }
-
- // Mapping from an Instruction pointer to its occurrence in a sequential
- // list of all the Instructions in a Module.
- DenseMap<Instruction *, unsigned> LLVMInstNum;
-
- // We give each instruction a number, which gives us a start and end value
- // for the beginning and end of each IRSimilarityCandidate.
- unsigned InstructionNumber = 1;
- for (Function &F : *ModuleToAnalyze)
- for (BasicBlock &BB : F)
- for (Instruction &I : BB)
- LLVMInstNum[&I]= InstructionNumber++;
-
- // The similarity identifier we will use to find the similar sections.
- IRSimilarityIdentifier SimIdent;
- SimilarityGroupList SimilaritySections =
- SimIdent.findSimilarity(*ModuleToAnalyze);
-
- std::error_code E =
- exportToFile(OutputFilename, SimilaritySections, LLVMInstNum);
- if (E) {
- errs() << argv[0] << ": " << E.message() << '\n';
- return 2;
- }
-
- return 0;
-}
diff --git a/llvm/unittests/Analysis/CMakeLists.txt b/llvm/unittests/Analysis/CMakeLists.txt
index 50bf4539e7984..b1f8cb918d590 100644
--- a/llvm/unittests/Analysis/CMakeLists.txt
+++ b/llvm/unittests/Analysis/CMakeLists.txt
@@ -34,7 +34,6 @@ set(ANALYSIS_TEST_SOURCES
FunctionPropertiesAnalysisTest.cpp
InlineCostTest.cpp
IR2VecTest.cpp
- IRSimilarityIdentifierTest.cpp
IVDescriptorsTest.cpp
LastRunTrackingAnalysisTest.cpp
LazyCallGraphTest.cpp
diff --git a/llvm/unittests/Analysis/IRSimilarityIdentifierTest.cpp b/llvm/unittests/Analysis/IRSimilarityIdentifierTest.cpp
deleted file mode 100644
index c74f9c63af219..0000000000000
--- a/llvm/unittests/Analysis/IRSimilarityIdentifierTest.cpp
+++ /dev/null
@@ -1,2850 +0,0 @@
-//===- IRSimilarityIdentifierTest.cpp - IRSimilarityIdentifier unit tests -===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// Tests for components for finding similarity such as the instruction mapper,
-// suffix tree usage, and structural analysis.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Analysis/IRSimilarityIdentifier.h"
-#include "llvm/ADT/ScopeExit.h"
-#include "llvm/AsmParser/Parser.h"
-#include "llvm/IR/LLVMContext.h"
-#include "llvm/IR/Module.h"
-#include "llvm/Support/Allocator.h"
-#include "llvm/Support/Compiler.h"
-#include "llvm/Support/SourceMgr.h"
-#include "gtest/gtest.h"
-
-using namespace llvm;
-using namespace IRSimilarity;
-
-static std::unique_ptr<Module> makeLLVMModule(LLVMContext &Context,
- StringRef ModuleStr) {
- SMDiagnostic Err;
- std::unique_ptr<Module> M = parseAssemblyString(ModuleStr, Err, Context);
- assert(M && "Bad LLVM IR?");
- return M;
-}
-
-void getVectors(Module &M, IRInstructionMapper &Mapper,
- std::vector<IRInstructionData *> &InstrList,
- std::vector<unsigned> &UnsignedVec) {
- for (Function &F : M)
- for (BasicBlock &BB : F)
- Mapper.convertToUnsignedVec(BB, InstrList, UnsignedVec);
-}
-
-void getSimilarities(
- Module &M,
- std::vector<std::vector<IRSimilarityCandidate>> &SimilarityCandidates) {
- // In order to keep the size of the tests from becoming too large, we do not
- // recognize similarity for branches unless explicitly needed.
- IRSimilarityIdentifier Identifier(/*EnableBranchMatching = */false);
- SimilarityCandidates = Identifier.findSimilarity(M);
-}
-
-// TODO: All these tests could probably become IR LIT tests like
-// IROutliner/outlining-special-state.ll
-
-// Checks that different opcodes are mapped to different values
-TEST(IRInstructionMapper, OpcodeDifferentiation) {
- StringRef ModuleString = R"(
- define i32 @f(i32 %a, i32 %b) {
- bb0:
- %0 = add i32 %a, %b
- %1 = mul i32 %a, %b
- ret i32 0
- })";
- LLVMContext Context;
- std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
-
- std::vector<IRInstructionData *> InstrList;
- std::vector<unsigned> UnsignedVec;
-
- SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
- SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
- IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
- getVectors(*M, Mapper, InstrList, UnsignedVec);
-
- // Check that the size of the unsigned vector and the instruction list are the
- // same as a safety check.
- ASSERT_TRUE(InstrList.size() == UnsignedVec.size());
-
- // Make sure that the unsigned vector is the expected size.
- ASSERT_TRUE(UnsignedVec.size() == 3);
-
- // Check whether the instructions are not mapped to the same value.
- ASSERT_TRUE(UnsignedVec[0] != UnsignedVec[1]);
-}
-
-// Checks that the same opcodes and types are mapped to the same values.
-TEST(IRInstructionMapper, OpcodeTypeSimilarity) {
- StringRef ModuleString = R"(
- define i32 @f(i32 %a, i32 %b) {
- bb0:
- %0 = add i32 %a, %b
- %1 = add i32 %b, %a
- ret i32 0
- })";
- LLVMContext Context;
- std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
-
- std::vector<IRInstructionData *> InstrList;
- std::vector<unsigned> UnsignedVec;
-
- SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
- SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
- IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
- getVectors(*M, Mapper, InstrList, UnsignedVec);
-
- ASSERT_TRUE(InstrList.size() == UnsignedVec.size());
- ASSERT_TRUE(UnsignedVec.size() == 3);
-
- // Check whether the instructions are mapped to the same value.
- ASSERT_TRUE(UnsignedVec[0] == UnsignedVec[1]);
-}
-
-// Checks that the same opcode and different types are mapped to different
-// values.
-TEST(IRInstructionMapper, TypeDifferentiation) {
- StringRef ModuleString = R"(
- define i32 @f(i32 %a, i32 %b, i64 %c, i64 %d) {
- bb0:
- %0 = add i32 %a, %b
- %1 = add i64 %c, %d
- ret i32 0
- })";
- LLVMContext Context;
- std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
-
- std::vector<IRInstructionData *> InstrList;
- std::vector<unsigned> UnsignedVec;
-
- SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
- SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
- IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
- getVectors(*M, Mapper, InstrList, UnsignedVec);
-
- ASSERT_TRUE(InstrList.size() == UnsignedVec.size());
- ASSERT_TRUE(UnsignedVec.size() == 3);
- ASSERT_TRUE(UnsignedVec[0] != UnsignedVec[1]);
-}
-
-// Checks that different predicates map to different values.
-TEST(IRInstructionMapper, PredicateDifferentiation) {
- StringRef ModuleString = R"(
- define i32 @f(i32 %a, i32 %b) {
- bb0:
- %0 = icmp sge i32 %b, %a
- %1 = icmp slt i32 %a, %b
- ret i32 0
- })";
- LLVMContext Context;
- std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
-
- std::vector<IRInstructionData *> InstrList;
- std::vector<unsigned> UnsignedVec;
-
- SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
- SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
- IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
- getVectors(*M, Mapper, InstrList, UnsignedVec);
-
- ASSERT_TRUE(InstrList.size() == UnsignedVec.size());
- ASSERT_TRUE(UnsignedVec.size() == 3);
- ASSERT_TRUE(UnsignedVec[0] != UnsignedVec[1]);
-}
-
-// Checks that predicates where that can be considered the same when the
-// operands are swapped, i.e. greater than to less than are mapped to the same
-// unsigned integer.
-TEST(IRInstructionMapper, PredicateIsomorphism) {
- StringRef ModuleString = R"(
- define i32 @f(i32 %a, i32 %b) {
- bb0:
- %0 = icmp sgt i32 %a, %b
- %1 = icmp slt i32 %b, %a
- ret i32 0
- })";
- LLVMContext Context;
- std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
-
- std::vector<IRInstructionData *> InstrList;
- std::vector<unsigned> UnsignedVec;
-
- SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
- SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
- IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
- getVectors(*M, Mapper, InstrList, UnsignedVec);
-
- ASSERT_TRUE(InstrList.size() == UnsignedVec.size());
- ASSERT_TRUE(UnsignedVec.size() == 3);
- ASSERT_TRUE(UnsignedVec[0] == UnsignedVec[1]);
-}
-
-// Checks that the same predicate maps to the same value.
-TEST(IRInstructionMapper, PredicateSimilarity) {
- StringRef ModuleString = R"(
- define i32 @f(i32 %a, i32 %b) {
- bb0:
- %0 = icmp slt i32 %a, %b
- %1 = icmp slt i32 %b, %a
- ret i32 0
- })";
- LLVMContext Context;
- std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
-
- std::vector<IRInstructionData *> InstrList;
- std::vector<unsigned> UnsignedVec;
-
- SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
- SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
- IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
- getVectors(*M, Mapper, InstrList, UnsignedVec);
-
- ASSERT_TRUE(InstrList.size() == UnsignedVec.size());
- ASSERT_TRUE(UnsignedVec.size() == 3);
- ASSERT_TRUE(UnsignedVec[0] == UnsignedVec[1]);
-}
-
-// Checks that the same predicate maps to the same value for floating point
-// CmpInsts.
-TEST(IRInstructionMapper, FPPredicateSimilarity) {
- StringRef ModuleString = R"(
- define i32 @f(double %a, double %b) {
- bb0:
- %0 = fcmp olt double %a, %b
- %1 = fcmp olt double %b, %a
- ret i32 0
- })";
- LLVMContext Context;
- std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
-
- std::vector<IRInstructionData *> InstrList;
- std::vector<unsigned> UnsignedVec;
-
- SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
- SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
- IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
- getVectors(*M, Mapper, InstrList, UnsignedVec);
-
- ASSERT_TRUE(InstrList.size() == UnsignedVec.size());
- ASSERT_TRUE(UnsignedVec.size() == 3);
- ASSERT_TRUE(UnsignedVec[0] == UnsignedVec[1]);
-}
-
-// Checks that the different predicate maps to a different value for floating
-// point CmpInsts.
-TEST(IRInstructionMapper, FPPredicatDifference) {
- StringRef ModuleString = R"(
- define i32 @f(double %a, double %b) {
- bb0:
- %0 = fcmp olt double %a, %b
- %1 = fcmp oge double %b, %a
- ret i32 0
- })";
- LLVMContext Context;
- std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
-
- std::vector<IRInstructionData *> InstrList;
- std::vector<unsigned> UnsignedVec;
-
- SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
- SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
- IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
- getVectors(*M, Mapper, InstrList, UnsignedVec);
-
- ASSERT_TRUE(InstrList.size() == UnsignedVec.size());
- ASSERT_TRUE(UnsignedVec.size() == 3);
- ASSERT_TRUE(UnsignedVec[0] != UnsignedVec[1]);
-}
-
-// Checks that the zexts that have the same type parameters map to the same
-// unsigned integer.
-TEST(IRInstructionMapper, ZextTypeSimilarity) {
- StringRef ModuleString = R"(
- define i32 @f(i32 %a) {
- bb0:
- %0 = zext i32 %a to i64
- %1 = zext i32 %a to i64
- ret i32 0
- })";
- LLVMContext Context;
- std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
-
- std::vector<IRInstructionData *> InstrList;
- std::vector<unsigned> UnsignedVec;
-
- SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
- SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
- IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
- getVectors(*M, Mapper, InstrList, UnsignedVec);
-
- ASSERT_TRUE(InstrList.size() == UnsignedVec.size());
- ASSERT_TRUE(UnsignedVec.size() == 3);
- ASSERT_TRUE(UnsignedVec[0] == UnsignedVec[1]);
-}
-
-// Checks that the sexts that have the same type parameters map to the same
-// unsigned integer.
-TEST(IRInstructionMapper, SextTypeSimilarity) {
- StringRef ModuleString = R"(
- define i32 @f(i32 %a) {
- bb0:
- %0 = sext i32 %a to i64
- %1 = sext i32 %a to i64
- ret i32 0
- })";
- LLVMContext Context;
- std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
-
- std::vector<IRInstructionData *> InstrList;
- std::vector<unsigned> UnsignedVec;
-
- SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
- SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
- IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
- getVectors(*M, Mapper, InstrList, UnsignedVec);
-
- ASSERT_TRUE(InstrList.size() == UnsignedVec.size());
- ASSERT_TRUE(UnsignedVec.size() == 3);
- ASSERT_TRUE(UnsignedVec[0] == UnsignedVec[1]);
-}
-
-// Checks that the zexts that have the different type parameters map to the
-// different unsigned integers.
-TEST(IRInstructionMapper, ZextTypeDifference) {
- StringRef ModuleString = R"(
- define i32 @f(i32 %a, i8 %b) {
- bb0:
- %0 = zext i32 %a to i64
- %1 = zext i8 %b to i32
- ret i32 0
- })";
- LLVMContext Context;
- std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
-
- std::vector<IRInstructionData *> InstrList;
- std::vector<unsigned> UnsignedVec;
-
- SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
- SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
- IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
- getVectors(*M, Mapper, InstrList, UnsignedVec);
-
- ASSERT_TRUE(InstrList.size() == UnsignedVec.size());
- ASSERT_TRUE(UnsignedVec.size() == 3);
- ASSERT_TRUE(UnsignedVec[0] != UnsignedVec[1]);
-}
-
-// Checks that the sexts that have the different type parameters map to the
-// different unsigned integers.
-TEST(IRInstructionMapper, SextTypeDifference) {
- StringRef ModuleString = R"(
- define i32 @f(i32 %a, i8 %b) {
- bb0:
- %0 = sext i32 %a to i64
- %1 = sext i8 %b to i32
- ret i32 0
- })";
- LLVMContext Context;
- std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
-
- std::vector<IRInstructionData *> InstrList;
- std::vector<unsigned> UnsignedVec;
-
- SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
- SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
- IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
- getVectors(*M, Mapper, InstrList, UnsignedVec);
-
- ASSERT_TRUE(InstrList.size() == UnsignedVec.size());
- ASSERT_TRUE(UnsignedVec.size() == 3);
- ASSERT_TRUE(UnsignedVec[0] != UnsignedVec[1]);
-}
-
-// Checks that loads that have the same type are mapped to the same unsigned
-// integer.
-TEST(IRInstructionMapper, LoadSimilarType) {
- StringRef ModuleString = R"(
- define i32 @f(ptr %a, ptr %b) {
- bb0:
- %0 = load i32, ptr %a
- %1 = load i32, ptr %b
- ret i32 0
- })";
- LLVMContext Context;
- std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
-
- std::vector<IRInstructionData *> InstrList;
- std::vector<unsigned> UnsignedVec;
-
- SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
- SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
- IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
- getVectors(*M, Mapper, InstrList, UnsignedVec);
-
- ASSERT_TRUE(InstrList.size() == UnsignedVec.size());
- ASSERT_TRUE(UnsignedVec.size() == 3);
- ASSERT_TRUE(UnsignedVec[0] == UnsignedVec[1]);
-}
-
-// Checks that loads that have the different types are mapped to
-// different unsigned integers.
-TEST(IRInstructionMapper, LoadDifferentType) {
- StringRef ModuleString = R"(
- define i32 @f(ptr %a, ptr %b) {
- bb0:
- %0 = load i32, ptr %a
- %1 = load i64, ptr %b
- ret i32 0
- })";
- LLVMContext Context;
- std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
-
- std::vector<IRInstructionData *> InstrList;
- std::vector<unsigned> UnsignedVec;
-
- SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
- SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
- IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
- getVectors(*M, Mapper, InstrList, UnsignedVec);
-
- ASSERT_TRUE(InstrList.size() == UnsignedVec.size());
- ASSERT_TRUE(UnsignedVec.size() == 3);
- ASSERT_TRUE(UnsignedVec[0] != UnsignedVec[1]);
-}
-
-// Checks that loads that have the different aligns are mapped to different
-// unsigned integers.
-TEST(IRInstructionMapper, LoadDifferentAlign) {
- StringRef ModuleString = R"(
- define i32 @f(ptr %a, ptr %b) {
- bb0:
- %0 = load i32, ptr %a, align 4
- %1 = load i32, ptr %b, align 8
- ret i32 0
- })";
- LLVMContext Context;
- std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
-
- std::vector<IRInstructionData *> InstrList;
- std::vector<unsigned> UnsignedVec;
-
- SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
- SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
- IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
- getVectors(*M, Mapper, InstrList, UnsignedVec);
-
- ASSERT_TRUE(InstrList.size() == UnsignedVec.size());
- ASSERT_TRUE(UnsignedVec.size() == 3);
- ASSERT_TRUE(UnsignedVec[0] != UnsignedVec[1]);
-}
-
-// Checks that loads that have the different volatile settings are mapped to
-// different unsigned integers.
-TEST(IRInstructionMapper, LoadDifferentVolatile) {
- StringRef ModuleString = R"(
- define i32 @f(ptr %a, ptr %b) {
- bb0:
- %0 = load volatile i32, ptr %a
- %1 = load i32, ptr %b
- ret i32 0
- })";
- LLVMContext Context;
- std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
-
- std::vector<IRInstructionData *> InstrList;
- std::vector<unsigned> UnsignedVec;
-
- SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
- SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
- IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
- getVectors(*M, Mapper, InstrList, UnsignedVec);
-
- ASSERT_TRUE(InstrList.size() == UnsignedVec.size());
- ASSERT_TRUE(UnsignedVec.size() == 3);
- ASSERT_TRUE(UnsignedVec[0] != UnsignedVec[1]);
-}
-
-// Checks that loads that have the same volatile settings are mapped to
-// different unsigned integers.
-TEST(IRInstructionMapper, LoadSameVolatile) {
- StringRef ModuleString = R"(
- define i32 @f(ptr %a, ptr %b) {
- bb0:
- %0 = load volatile i32, ptr %a
- %1 = load volatile i32, ptr %b
- ret i32 0
- })";
- LLVMContext Context;
- std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
-
- std::vector<IRInstructionData *> InstrList;
- std::vector<unsigned> UnsignedVec;
-
- SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
- SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
- IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
- getVectors(*M, Mapper, InstrList, UnsignedVec);
-
- ASSERT_TRUE(InstrList.size() == UnsignedVec.size());
- ASSERT_TRUE(UnsignedVec.size() == 3);
- ASSERT_TRUE(UnsignedVec[0] == UnsignedVec[1]);
-}
-
-// Checks that loads that have the different atomicity settings are mapped to
-// different unsigned integers.
-TEST(IRInstructionMapper, LoadDifferentAtomic) {
- StringRef ModuleString = R"(
- define i32 @f(ptr %a, ptr %b) {
- bb0:
- %0 = load atomic i32, ptr %a unordered, align 4
- %1 = load atomic i32, ptr %b monotonic, align 4
- ret i32 0
- })";
- LLVMContext Context;
- std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
-
- std::vector<IRInstructionData *> InstrList;
- std::vector<unsigned> UnsignedVec;
-
- SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
- SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
- IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
- getVectors(*M, Mapper, InstrList, UnsignedVec);
-
- ASSERT_TRUE(InstrList.size() == UnsignedVec.size());
- ASSERT_TRUE(UnsignedVec.size() == 3);
- ASSERT_TRUE(UnsignedVec[0] != UnsignedVec[1]);
-}
-
-// Checks that loads that have the same atomicity settings are mapped to
-// different unsigned integers.
-TEST(IRInstructionMapper, LoadSameAtomic) {
- StringRef ModuleString = R"(
- define i32 @f(ptr %a, ptr %b) {
- bb0:
- %0 = load atomic i32, ptr %a unordered, align 4
- %1 = load atomic i32, ptr %b unordered, align 4
- ret i32 0
- })";
- LLVMContext Context;
- std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
-
- std::vector<IRInstructionData *> InstrList;
- std::vector<unsigned> UnsignedVec;
-
- SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
- SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
- IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
- getVectors(*M, Mapper, InstrList, UnsignedVec);
-
- ASSERT_TRUE(InstrList.size() == UnsignedVec.size());
- ASSERT_TRUE(UnsignedVec.size() == 3);
- ASSERT_TRUE(UnsignedVec[0] == UnsignedVec[1]);
-}
-
-// Checks that stores that have the same type are mapped to the same unsigned
-// integer.
-TEST(IRInstructionMapper, StoreSimilarType) {
- StringRef ModuleString = R"(
- define i32 @f(ptr %a, ptr %b) {
- bb0:
- store i32 1, ptr %a
- store i32 2, ptr %a
- ret i32 0
- })";
- LLVMContext Context;
- std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
-
- std::vector<IRInstructionData *> InstrList;
- std::vector<unsigned> UnsignedVec;
-
- SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
- SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
- IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
- getVectors(*M, Mapper, InstrList, UnsignedVec);
-
- ASSERT_TRUE(InstrList.size() == UnsignedVec.size());
- ASSERT_TRUE(UnsignedVec.size() == 3);
- ASSERT_TRUE(UnsignedVec[0] == UnsignedVec[1]);
-}
-
-// Checks that stores that have the different types are mapped to
-// different unsigned integers.
-TEST(IRInstructionMapper, StoreDifferentType) {
- StringRef ModuleString = R"(
- define i32 @f(ptr %a, ptr %b) {
- bb0:
- store i32 1, ptr %a
- store i64 1, ptr %b
- ret i32 0
- })";
- LLVMContext Context;
- std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
-
- std::vector<IRInstructionData *> InstrList;
- std::vector<unsigned> UnsignedVec;
-
- SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
- SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
- IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
- getVectors(*M, Mapper, InstrList, UnsignedVec);
-
- ASSERT_TRUE(InstrList.size() == UnsignedVec.size());
- ASSERT_TRUE(UnsignedVec.size() == 3);
- ASSERT_TRUE(UnsignedVec[0] != UnsignedVec[1]);
-}
-
-// Checks that stores that have the different aligns are mapped to different
-// unsigned integers.
-TEST(IRInstructionMapper, StoreDifferentAlign) {
- StringRef ModuleString = R"(
- define i32 @f(ptr %a, ptr %b) {
- bb0:
- store i32 1, ptr %a, align 4
- store i32 1, ptr %b, align 8
- ret i32 0
- })";
- LLVMContext Context;
- std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
-
- std::vector<IRInstructionData *> InstrList;
- std::vector<unsigned> UnsignedVec;
-
- SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
- SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
- IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
- getVectors(*M, Mapper, InstrList, UnsignedVec);
-
- ASSERT_TRUE(InstrList.size() == UnsignedVec.size());
- ASSERT_TRUE(UnsignedVec.size() == 3);
- ASSERT_TRUE(UnsignedVec[0] != UnsignedVec[1]);
-}
-
-// Checks that stores that have the different volatile settings are mapped to
-// different unsigned integers.
-TEST(IRInstructionMapper, StoreDifferentVolatile) {
- StringRef ModuleString = R"(
- define i32 @f(ptr %a, ptr %b) {
- bb0:
- store volatile i32 1, ptr %a
- store i32 1, ptr %b
- ret i32 0
- })";
- LLVMContext Context;
- std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
-
- std::vector<IRInstructionData *> InstrList;
- std::vector<unsigned> UnsignedVec;
-
- SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
- SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
- IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
- getVectors(*M, Mapper, InstrList, UnsignedVec);
-
- ASSERT_TRUE(InstrList.size() == UnsignedVec.size());
- ASSERT_TRUE(UnsignedVec.size() == 3);
- ASSERT_TRUE(UnsignedVec[0] != UnsignedVec[1]);
-}
-
-// Checks that stores that have the same volatile settings are mapped to
-// different unsigned integers.
-TEST(IRInstructionMapper, StoreSameVolatile) {
- StringRef ModuleString = R"(
- define i32 @f(ptr %a, ptr %b) {
- bb0:
- store volatile i32 1, ptr %a
- store volatile i32 1, ptr %b
- ret i32 0
- })";
- LLVMContext Context;
- std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
-
- std::vector<IRInstructionData *> InstrList;
- std::vector<unsigned> UnsignedVec;
-
- SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
- SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
- IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
- getVectors(*M, Mapper, InstrList, UnsignedVec);
-
- ASSERT_TRUE(InstrList.size() == UnsignedVec.size());
- ASSERT_TRUE(UnsignedVec.size() == 3);
- ASSERT_TRUE(UnsignedVec[0] == UnsignedVec[1]);
-}
-
-// Checks that loads that have the same atomicity settings are mapped to
-// different unsigned integers.
-TEST(IRInstructionMapper, StoreSameAtomic) {
- StringRef ModuleString = R"(
- define i32 @f(ptr %a, ptr %b) {
- bb0:
- store atomic i32 1, ptr %a unordered, align 4
- store atomic i32 1, ptr %b unordered, align 4
- ret i32 0
- })";
- LLVMContext Context;
- std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
-
- std::vector<IRInstructionData *> InstrList;
- std::vector<unsigned> UnsignedVec;
-
- SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
- SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
- IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
- getVectors(*M, Mapper, InstrList, UnsignedVec);
-
- ASSERT_TRUE(InstrList.size() == UnsignedVec.size());
- ASSERT_TRUE(UnsignedVec.size() == 3);
- ASSERT_TRUE(UnsignedVec[0] == UnsignedVec[1]);
-}
-
-// Checks that loads that have the different atomicity settings are mapped to
-// different unsigned integers.
-TEST(IRInstructionMapper, StoreDifferentAtomic) {
- StringRef ModuleString = R"(
- define i32 @f(ptr %a, ptr %b) {
- bb0:
- store atomic i32 1, ptr %a unordered, align 4
- store atomic i32 1, ptr %b monotonic, align 4
- ret i32 0
- })";
- LLVMContext Context;
- std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
-
- std::vector<IRInstructionData *> InstrList;
- std::vector<unsigned> UnsignedVec;
-
- SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
- SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
- IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
- getVectors(*M, Mapper, InstrList, UnsignedVec);
-
- ASSERT_TRUE(InstrList.size() == UnsignedVec.size());
- ASSERT_TRUE(UnsignedVec.size() == 3);
- ASSERT_TRUE(UnsignedVec[0] != UnsignedVec[1]);
-}
-
-// Checks that the branch is mapped to legal when the option is set.
-TEST(IRInstructionMapper, BranchLegal) {
- StringRef ModuleString = R"(
- define i32 @f(i32 %a, i32 %b) {
- bb0:
- %0 = icmp slt i32 %a, %b
- br i1 %0, label %bb0, label %bb1
- bb1:
- ret i32 0
- })";
- LLVMContext Context;
- std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
-
- std::vector<IRInstructionData *> InstrList;
- std::vector<unsigned> UnsignedVec;
-
- SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
- SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
- IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
- Mapper.InstClassifier.EnableBranches = true;
- Mapper.initializeForBBs(*M);
- getVectors(*M, Mapper, InstrList, UnsignedVec);
-
- ASSERT_EQ(InstrList.size(), UnsignedVec.size());
- ASSERT_EQ(UnsignedVec.size(), static_cast<unsigned>(3));
- ASSERT_TRUE(UnsignedVec[1] > UnsignedVec[0]);
- ASSERT_TRUE(UnsignedVec[1] < UnsignedVec[2]);
-}
-
-// Checks that a PHINode is mapped to be legal.
-TEST(IRInstructionMapper, PhiLegal) {
- StringRef ModuleString = R"(
- define i32 @f(i32 %a, i32 %b) {
- bb0:
- %0 = phi i1 [ 0, %bb0 ], [ %0, %bb1 ]
- %1 = add i32 %a, %b
- ret i32 0
- bb1:
- ret i32 1
- })";
- LLVMContext Context;
- std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
-
- std::vector<IRInstructionData *> InstrList;
- std::vector<unsigned> UnsignedVec;
-
- SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
- SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
- IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
- Mapper.InstClassifier.EnableBranches = true;
- Mapper.initializeForBBs(*M);
- getVectors(*M, Mapper, InstrList, UnsignedVec);
-
- ASSERT_EQ(InstrList.size(), UnsignedVec.size());
- ASSERT_EQ(UnsignedVec.size(), static_cast<unsigned>(3));
-}
-
-// Checks that a PHINode is mapped to be legal.
-TEST(IRInstructionMapper, PhiIllegal) {
- StringRef ModuleString = R"(
- define i32 @f(i32 %a, i32 %b) {
- bb0:
- %0 = phi i1 [ 0, %bb0 ], [ %0, %bb1 ]
- %1 = add i32 %a, %b
- ret i32 0
- bb1:
- ret i32 1
- })";
- LLVMContext Context;
- std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
-
- std::vector<IRInstructionData *> InstrList;
- std::vector<unsigned> UnsignedVec;
-
- SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
- SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
- IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
- Mapper.initializeForBBs(*M);
- getVectors(*M, Mapper, InstrList, UnsignedVec);
-
- ASSERT_EQ(InstrList.size(), UnsignedVec.size());
- ASSERT_EQ(UnsignedVec.size(), static_cast<unsigned>(3));
- ASSERT_GT(UnsignedVec[0], Mapper.IllegalInstrNumber);
-}
-
-// In most cases, the illegal instructions we are collecting don't require any
-// sort of setup. In these cases, we can just only have illegal instructions,
-// and the mapper will create 0 length vectors, and we can check that.
-
-// In cases where we have legal instructions needed to set up the illegal
-// instruction, to check illegal instructions are assigned unsigned integers
-// from the maximum value decreasing to 0, it will be greater than a legal
-// instruction that comes after. So to check that we have an illegal
-// instruction, we place a legal instruction after an illegal instruction, and
-// check that the illegal unsigned integer is greater than the unsigned integer
-// of the legal instruction.
-
-// Checks that an alloca instruction is mapped to be illegal.
-TEST(IRInstructionMapper, AllocaIllegal) {
- StringRef ModuleString = R"(
- define i32 @f(i32 %a, i32 %b) {
- bb0:
- %0 = alloca i32
- ret i32 0
- })";
- LLVMContext Context;
- std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
-
- std::vector<IRInstructionData *> InstrList;
- std::vector<unsigned> UnsignedVec;
-
- SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
- SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
- IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
- getVectors(*M, Mapper, InstrList, UnsignedVec);
-
- ASSERT_EQ(InstrList.size(), UnsignedVec.size());
- ASSERT_EQ(UnsignedVec.size(), static_cast<unsigned>(1));
- ASSERT_GT(UnsignedVec[0], Mapper.IllegalInstrNumber);
-}
-
-// Checks that an getelementptr instruction is mapped to be legal. And that
-// the operands in getelementpointer instructions are the exact same after the
-// first element operand, which only requires the same type.
-TEST(IRInstructionMapper, GetElementPtrSameEndOperands) {
- StringRef ModuleString = R"(
- %struct.RT = type { i8, [10 x [20 x i32]], i8 }
- %struct.ST = type { i32, double, %struct.RT }
- define i32 @f(%struct.ST* %s, i64 %a, i64 %b) {
- bb0:
- %0 = getelementptr inbounds %struct.ST, %struct.ST* %s, i64 %a, i32 0
- %1 = getelementptr inbounds %struct.ST, %struct.ST* %s, i64 %b, i32 0
- ret i32 0
- })";
- LLVMContext Context;
- std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
-
- std::vector<IRInstructionData *> InstrList;
- std::vector<unsigned> UnsignedVec;
-
- SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
- SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
- IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
- getVectors(*M, Mapper, InstrList, UnsignedVec);
-
- ASSERT_EQ(InstrList.size(), UnsignedVec.size());
- ASSERT_EQ(UnsignedVec.size(), static_cast<unsigned>(3));
- ASSERT_EQ(UnsignedVec[0], UnsignedVec[1]);
-}
-
-// Check that when the operands in getelementpointer instructions are not the
-// exact same after the first element operand, the instructions are mapped to
-// different values.
-TEST(IRInstructionMapper, GetElementPtrDifferentEndOperands) {
- StringRef ModuleString = R"(
- %struct.RT = type { i8, [10 x [20 x i32]], i8 }
- %struct.ST = type { i32, double, %struct.RT }
- define i32 @f(%struct.ST* %s, i64 %a, i64 %b) {
- bb0:
- %0 = getelementptr inbounds %struct.ST, %struct.ST* %s, i64 %a, i32 0
- %1 = getelementptr inbounds %struct.ST, %struct.ST* %s, i64 %b, i32 2
- ret i32 0
- })";
- LLVMContext Context;
- std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
-
- std::vector<IRInstructionData *> InstrList;
- std::vector<unsigned> UnsignedVec;
-
- SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
- SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
- IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
- getVectors(*M, Mapper, InstrList, UnsignedVec);
-
- ASSERT_EQ(InstrList.size(), UnsignedVec.size());
- ASSERT_EQ(UnsignedVec.size(), static_cast<unsigned>(3));
- ASSERT_NE(UnsignedVec[0], UnsignedVec[1]);
-}
-
-// Check that when the operands in getelementpointer instructions are not the
-// same initial base type, each instruction is mapped to a different value.
-TEST(IRInstructionMapper, GetElementPtrDifferentBaseType) {
- StringRef ModuleString = R"(
- %struct.RT = type { i8, [10 x [20 x i32]], i8 }
- %struct.ST = type { i32, double, %struct.RT }
- define i32 @f(%struct.ST* %s, %struct.RT* %r, i64 %a, i64 %b) {
- bb0:
- %0 = getelementptr inbounds %struct.ST, %struct.ST* %s, i64 %a
- %1 = getelementptr inbounds %struct.RT, %struct.RT* %r, i64 %b
- ret i32 0
- })";
- LLVMContext Context;
- std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
-
- std::vector<IRInstructionData *> InstrList;
- std::vector<unsigned> UnsignedVec;
-
- SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
- SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
- IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
- getVectors(*M, Mapper, InstrList, UnsignedVec);
-
- ASSERT_EQ(InstrList.size(), UnsignedVec.size());
- ASSERT_EQ(UnsignedVec.size(), static_cast<unsigned>(3));
- ASSERT_NE(UnsignedVec[0], UnsignedVec[1]);
-}
-
-// Check that when the operands in getelementpointer instructions do not have
-// the same inbounds modifier, they are not counted as the same.
-TEST(IRInstructionMapper, GetElementPtrDifferentInBounds) {
- StringRef ModuleString = R"(
- %struct.RT = type { i8, [10 x [20 x i32]], i8 }
- %struct.ST = type { i32, double, %struct.RT }
- define i32 @f(%struct.ST* %s, %struct.RT* %r, i64 %a, i64 %b) {
- bb0:
- %0 = getelementptr inbounds %struct.ST, %struct.ST* %s, i64 %a, i32 0
- %1 = getelementptr %struct.ST, %struct.ST* %s, i64 %b, i32 0
- ret i32 0
- })";
- LLVMContext Context;
- std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
-
- std::vector<IRInstructionData *> InstrList;
- std::vector<unsigned> UnsignedVec;
-
- SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
- SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
- IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
- getVectors(*M, Mapper, InstrList, UnsignedVec);
-
- ASSERT_EQ(InstrList.size(), UnsignedVec.size());
- ASSERT_EQ(UnsignedVec.size(), static_cast<unsigned>(3));
- ASSERT_NE(UnsignedVec[0], UnsignedVec[1]);
-}
-
-// Checks that indirect call instructions are mapped to be illegal when it is
-// specified to disallow them.
-TEST(IRInstructionMapper, CallsIllegalIndirect) {
- StringRef ModuleString = R"(
- define i32 @f(void()* %func) {
- bb0:
- call void %func()
- ret i32 0
- })";
- LLVMContext Context;
- std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
-
- std::vector<IRInstructionData *> InstrList;
- std::vector<unsigned> UnsignedVec;
-
- SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
- SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
- IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
- Mapper.InstClassifier.EnableIndirectCalls = false;
- getVectors(*M, Mapper, InstrList, UnsignedVec);
-
- ASSERT_EQ(InstrList.size(), UnsignedVec.size());
- ASSERT_EQ(UnsignedVec.size(), static_cast<unsigned>(1));
- ASSERT_GT(UnsignedVec[0], Mapper.IllegalInstrNumber);
-}
-
-// Checks that indirect call instructions are mapped to be legal when it is not
-// specified to disallow them.
-TEST(IRInstructionMapper, CallsLegalIndirect) {
- StringRef ModuleString = R"(
- define i32 @f(void()* %func) {
- bb0:
- call void %func()
- call void %func()
- ret i32 0
- })";
- LLVMContext Context;
- std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
-
- std::vector<IRInstructionData *> InstrList;
- std::vector<unsigned> UnsignedVec;
-
- SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
- SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
- IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
- Mapper.InstClassifier.EnableIndirectCalls = true;
- getVectors(*M, Mapper, InstrList, UnsignedVec);
-
- ASSERT_EQ(InstrList.size(), UnsignedVec.size());
- ASSERT_EQ(UnsignedVec.size(), static_cast<unsigned>(3));
-}
-
-// Checks that a call instruction is mapped to be legal. Here we check that
-// a call with the same name, and same types are mapped to the same
-// value.
-TEST(IRInstructionMapper, CallsSameTypeSameName) {
- StringRef ModuleString = R"(
- declare i32 @f1(i32, i32)
- define i32 @f(i32 %a, i32 %b) {
- bb0:
- %0 = call i32 @f1(i32 %a, i32 %b)
- %1 = call i32 @f1(i32 %a, i32 %b)
- ret i32 0
- })";
- LLVMContext Context;
- std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
-
- std::vector<IRInstructionData *> InstrList;
- std::vector<unsigned> UnsignedVec;
-
- SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
- SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
- IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
- getVectors(*M, Mapper, InstrList, UnsignedVec);
-
- ASSERT_EQ(InstrList.size(), UnsignedVec.size());
- ASSERT_EQ(UnsignedVec.size(), static_cast<unsigned>(3));
- ASSERT_EQ(UnsignedVec[0], UnsignedVec[1]);
-}
-
-// Here we check that a calls with different names, but the same arguments types
-// are mapped to different value when specified that the name must match.
-TEST(IRInstructionMapper, CallsSameArgTypeDifferentNameDisallowed) {
- StringRef ModuleString = R"(
- declare i32 @f1(i32, i32)
- declare i32 @f2(i32, i32)
- define i32 @f(i32 %a, i32 %b) {
- bb0:
- %0 = call i32 @f1(i32 %a, i32 %b)
- %1 = call i32 @f2(i32 %a, i32 %b)
- ret i32 0
- })";
- LLVMContext Context;
- std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
-
- std::vector<IRInstructionData *> InstrList;
- std::vector<unsigned> UnsignedVec;
-
- SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
- SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
- IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
- Mapper.EnableMatchCallsByName = true;
- getVectors(*M, Mapper, InstrList, UnsignedVec);
-
- ASSERT_EQ(InstrList.size(), UnsignedVec.size());
- ASSERT_EQ(UnsignedVec.size(), static_cast<unsigned>(3));
- ASSERT_NE(UnsignedVec[0], UnsignedVec[1]);
-}
-
-// Here we check that a calls with different names, but the same arguments types
-// are mapped to the same value when it is not specifed that they must match.
-TEST(IRInstructionMapper, CallsSameArgTypeDifferentName) {
- StringRef ModuleString = R"(
- declare i32 @f1(i32, i32)
- declare i32 @f2(i32, i32)
- define i32 @f(i32 %a, i32 %b) {
- bb0:
- %0 = call i32 @f1(i32 %a, i32 %b)
- %1 = call i32 @f2(i32 %a, i32 %b)
- ret i32 0
- })";
- LLVMContext Context;
- std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
-
- std::vector<IRInstructionData *> InstrList;
- std::vector<unsigned> UnsignedVec;
-
- SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
- SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
- IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
- Mapper.EnableMatchCallsByName = false;
- getVectors(*M, Mapper, InstrList, UnsignedVec);
-
- ASSERT_EQ(InstrList.size(), UnsignedVec.size());
- ASSERT_EQ(UnsignedVec.size(), static_cast<unsigned>(3));
- ASSERT_EQ(UnsignedVec[0], UnsignedVec[1]);
-}
-
-// Here we check that a calls with different names, and different arguments
-// types are mapped to different value.
-TEST(IRInstructionMapper, CallsDifferentArgTypeDifferentName) {
- StringRef ModuleString = R"(
- declare i32 @f1(i32, i32)
- declare i32 @f2(i32)
- define i32 @f(i32 %a, i32 %b) {
- bb0:
- %0 = call i32 @f1(i32 %a, i32 %b)
- %1 = call i32 @f2(i32 %a)
- ret i32 0
- })";
- LLVMContext Context;
- std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
-
- std::vector<IRInstructionData *> InstrList;
- std::vector<unsigned> UnsignedVec;
-
- SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
- SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
- IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
- getVectors(*M, Mapper, InstrList, UnsignedVec);
-
- ASSERT_EQ(InstrList.size(), UnsignedVec.size());
- ASSERT_EQ(UnsignedVec.size(), static_cast<unsigned>(3));
- ASSERT_NE(UnsignedVec[0], UnsignedVec[1]);
-}
-
-// Here we check that calls with different names, and different return
-// types are mapped to different value.
-TEST(IRInstructionMapper, CallsDifferentReturnTypeDifferentName) {
- StringRef ModuleString = R"(
- declare i64 @f1(i32, i32)
- declare i32 @f2(i32, i32)
- define i32 @f(i32 %a, i32 %b) {
- bb0:
- %0 = call i64 @f1(i32 %a, i32 %b)
- %1 = call i32 @f2(i32 %a, i32 %b)
- ret i32 0
- })";
- LLVMContext Context;
- std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
-
- std::vector<IRInstructionData *> InstrList;
- std::vector<unsigned> UnsignedVec;
-
- SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
- SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
- IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
- getVectors(*M, Mapper, InstrList, UnsignedVec);
-
- ASSERT_EQ(InstrList.size(), UnsignedVec.size());
- ASSERT_EQ(UnsignedVec.size(), static_cast<unsigned>(3));
- ASSERT_NE(UnsignedVec[0], UnsignedVec[1]);
-}
-
-// Here we check that calls with the same name, types, and parameters map to the
-// same unsigned integer.
-TEST(IRInstructionMapper, CallsSameParameters) {
- StringRef ModuleString = R"(
- declare i32 @f1(i32, i32)
- define i32 @f(i32 %a, i32 %b) {
- bb0:
- %0 = tail call fastcc i32 @f1(i32 %a, i32 %b)
- %1 = tail call fastcc i32 @f1(i32 %a, i32 %b)
- ret i32 0
- })";
- LLVMContext Context;
- std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
-
- std::vector<IRInstructionData *> InstrList;
- std::vector<unsigned> UnsignedVec;
-
- SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
- SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
- IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
- getVectors(*M, Mapper, InstrList, UnsignedVec);
-
- ASSERT_EQ(InstrList.size(), UnsignedVec.size());
- ASSERT_EQ(UnsignedVec.size(), static_cast<unsigned>(3));
- ASSERT_EQ(UnsignedVec[0], UnsignedVec[1]);
-}
-
-// Here we check that calls with different tail call settings are mapped to
-// different values.
-TEST(IRInstructionMapper, CallsDifferentTails) {
- StringRef ModuleString = R"(
- declare i32 @f1(i32, i32)
- define i32 @f(i32 %a, i32 %b) {
- bb0:
- %0 = tail call i32 @f1(i32 %a, i32 %b)
- %1 = call i32 @f1(i32 %a, i32 %b)
- ret i32 0
- })";
- LLVMContext Context;
- std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
-
- std::vector<IRInstructionData *> InstrList;
- std::vector<unsigned> UnsignedVec;
-
- SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
- SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
- IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
- getVectors(*M, Mapper, InstrList, UnsignedVec);
-
- ASSERT_EQ(InstrList.size(), UnsignedVec.size());
- ASSERT_EQ(UnsignedVec.size(), static_cast<unsigned>(3));
- ASSERT_NE(UnsignedVec[0], UnsignedVec[1]);
-}
-
-// Here we check that calls with different calling convention settings are
-// mapped to different values.
-TEST(IRInstructionMapper, CallsDifferentCallingConventions) {
- StringRef ModuleString = R"(
- declare i32 @f1(i32, i32)
- define i32 @f(i32 %a, i32 %b) {
- bb0:
- %0 = call fastcc i32 @f1(i32 %a, i32 %b)
- %1 = call i32 @f1(i32 %a, i32 %b)
- ret i32 0
- })";
- LLVMContext Context;
- std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
-
- std::vector<IRInstructionData *> InstrList;
- std::vector<unsigned> UnsignedVec;
-
- SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
- SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
- IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
- getVectors(*M, Mapper, InstrList, UnsignedVec);
-
- ASSERT_EQ(InstrList.size(), UnsignedVec.size());
- ASSERT_EQ(UnsignedVec.size(), static_cast<unsigned>(3));
- ASSERT_NE(UnsignedVec[0], UnsignedVec[1]);
-}
-
-// Checks that an invoke instruction is mapped to be illegal. Invoke
-// instructions are considered to be illegal because of the change in the
-// control flow that is currently not recognized.
-TEST(IRInstructionMapper, InvokeIllegal) {
- StringRef ModuleString = R"(
- define i32 @f(ptr %gep1, i32 %b) {
- then:
- invoke i32 undef(ptr undef)
- to label %invoke unwind label %lpad
-
- invoke:
- unreachable
-
- lpad:
- landingpad { ptr, i32 }
- catch ptr null
- unreachable
- })";
- LLVMContext Context;
- std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
-
- std::vector<IRInstructionData *> InstrList;
- std::vector<unsigned> UnsignedVec;
-
- SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
- SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
- IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
- getVectors(*M, Mapper, InstrList, UnsignedVec);
-
- ASSERT_EQ(InstrList.size(), UnsignedVec.size());
- ASSERT_EQ(UnsignedVec.size(), static_cast<unsigned>(1));
- ASSERT_GT(UnsignedVec[0], Mapper.IllegalInstrNumber);
-}
-
-// Checks that an callbr instructions are considered to be illegal. Callbr
-// instructions are considered to be illegal because of the change in the
-// control flow that is currently not recognized.
-TEST(IRInstructionMapper, CallBrInstIllegal) {
- StringRef ModuleString = R"(
- define void @test() {
- fail:
- ret void
- }
-
- define i32 @f(i32 %a, i32 %b) {
- bb0:
- callbr void asm "xorl $0, $0; jmp ${1:l}", "r,X,~{dirflag},~{fpsr},~{flags}"(i32 %a, ptr blockaddress(@test, %fail)) to label %normal [label %fail]
- fail:
- ret i32 0
- normal:
- ret i32 0
- })";
- LLVMContext Context;
- std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
-
- std::vector<IRInstructionData *> InstrList;
- std::vector<unsigned> UnsignedVec;
-
- SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
- SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
- IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
- getVectors(*M, Mapper, InstrList, UnsignedVec);
-
- ASSERT_EQ(InstrList.size(), UnsignedVec.size());
- ASSERT_EQ(UnsignedVec.size(), static_cast<unsigned>(1));
- ASSERT_GT(UnsignedVec[0], Mapper.IllegalInstrNumber);
-}
-
-// Checks that an debuginfo records are mapped to be invisible. Since they
-// do not semantically change the program, they can be recognized as similar.
-TEST(IRInstructionMapper, DebugInfoInvisible) {
- StringRef ModuleString = R"(
- define i32 @f(i32 %a, i32 %b) {
- then:
- %0 = add i32 %a, %b
- #dbg_value(i32 0, !0, !0, !1)
- %1 = add i32 %a, %b
- ret i32 0
- }
-
- !0 = distinct !{!"test\00", i32 10}
- !1 = !DILocation(line: 1, column: 1, scope: !{}))";
- LLVMContext Context;
- std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
-
- std::vector<IRInstructionData *> InstrList;
- std::vector<unsigned> UnsignedVec;
-
- SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
- SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
- IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
- getVectors(*M, Mapper, InstrList, UnsignedVec);
-
- ASSERT_EQ(InstrList.size(), UnsignedVec.size());
- ASSERT_EQ(UnsignedVec.size(), static_cast<unsigned>(3));
-}
-
-// The following are all exception handling intrinsics. We do not currently
-// handle these instruction because they are very context dependent.
-
-// Checks that an eh.typeid.for intrinsic is mapped to be illegal.
-TEST(IRInstructionMapper, ExceptionHandlingTypeIdIllegal) {
- StringRef ModuleString = R"(
- @_ZTIi = external constant ptr
- define i32 @f() {
- then:
- %0 = call i32 @llvm.eh.typeid.for(ptr @_ZTIi)
- ret i32 0
- }
-
- declare i32 @llvm.eh.typeid.for(ptr))";
- LLVMContext Context;
- std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
-
- std::vector<IRInstructionData *> InstrList;
- std::vector<unsigned> UnsignedVec;
-
- SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
- SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
- IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
- getVectors(*M, Mapper, InstrList, UnsignedVec);
-
- ASSERT_EQ(InstrList.size(), UnsignedVec.size());
- ASSERT_EQ(UnsignedVec.size(), static_cast<unsigned>(1));
- ASSERT_GT(UnsignedVec[0], Mapper.IllegalInstrNumber);
-}
-
-// Checks that an eh.exceptioncode intrinsic is mapped to be illegal.
-TEST(IRInstructionMapper, ExceptionHandlingExceptionCodeIllegal) {
- StringRef ModuleString = R"(
- define i32 @f(i32 %a, i32 %b) {
- entry:
- %0 = catchswitch within none [label %__except] unwind to caller
-
- __except:
- %1 = catchpad within %0 [ptr null]
- catchret from %1 to label %__except
-
- then:
- %2 = call i32 @llvm.eh.exceptioncode(token %1)
- ret i32 0
- }
-
- declare i32 @llvm.eh.exceptioncode(token))";
- LLVMContext Context;
- std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
-
- std::vector<IRInstructionData *> InstrList;
- std::vector<unsigned> UnsignedVec;
-
- SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
- SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
- IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
- getVectors(*M, Mapper, InstrList, UnsignedVec);
-
- ASSERT_EQ(InstrList.size(), UnsignedVec.size());
- ASSERT_EQ(UnsignedVec.size(), static_cast<unsigned>(1));
- ASSERT_GT(UnsignedVec[0], Mapper.IllegalInstrNumber);
-}
-
-// Checks that an eh.unwind intrinsic is mapped to be illegal.
-TEST(IRInstructionMapper, ExceptionHandlingUnwindIllegal) {
- StringRef ModuleString = R"(
- define i32 @f(i32 %a, i32 %b) {
- entry:
- call void @llvm.eh.unwind.init()
- ret i32 0
- }
-
- declare void @llvm.eh.unwind.init())";
- LLVMContext Context;
- std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
-
- std::vector<IRInstructionData *> InstrList;
- std::vector<unsigned> UnsignedVec;
-
- SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
- SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
- IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
- getVectors(*M, Mapper, InstrList, UnsignedVec);
-
- ASSERT_EQ(InstrList.size(), UnsignedVec.size());
- ASSERT_EQ(UnsignedVec.size(), static_cast<unsigned>(1));
- ASSERT_GT(UnsignedVec[0], Mapper.IllegalInstrNumber);
-}
-
-// Checks that an eh.exceptionpointer intrinsic is mapped to be illegal.
-TEST(IRInstructionMapper, ExceptionHandlingExceptionPointerIllegal) {
- StringRef ModuleString = R"(
- define i32 @f(i32 %a, i32 %b) {
- entry:
- %0 = call ptr @llvm.eh.exceptionpointer.p0i8(i32 0)
- ret i32 0
- }
-
- declare ptr @llvm.eh.exceptionpointer.p0i8(i32))";
- LLVMContext Context;
- std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
-
- std::vector<IRInstructionData *> InstrList;
- std::vector<unsigned> UnsignedVec;
-
- SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
- SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
- IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
- getVectors(*M, Mapper, InstrList, UnsignedVec);
-
- ASSERT_EQ(InstrList.size(), UnsignedVec.size());
- ASSERT_EQ(UnsignedVec.size(), static_cast<unsigned>(1));
- ASSERT_GT(UnsignedVec[0], Mapper.IllegalInstrNumber);
-}
-
-// Checks that a catchpad instruction is mapped to an illegal value.
-TEST(IRInstructionMapper, CatchpadIllegal) {
- StringRef ModuleString = R"(
- declare void @llvm.donothing() nounwind readnone
-
- define void @function() personality i8 3 {
- entry:
- invoke void @llvm.donothing() to label %normal unwind label %exception
- exception:
- %cs1 = catchswitch within none [label %catchpad1] unwind to caller
- catchpad1:
- catchpad within %cs1 []
- br label %normal
- normal:
- ret void
- })";
- LLVMContext Context;
- std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
-
- std::vector<IRInstructionData *> InstrList;
- std::vector<unsigned> UnsignedVec;
-
- SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
- SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
- IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
- getVectors(*M, Mapper, InstrList, UnsignedVec);
-
- ASSERT_EQ(InstrList.size(), UnsignedVec.size());
- ASSERT_EQ(UnsignedVec.size(), static_cast<unsigned>(1));
- ASSERT_GT(UnsignedVec[0], Mapper.IllegalInstrNumber);
-}
-
-// Checks that a cleanuppad instruction is mapped to an illegal value.
-TEST(IRInstructionMapper, CleanuppadIllegal) {
- StringRef ModuleString = R"(
- declare void @llvm.donothing() nounwind readnone
-
- define void @function() personality i8 3 {
- entry:
- invoke void @llvm.donothing() to label %normal unwind label %exception
- exception:
- %cs1 = catchswitch within none [label %catchpad1] unwind to caller
- catchpad1:
- %clean = cleanuppad within none []
- br label %normal
- normal:
- ret void
- })";
- LLVMContext Context;
- std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
-
- std::vector<IRInstructionData *> InstrList;
- std::vector<unsigned> UnsignedVec;
-
- SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
- SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
- IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
- getVectors(*M, Mapper, InstrList, UnsignedVec);
-
- ASSERT_EQ(InstrList.size(), UnsignedVec.size());
- ASSERT_EQ(UnsignedVec.size(), static_cast<unsigned>(1));
- ASSERT_GT(UnsignedVec[0], Mapper.IllegalInstrNumber);
-}
-
-// The following three instructions are memory transfer and setting based, which
-// are considered illegal since is extra checking needed to handle the address
-// space checking.
-
-// Checks that a memset instruction is mapped to an illegal value when
-// specified.
-TEST(IRInstructionMapper, MemSetIllegal) {
- StringRef ModuleString = R"(
- declare void @llvm.memset.p0i8.i64(ptr nocapture writeonly, i8, i64, i32, i1)
-
- define i64 @function(i64 %x, i64 %z, i64 %n) {
- entry:
- %pool = alloca [59 x i64], align 4
- %tmp = bitcast ptr %pool to ptr
- call void @llvm.memset.p0i8.i64(ptr nonnull %tmp, i8 0, i64 236, i32 4, i1 false)
- %cmp3 = icmp eq i64 %n, 0
- %a = add i64 %x, %z
- %c = add i64 %x, %z
- ret i64 0
- })";
- LLVMContext Context;
- std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
-
- std::vector<IRInstructionData *> InstrList;
- std::vector<unsigned> UnsignedVec;
-
- SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
- SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
- IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
- Mapper.InstClassifier.EnableIntrinsics = false;
- getVectors(*M, Mapper, InstrList, UnsignedVec);
-
- ASSERT_EQ(InstrList.size(), UnsignedVec.size());
- ASSERT_EQ(UnsignedVec.size(), static_cast<unsigned>(7));
- ASSERT_TRUE(UnsignedVec[2] < UnsignedVec[0]);
-}
-
-// Checks that a memcpy instruction is mapped to an illegal value when
-// specified.
-TEST(IRInstructionMapper, MemCpyIllegal) {
- StringRef ModuleString = R"(
- declare void @llvm.memcpy.p0i8.i64(ptr nocapture writeonly, i8, i64, i32, i1)
-
- define i64 @function(i64 %x, i64 %z, i64 %n) {
- entry:
- %pool = alloca [59 x i64], align 4
- %tmp = bitcast ptr %pool to ptr
- call void @llvm.memcpy.p0i8.i64(ptr nonnull %tmp, i8 0, i64 236, i32 4, i1 false)
- %cmp3 = icmp eq i64 %n, 0
- %a = add i64 %x, %z
- %c = add i64 %x, %z
- ret i64 0
- })";
- LLVMContext Context;
- std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
-
- std::vector<IRInstructionData *> InstrList;
- std::vector<unsigned> UnsignedVec;
-
- SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
- SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
- IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
- Mapper.InstClassifier.EnableIntrinsics = false;
- getVectors(*M, Mapper, InstrList, UnsignedVec);
-
- ASSERT_EQ(InstrList.size(), UnsignedVec.size());
- ASSERT_EQ(UnsignedVec.size(), static_cast<unsigned>(7));
- ASSERT_GT(UnsignedVec[2], UnsignedVec[3]);
- ASSERT_LT(UnsignedVec[2], UnsignedVec[0]);
-}
-
-// Checks that a memmove instruction is mapped to an illegal value when
-// specified.
-TEST(IRInstructionMapper, MemMoveIllegal) {
- StringRef ModuleString = R"(
- declare void @llvm.memmove.p0i8.i64(ptr nocapture writeonly, i8, i64, i32, i1)
-
- define i64 @function(i64 %x, i64 %z, i64 %n) {
- entry:
- %pool = alloca [59 x i64], align 4
- %tmp = bitcast ptr %pool to ptr
- call void @llvm.memmove.p0i8.i64(ptr nonnull %tmp, i8 0, i64 236, i32 4, i1 false)
- %cmp3 = icmp eq i64 %n, 0
- %a = add i64 %x, %z
- %c = add i64 %x, %z
- ret i64 0
- })";
- LLVMContext Context;
- std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
-
- std::vector<IRInstructionData *> InstrList;
- std::vector<unsigned> UnsignedVec;
-
- SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
- SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
- IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
- Mapper.InstClassifier.EnableIntrinsics = false;
- getVectors(*M, Mapper, InstrList, UnsignedVec);
-
- ASSERT_EQ(InstrList.size(), UnsignedVec.size());
- ASSERT_EQ(UnsignedVec.size(), static_cast<unsigned>(7));
- ASSERT_LT(UnsignedVec[2], UnsignedVec[0]);
-}
-
-// Checks that mem* instructions are mapped to an legal value when not
-// specified, and that all the intrinsics are marked differently.
-TEST(IRInstructionMapper, MemOpsLegal) {
- StringRef ModuleString = R"(
- declare void @llvm.memmove.p0i8.i64(ptr nocapture writeonly, i8, i64, i32, i1)
- declare void @llvm.memcpy.p0i8.i64(ptr nocapture writeonly, i8, i64, i32, i1)
- declare void @llvm.memset.p0i8.i64(ptr nocapture writeonly, i8, i64, i32, i1)
-
- define i64 @function(i64 %x, i64 %z, i64 %n) {
- entry:
- %pool = alloca [59 x i64], align 4
- %tmp = bitcast ptr %pool to ptr
- call void @llvm.memmove.p0i8.i64(ptr nonnull %tmp, i8 0, i64 236, i32 4, i1 false)
- call void @llvm.memcpy.p0i8.i64(ptr nonnull %tmp, i8 0, i64 236, i32 4, i1 false)
- call void @llvm.memset.p0i8.i64(ptr nonnull %tmp, i8 0, i64 236, i32 4, i1 false)
- %cmp3 = icmp eq i64 %n, 0
- %a = add i64 %x, %z
- %c = add i64 %x, %z
- ret i64 0
- })";
- LLVMContext Context;
- std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
-
- std::vector<IRInstructionData *> InstrList;
- std::vector<unsigned> UnsignedVec;
-
- SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
- SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
- IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
- Mapper.InstClassifier.EnableIntrinsics = true;
- getVectors(*M, Mapper, InstrList, UnsignedVec);
-
- ASSERT_EQ(InstrList.size(), UnsignedVec.size());
- ASSERT_EQ(UnsignedVec.size(), static_cast<unsigned>(9));
- ASSERT_LT(UnsignedVec[2], UnsignedVec[3]);
- ASSERT_LT(UnsignedVec[3], UnsignedVec[4]);
- ASSERT_LT(UnsignedVec[4], UnsignedVec[5]);
-}
-
-// Checks that a variable argument instructions are mapped to an illegal value.
-// We exclude variable argument instructions since variable arguments
-// requires extra checking of the argument list.
-TEST(IRInstructionMapper, VarArgsIllegal) {
- StringRef ModuleString = R"(
- declare void @llvm.va_start(ptr)
- declare void @llvm.va_copy(ptr, ptr)
- declare void @llvm.va_end(ptr)
-
- define i32 @func1(i32 %a, double %b, ptr %v, ...) nounwind {
- entry:
- %a.addr = alloca i32, align 4
- %b.addr = alloca double, align 8
- %ap = alloca ptr, align 4
- %c = alloca i32, align 4
- store i32 %a, ptr %a.addr, align 4
- store double %b, ptr %b.addr, align 8
- %ap1 = bitcast ptr %ap to ptr
- call void @llvm.va_start(ptr %ap1)
- store double %b, ptr %b.addr, align 8
- store double %b, ptr %b.addr, align 8
- %0 = va_arg ptr %ap, i32
- store double %b, ptr %b.addr, align 8
- store double %b, ptr %b.addr, align 8
- call void @llvm.va_copy(ptr %v, ptr %ap1)
- store double %b, ptr %b.addr, align 8
- store double %b, ptr %b.addr, align 8
- call void @llvm.va_end(ptr %ap1)
- store i32 %0, ptr %c, align 4
- %tmp = load i32, ptr %c, align 4
- ret i32 %tmp
- })";
- LLVMContext Context;
- std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
-
- std::vector<IRInstructionData *> InstrList;
- std::vector<unsigned> UnsignedVec;
-
- SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
- SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
- IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
- Mapper.InstClassifier.EnableIntrinsics = false;
- getVectors(*M, Mapper, InstrList, UnsignedVec);
-
- ASSERT_EQ(InstrList.size(), UnsignedVec.size());
- ASSERT_EQ(UnsignedVec.size(), static_cast<unsigned>(17));
- ASSERT_TRUE(UnsignedVec[7] < UnsignedVec[0]);
- ASSERT_TRUE(UnsignedVec[13] < UnsignedVec[10]);
- ASSERT_TRUE(UnsignedVec[16] < UnsignedVec[13]);
-}
-
-// Check the length of adding two illegal instructions one after th other. We
-// should find that only one element is added for each illegal range.
-TEST(IRInstructionMapper, RepeatedIllegalLength) {
- StringRef ModuleString = R"(
- define i32 @f(i32 %a, i32 %b) {
- bb0:
- %0 = add i32 %a, %b
- %1 = mul i32 %a, %b
- %2 = alloca i32
- %3 = alloca i32
- %4 = add i32 %a, %b
- %5 = mul i32 %a, %b
- ret i32 0
- })";
- LLVMContext Context;
- std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
-
- std::vector<IRInstructionData *> InstrList;
- std::vector<unsigned> UnsignedVec;
-
- SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
- SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
- IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
- getVectors(*M, Mapper, InstrList, UnsignedVec);
-
- // Check that the size of the unsigned vector and the instruction list are the
- // same as a safety check.
- ASSERT_TRUE(InstrList.size() == UnsignedVec.size());
-
- // Make sure that the unsigned vector is the expected size.
- ASSERT_TRUE(UnsignedVec.size() == 6);
-}
-
-// A helper function that accepts an instruction list from a module made up of
-// two blocks of two legal instructions and terminator, and checks them for
-// instruction similarity.
-static bool longSimCandCompare(std::vector<IRInstructionData *> &InstrList,
- bool Structure = false, unsigned Length = 2,
- unsigned StartIdxOne = 0,
- unsigned StartIdxTwo = 3) {
- std::vector<IRInstructionData *>::iterator Start, End;
-
- Start = InstrList.begin();
- End = InstrList.begin();
-
- std::advance(End, StartIdxOne + Length - 1);
- IRSimilarityCandidate Cand1(StartIdxOne, Length, *Start, *End);
-
- Start = InstrList.begin();
- End = InstrList.begin();
-
- std::advance(Start, StartIdxTwo);
- std::advance(End, StartIdxTwo + Length - 1);
- IRSimilarityCandidate Cand2(StartIdxTwo, Length, *Start, *End);
- if (Structure)
- return IRSimilarityCandidate::compareStructure(Cand1, Cand2);
- return IRSimilarityCandidate::isSimilar(Cand1, Cand2);
-}
-
-// Checks that two adds with commuted operands are considered to be the same
-// instructions.
-TEST(IRSimilarityCandidate, CheckIdenticalInstructions) {
- StringRef ModuleString = R"(
- define i32 @f(i32 %a, i32 %b) {
- bb0:
- %0 = add i32 %a, %b
- %1 = add i32 %b, %a
- ret i32 0
- })";
- LLVMContext Context;
- std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
-
- std::vector<IRInstructionData *> InstrList;
- std::vector<unsigned> UnsignedVec;
-
- SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
- SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
- IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
- getVectors(*M, Mapper, InstrList, UnsignedVec);
-
- // Check to make sure that we have a long enough region.
- ASSERT_EQ(InstrList.size(), static_cast<unsigned>(3));
- // Check that the instructions were added correctly to both vectors.
- ASSERT_TRUE(InstrList.size() == UnsignedVec.size());
-
- std::vector<IRInstructionData *>::iterator Start, End;
- Start = InstrList.begin();
- End = InstrList.begin();
- std::advance(End, 1);
- IRSimilarityCandidate Cand1(0, 2, *Start, *End);
- IRSimilarityCandidate Cand2(0, 2, *Start, *End);
-
- ASSERT_TRUE(IRSimilarityCandidate::isSimilar(Cand1, Cand2));
-}
-
-// Checks that comparison instructions are found to be similar instructions
-// when the operands are flipped and the predicate is also swapped.
-TEST(IRSimilarityCandidate, PredicateIsomorphism) {
- StringRef ModuleString = R"(
- define i32 @f(i32 %a, i32 %b) {
- bb0:
- %0 = icmp sgt i32 %a, %b
- %1 = add i32 %b, %a
- br label %bb1
- bb1:
- %2 = icmp slt i32 %a, %b
- %3 = add i32 %a, %b
- ret i32 0
- })";
- LLVMContext Context;
- std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
-
- std::vector<IRInstructionData *> InstrList;
- std::vector<unsigned> UnsignedVec;
-
- SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
- SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
- IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
- getVectors(*M, Mapper, InstrList, UnsignedVec);
-
- ASSERT_TRUE(InstrList.size() > 5);
- ASSERT_TRUE(InstrList.size() == UnsignedVec.size());
-
- std::vector<IRInstructionData *>::iterator Start, End;
- Start = InstrList.begin();
- End = InstrList.begin();
-
- std::advance(End, 1);
- IRSimilarityCandidate Cand1(0, 2, *Start, *End);
-
- Start = InstrList.begin();
- End = InstrList.begin();
-
- std::advance(Start, 3);
- std::advance(End, 4);
- IRSimilarityCandidate Cand2(3, 2, *Start, *End);
-
- ASSERT_TRUE(IRSimilarityCandidate::isSimilar(Cand1, Cand2));
-}
-
-// Checks that IRSimilarityCandidates wrapping these two regions of instructions
-// are able to differentiate between instructions that have different opcodes.
-TEST(IRSimilarityCandidate, CheckRegionsDifferentInstruction) {
- StringRef ModuleString = R"(
- define i32 @f(i32 %a, i32 %b) {
- bb0:
- %0 = add i32 %a, %b
- %1 = add i32 %b, %a
- ret i32 0
- bb1:
- %2 = sub i32 %a, %b
- %3 = add i32 %b, %a
- ret i32 0
- })";
- LLVMContext Context;
- std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
-
- std::vector<IRInstructionData *> InstrList;
- std::vector<unsigned> UnsignedVec;
-
- SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
- SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
- IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
- getVectors(*M, Mapper, InstrList, UnsignedVec);
-
- // Check to make sure that we have a long enough region.
- ASSERT_EQ(InstrList.size(), static_cast<unsigned>(6));
- // Check that the instructions were added correctly to both vectors.
- ASSERT_TRUE(InstrList.size() == UnsignedVec.size());
-
- ASSERT_FALSE(longSimCandCompare(InstrList));
-}
-
-// Checks that IRSimilarityCandidates wrapping these two regions of instructions
-// are able to differentiate between instructions that have different types.
-TEST(IRSimilarityCandidate, CheckRegionsDifferentTypes) {
- StringRef ModuleString = R"(
- define i32 @f(i32 %a, i32 %b, i64 %c, i64 %d) {
- bb0:
- %0 = add i32 %a, %b
- %1 = add i32 %b, %a
- ret i32 0
- bb1:
- %2 = add i64 %c, %d
- %3 = add i64 %d, %c
- ret i32 0
- })";
- LLVMContext Context;
- std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
-
- std::vector<IRInstructionData *> InstrList;
- std::vector<unsigned> UnsignedVec;
-
- SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
- SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
- IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
- getVectors(*M, Mapper, InstrList, UnsignedVec);
-
- // Check to make sure that we have a long enough region.
- ASSERT_EQ(InstrList.size(), static_cast<unsigned>(6));
- // Check that the instructions were added correctly to both vectors.
- ASSERT_TRUE(InstrList.size() == UnsignedVec.size());
-
- ASSERT_FALSE(longSimCandCompare(InstrList));
-}
-
-// Check that debug records do not impact similarity. They are marked as
-// invisible.
-TEST(IRSimilarityCandidate, IdenticalWithDebug) {
- StringRef ModuleString = R"(
- define i32 @f(i32 %a, i32 %b) {
- bb0:
- %0 = add i32 %a, %b
- #dbg_value(i32 0, !0, !0, !2)
- %1 = add i32 %b, %a
- ret i32 0
- bb1:
- %2 = add i32 %a, %b
- #dbg_value(i32 1, !1, !1, !2)
- %3 = add i32 %b, %a
- ret i32 0
- bb2:
- %4 = add i32 %a, %b
- %5 = add i32 %b, %a
- ret i32 0
- }
-
- !0 = distinct !{!"test\00", i32 10}
- !1 = distinct !{!"test\00", i32 11}
- !2 = !DILocation(line: 1, column: 1, scope: !{}))";
- LLVMContext Context;
- std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
-
- std::vector<IRInstructionData *> InstrList;
- std::vector<unsigned> UnsignedVec;
-
- SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
- SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
- IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
- getVectors(*M, Mapper, InstrList, UnsignedVec);
-
- // Check to make sure that we have a long enough region.
- ASSERT_EQ(InstrList.size(), static_cast<unsigned>(9));
- // Check that the instructions were added correctly to both vectors.
- ASSERT_TRUE(InstrList.size() == UnsignedVec.size());
-
- ASSERT_TRUE(longSimCandCompare(InstrList));
-}
-
-// Checks that IRSimilarityCandidates that include illegal instructions, are not
-// considered to be the same set of instructions. In these sets of instructions
-// the allocas are illegal.
-TEST(IRSimilarityCandidate, IllegalInCandidate) {
- StringRef ModuleString = R"(
- define i32 @f(i32 %a, i32 %b) {
- bb0:
- %0 = add i32 %a, %b
- %1 = add i32 %a, %b
- %2 = alloca i32
- ret i32 0
- bb1:
- %3 = add i32 %a, %b
- %4 = add i32 %a, %b
- %5 = alloca i32
- ret i32 0
- })";
- LLVMContext Context;
- std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
-
- std::vector<IRInstructionData *> InstrList;
- std::vector<unsigned> UnsignedVec;
-
- SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
- SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
- IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
- getVectors(*M, Mapper, InstrList, UnsignedVec);
-
- // Check to make sure that we have a long enough region.
- ASSERT_EQ(InstrList.size(), static_cast<unsigned>(6));
- // Check that the instructions were added correctly to both vectors.
- ASSERT_TRUE(InstrList.size() == UnsignedVec.size());
-
- std::vector<IRInstructionData *>::iterator Start, End;
-
- Start = InstrList.begin();
- End = InstrList.begin();
-
- std::advance(End, 2);
- IRSimilarityCandidate Cand1(0, 3, *Start, *End);
-
- Start = InstrList.begin();
- End = InstrList.begin();
-
- std::advance(Start, 3);
- std::advance(End, 5);
- IRSimilarityCandidate Cand2(3, 3, *Start, *End);
- ASSERT_FALSE(IRSimilarityCandidate::isSimilar(Cand1, Cand2));
-}
-
-// Checks that different structure, in this case, where we introduce a new
-// needed input in one region, is recognized as different.
-TEST(IRSimilarityCandidate, DifferentStructure) {
- StringRef ModuleString = R"(
- define i32 @f(i32 %a, i32 %b) {
- bb0:
- %0 = add i32 %a, %b
- %1 = add i32 %b, %a
- ret i32 0
- bb1:
- %2 = add i32 %a, %b
- %3 = add i32 %b, %0
- ret i32 0
- })";
- LLVMContext Context;
- std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
-
- std::vector<IRInstructionData *> InstrList;
- std::vector<unsigned> UnsignedVec;
-
- SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
- SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
- IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
- getVectors(*M, Mapper, InstrList, UnsignedVec);
-
- // Check to make sure that we have a long enough region.
- ASSERT_EQ(InstrList.size(), static_cast<unsigned>(6));
- // Check that the instructions were added correctly to both vectors.
- ASSERT_TRUE(InstrList.size() == UnsignedVec.size());
-
- ASSERT_FALSE(longSimCandCompare(InstrList, true));
-}
-
-// Checks that comparison instructions are found to have the same structure
-// when the operands are flipped and the predicate is also swapped.
-TEST(IRSimilarityCandidate, PredicateIsomorphismStructure) {
- StringRef ModuleString = R"(
- define i32 @f(i32 %a, i32 %b) {
- bb0:
- %0 = icmp sgt i32 %a, %b
- %1 = add i32 %a, %b
- br label %bb1
- bb1:
- %2 = icmp slt i32 %b, %a
- %3 = add i32 %a, %b
- ret i32 0
- })";
- LLVMContext Context;
- std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
-
- std::vector<IRInstructionData *> InstrList;
- std::vector<unsigned> UnsignedVec;
-
- SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
- SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
- IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
- getVectors(*M, Mapper, InstrList, UnsignedVec);
-
- ASSERT_TRUE(InstrList.size() > 5);
- ASSERT_TRUE(InstrList.size() == UnsignedVec.size());
-
- ASSERT_TRUE(longSimCandCompare(InstrList, true));
-}
-
-// Checks that different predicates are counted as diferent.
-TEST(IRSimilarityCandidate, PredicateDifference) {
- StringRef ModuleString = R"(
- define i32 @f(i32 %a, i32 %b) {
- bb0:
- %0 = icmp sge i32 %a, %b
- %1 = add i32 %b, %a
- br label %bb1
- bb1:
- %2 = icmp slt i32 %b, %a
- %3 = add i32 %a, %b
- ret i32 0
- })";
- LLVMContext Context;
- std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
-
- std::vector<IRInstructionData *> InstrList;
- std::vector<unsigned> UnsignedVec;
-
- SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
- SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
- IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
- getVectors(*M, Mapper, InstrList, UnsignedVec);
-
- ASSERT_TRUE(InstrList.size() > 5);
- ASSERT_TRUE(InstrList.size() == UnsignedVec.size());
-
- ASSERT_FALSE(longSimCandCompare(InstrList));
-}
-
-// Checks that the same structure is recognized between two candidates. The
-// items %a and %b are used in the same way in both sets of instructions.
-TEST(IRSimilarityCandidate, SameStructure) {
- StringRef ModuleString = R"(
- define i32 @f(i32 %a, i32 %b) {
- bb0:
- %0 = add i32 %a, %b
- %1 = sub i32 %b, %a
- ret i32 0
- bb1:
- %2 = add i32 %a, %b
- %3 = sub i32 %b, %a
- ret i32 0
- })";
- LLVMContext Context;
- std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
-
- std::vector<IRInstructionData *> InstrList;
- std::vector<unsigned> UnsignedVec;
-
- SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
- SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
- IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
- getVectors(*M, Mapper, InstrList, UnsignedVec);
-
- // Check to make sure that we have a long enough region.
- ASSERT_EQ(InstrList.size(), static_cast<unsigned>(6));
- // Check that the instructions were added correctly to both vectors.
- ASSERT_TRUE(InstrList.size() == UnsignedVec.size());
-
- ASSERT_TRUE(longSimCandCompare(InstrList, true));
-}
-
-// Checks that the canonical numbering between two candidates matches the found
-// mapping between two candidates.
-TEST(IRSimilarityCandidate, CanonicalNumbering) {
- StringRef ModuleString = R"(
- define i32 @f(i32 %a, i32 %b) {
- bb0:
- %0 = add i32 %a, %b
- %1 = sub i32 %b, %a
- ret i32 0
- bb1:
- %2 = add i32 %a, %b
- %3 = sub i32 %b, %a
- ret i32 0
- })";
- LLVMContext Context;
- std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
-
- std::vector<IRInstructionData *> InstrList;
- std::vector<unsigned> UnsignedVec;
-
- SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
- SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
- IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
- getVectors(*M, Mapper, InstrList, UnsignedVec);
-
- // Check to make sure that we have a long enough region.
- ASSERT_EQ(InstrList.size(), static_cast<unsigned>(6));
- // Check that the instructions were added correctly to both vectors.
- ASSERT_EQ(InstrList.size(), UnsignedVec.size());
-
- std::vector<IRInstructionData *>::iterator Start, End;
-
- Start = InstrList.begin();
- End = InstrList.begin();
-
- std::advance(End, 1);
- IRSimilarityCandidate Cand1(0, 2, *Start, *End);
-
- Start = InstrList.begin();
- End = InstrList.begin();
-
- std::advance(Start, 3);
- std::advance(End, 4);
- IRSimilarityCandidate Cand2(3, 2, *Start, *End);
- DenseMap<unsigned, DenseSet<unsigned>> Mapping1;
- DenseMap<unsigned, DenseSet<unsigned>> Mapping2;
- ASSERT_TRUE(IRSimilarityCandidate::compareStructure(Cand1, Cand2, Mapping1,
- Mapping2));
- IRSimilarityCandidate::createCanonicalMappingFor(Cand1);
- Cand2.createCanonicalRelationFrom(Cand1, Mapping1, Mapping2);
-
- for (std::pair<unsigned, DenseSet<unsigned>> &P : Mapping2) {
- unsigned Source = P.first;
-
- ASSERT_TRUE(Cand2.getCanonicalNum(Source).has_value());
- unsigned Canon = *Cand2.getCanonicalNum(Source);
- ASSERT_TRUE(Cand1.fromCanonicalNum(Canon).has_value());
- unsigned Dest = *Cand1.fromCanonicalNum(Canon);
-
- DenseSet<unsigned>::iterator It = P.second.find(Dest);
- ASSERT_NE(It, P.second.end());
- }
-}
-
-// Checks that the same structure is recognized between two candidates. While
-// the input names are reversed, they still perform the same overall operation.
-TEST(IRSimilarityCandidate, DifferentNameSameStructure) {
- StringRef ModuleString = R"(
- define i32 @f(i32 %a, i32 %b) {
- bb0:
- %0 = add i32 %a, %b
- %1 = add i32 %b, %a
- ret i32 0
- bb1:
- %2 = add i32 %b, %a
- %3 = add i32 %a, %b
- ret i32 0
- })";
- LLVMContext Context;
- std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
-
- std::vector<IRInstructionData *> InstrList;
- std::vector<unsigned> UnsignedVec;
-
- SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
- SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
- IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
- getVectors(*M, Mapper, InstrList, UnsignedVec);
-
- // Check to make sure that we have a long enough region.
- ASSERT_EQ(InstrList.size(), static_cast<unsigned>(6));
- // Check that the instructions were added correctly to both vectors.
- ASSERT_TRUE(InstrList.size() == UnsignedVec.size());
-
- ASSERT_TRUE(longSimCandCompare(InstrList, true));
-}
-
-// Checks that the same structure is recognized between two candidates when
-// the branches target other blocks inside the same region, the relative
-// distance between the blocks must be the same.
-TEST(IRSimilarityCandidate, SameBranchStructureInternal) {
- StringRef ModuleString = R"(
- define i32 @f(i32 %a, i32 %b) {
- bb0:
- %0 = add i32 %a, %b
- %1 = add i32 %b, %a
- br label %bb1
- bb1:
- %2 = add i32 %b, %a
- %3 = add i32 %a, %b
- ret i32 0
- }
-
- define i32 @f2(i32 %a, i32 %b) {
- bb0:
- %0 = add i32 %a, %b
- %1 = add i32 %b, %a
- br label %bb1
- bb1:
- %2 = add i32 %b, %a
- %3 = add i32 %a, %b
- ret i32 0
- })";
- LLVMContext Context;
- std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
-
- std::vector<IRInstructionData *> InstrList;
- std::vector<unsigned> UnsignedVec;
-
- SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
- SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
- IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
- Mapper.InstClassifier.EnableBranches = true;
- Mapper.initializeForBBs(*M);
- getVectors(*M, Mapper, InstrList, UnsignedVec);
-
- // Check to make sure that we have a long enough region.
- ASSERT_EQ(InstrList.size(), static_cast<unsigned>(12));
- // Check that the instructions were added correctly to both vectors.
- ASSERT_TRUE(InstrList.size() == UnsignedVec.size());
-
- ASSERT_TRUE(longSimCandCompare(InstrList, true, 5, 0, 6));
-}
-
-// Checks that the different structure is recognized between two candidates,
-// when the branches target other blocks inside the same region, the relative
-// distance between the blocks must be the same.
-TEST(IRSimilarityCandidate, DifferentBranchStructureInternal) {
- StringRef ModuleString = R"(
- define i32 @f(i32 %a, i32 %b) {
- bb0:
- %0 = add i32 %a, %b
- %1 = add i32 %b, %a
- br label %bb2
- bb1:
- %2 = add i32 %b, %a
- %3 = add i32 %a, %b
- br label %bb2
- bb2:
- %4 = add i32 %b, %a
- %5 = add i32 %a, %b
- ret i32 0
- }
-
- define i32 @f2(i32 %a, i32 %b) {
- bb0:
- %0 = add i32 %a, %b
- %1 = add i32 %b, %a
- br label %bb1
- bb1:
- %2 = add i32 %b, %a
- %3 = add i32 %a, %b
- br label %bb2
- bb2:
- %4 = add i32 %b, %a
- %5 = add i32 %a, %b
- ret i32 0
- })";
- LLVMContext Context;
- std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
-
- std::vector<IRInstructionData *> InstrList;
- std::vector<unsigned> UnsignedVec;
-
- SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
- SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
- IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
- Mapper.InstClassifier.EnableBranches = true;
- Mapper.initializeForBBs(*M);
- getVectors(*M, Mapper, InstrList, UnsignedVec);
-
- // Check to make sure that we have a long enough region.
- ASSERT_EQ(InstrList.size(), static_cast<unsigned>(18));
- // Check that the instructions were added correctly to both vectors.
- ASSERT_TRUE(InstrList.size() == UnsignedVec.size());
-
- ASSERT_FALSE(longSimCandCompare(InstrList, true, 6, 0, 9));
-}
-
-// Checks that the same structure is recognized between two candidates, when
-// the branches target other blocks outside region, the relative distance
-// does not need to be the same.
-TEST(IRSimilarityCandidate, SameBranchStructureOutside) {
- StringRef ModuleString = R"(
- define i32 @f(i32 %a, i32 %b) {
- bb0:
- %0 = add i32 %a, %b
- %1 = add i32 %b, %a
- br label %bb1
- bb1:
- %2 = add i32 %b, %a
- %3 = add i32 %a, %b
- ret i32 0
- }
-
- define i32 @f2(i32 %a, i32 %b) {
- bb0:
- %0 = add i32 %a, %b
- %1 = add i32 %b, %a
- br label %bb1
- bb1:
- %2 = add i32 %b, %a
- %3 = add i32 %a, %b
- ret i32 0
- })";
- LLVMContext Context;
- std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
-
- std::vector<IRInstructionData *> InstrList;
- std::vector<unsigned> UnsignedVec;
-
- SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
- SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
- IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
- Mapper.InstClassifier.EnableBranches = true;
- Mapper.initializeForBBs(*M);
- getVectors(*M, Mapper, InstrList, UnsignedVec);
-
- // Check to make sure that we have a long enough region.
- ASSERT_EQ(InstrList.size(), static_cast<unsigned>(12));
- // Check that the instructions were added correctly to both vectors.
- ASSERT_TRUE(InstrList.size() == UnsignedVec.size());
-
- ASSERT_TRUE(longSimCandCompare(InstrList, true, 3, 0, 6));
-}
-
-// Checks that the same structure is recognized between two candidates, when
-// the branches target other blocks outside region, the relative distance
-// does not need to be the same.
-TEST(IRSimilarityCandidate, DifferentBranchStructureOutside) {
- StringRef ModuleString = R"(
- define i32 @f(i32 %a, i32 %b) {
- bb0:
- %0 = add i32 %a, %b
- %1 = add i32 %b, %a
- br label %bb1
- bb1:
- %2 = add i32 %b, %a
- %3 = add i32 %a, %b
- ret i32 0
- }
-
- define i32 @f2(i32 %a, i32 %b) {
- bb0:
- %0 = add i32 %a, %b
- %1 = add i32 %b, %a
- br label %bb2
- bb1:
- %2 = add i32 %b, %a
- %3 = add i32 %a, %b
- br label %bb2
- bb2:
- %4 = add i32 %b, %a
- %5 = add i32 %a, %b
- ret i32 0
- })";
- LLVMContext Context;
- std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
-
- std::vector<IRInstructionData *> InstrList;
- std::vector<unsigned> UnsignedVec;
-
- SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
- SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
- IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
- Mapper.InstClassifier.EnableBranches = true;
- Mapper.initializeForBBs(*M);
- getVectors(*M, Mapper, InstrList, UnsignedVec);
-
- // Check to make sure that we have a long enough region.
- ASSERT_EQ(InstrList.size(), static_cast<unsigned>(15));
- // Check that the instructions were added correctly to both vectors.
- ASSERT_TRUE(InstrList.size() == UnsignedVec.size());
-
- ASSERT_TRUE(longSimCandCompare(InstrList, true, 3, 0, 6));
-}
-
-// Checks that the same structure is recognized between two candidates,
-// when the phi predecessor are other blocks inside the same region,
-// the relative distance between the blocks must be the same.
-TEST(IRSimilarityCandidate, SamePHIStructureInternal) {
- StringRef ModuleString = R"(
- define i32 @f(i32 %a, i32 %b) {
- bb0:
- br label %bb2
- bb1:
- br label %bb2
- bb2:
- %0 = phi i32 [ %a, %bb0 ], [ %b, %bb1 ]
- %1 = add i32 %b, %a
- %2 = add i32 %a, %b
- ret i32 0
- }
-
- define i32 @f2(i32 %a, i32 %b) {
- bb0:
- br label %bb2
- bb1:
- br label %bb2
- bb2:
- %0 = phi i32 [ %a, %bb0 ], [ %b, %bb1 ]
- %1 = add i32 %b, %a
- %2 = add i32 %a, %b
- ret i32 0
- })";
- LLVMContext Context;
- std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
-
- std::vector<IRInstructionData *> InstrList;
- std::vector<unsigned> UnsignedVec;
-
- SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
- SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
- IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
- Mapper.InstClassifier.EnableBranches = true;
- Mapper.initializeForBBs(*M);
- getVectors(*M, Mapper, InstrList, UnsignedVec);
-
- // Check to make sure that we have a long enough region.
- ASSERT_EQ(InstrList.size(), static_cast<unsigned>(12));
- // Check that the instructions were added correctly to both vectors.
- ASSERT_TRUE(InstrList.size() == UnsignedVec.size());
-
- ASSERT_TRUE(longSimCandCompare(InstrList, true, 4, 0, 6));
-}
-
-// Checks that the different structure is recognized between two candidates,
-// when the phi predecessor are other blocks inside the same region,
-// the relative distance between the blocks must be the same.
-TEST(IRSimilarityCandidate, DifferentPHIStructureInternal) {
- StringRef ModuleString = R"(
- define i32 @f(i32 %a, i32 %b) {
- bb0:
- br label %bb2
- bb1:
- br label %bb2
- bb3:
- br label %bb2
- bb2:
- %0 = phi i32 [ %a, %bb0 ], [ %b, %bb1 ]
- %1 = add i32 %b, %a
- %2 = add i32 %a, %b
- ret i32 0
- }
-
- define i32 @f2(i32 %a, i32 %b) {
- bb0:
- br label %bb2
- bb1:
- br label %bb2
- bb3:
- br label %bb2
- bb2:
- %0 = phi i32 [ %a, %bb0 ], [ %b, %bb3 ]
- %1 = add i32 %b, %a
- %2 = add i32 %a, %b
- ret i32 0
- })";
- LLVMContext Context;
- std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
-
- std::vector<IRInstructionData *> InstrList;
- std::vector<unsigned> UnsignedVec;
-
- SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator;
- SpecificBumpPtrAllocator<IRInstructionDataList> IDLAllocator;
- IRInstructionMapper Mapper(&InstDataAllocator, &IDLAllocator);
- Mapper.InstClassifier.EnableBranches = true;
- Mapper.initializeForBBs(*M);
- getVectors(*M, Mapper, InstrList, UnsignedVec);
-
- // Check to make sure that we have a long enough region.
- ASSERT_EQ(InstrList.size(), static_cast<unsigned>(14));
- // Check that the instructions were added correctly to both vectors.
- ASSERT_TRUE(InstrList.size() == UnsignedVec.size());
-
- ASSERT_FALSE(longSimCandCompare(InstrList, true, 5, 0, 7));
-}
-
-// Checks that two sets of identical instructions are found to be the same.
-// Both sequences of adds have the same operand ordering, and the same
-// instructions, making them strcturally equivalent.
-TEST(IRSimilarityIdentifier, IdentitySimilarity) {
- StringRef ModuleString = R"(
- define i32 @f(i32 %a, i32 %b) {
- bb0:
- %0 = add i32 %a, %b
- %1 = sub i32 %b, %a
- br label %bb1
- bb1:
- %2 = add i32 %a, %b
- %3 = sub i32 %b, %a
- ret i32 0
- })";
- LLVMContext Context;
- std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
-
- std::vector<std::vector<IRSimilarityCandidate>> SimilarityCandidates;
- getSimilarities(*M, SimilarityCandidates);
-
- ASSERT_TRUE(SimilarityCandidates.size() == 1);
- for (std::vector<IRSimilarityCandidate> &Cands : SimilarityCandidates) {
- ASSERT_TRUE(Cands.size() == 2);
- unsigned InstIdx = 0;
- for (IRSimilarityCandidate &Cand : Cands) {
- ASSERT_TRUE(Cand.getStartIdx() == InstIdx);
- InstIdx += 3;
- }
- }
-}
-
-// Checks that incorrect sequences are not found as similar. In this case,
-// we have different sequences of instructions.
-TEST(IRSimilarityIdentifier, InstructionDifference) {
- StringRef ModuleString = R"(
- define i32 @f(i32 %a, i32 %b, i32 %c, i32 %d) {
- bb0:
- %0 = sub i32 %a, %b
- %1 = add i32 %b, %a
- br label %bb1
- bb1:
- %2 = add i32 %c, %d
- %3 = sub i32 %d, %c
- ret i32 0
- })";
- LLVMContext Context;
- std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
-
- std::vector<std::vector<IRSimilarityCandidate>> SimilarityCandidates;
- getSimilarities(*M, SimilarityCandidates);
-
- ASSERT_TRUE(SimilarityCandidates.empty());
-}
-
-// This test checks to see whether we can detect similarity for commutative
-// instructions where the operands have been reversed.
-TEST(IRSimilarityIdentifier, CommutativeSimilarity) {
- StringRef ModuleString = R"(
- define i32 @f(i32 %a, i32 %b) {
- bb0:
- %0 = add i32 %a, %b
- %1 = add i32 %b, %a
- br label %bb1
- bb1:
- %2 = add i32 %a, %b
- %3 = add i32 %a, %b
- ret i32 0
- })";
- LLVMContext Context;
- std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
-
- std::vector<std::vector<IRSimilarityCandidate>> SimilarityCandidates;
- getSimilarities(*M, SimilarityCandidates);
-
- ASSERT_TRUE(SimilarityCandidates.size() == 1);
- for (std::vector<IRSimilarityCandidate> &Cands : SimilarityCandidates) {
- ASSERT_TRUE(Cands.size() == 2);
- unsigned InstIdx = 0;
- for (IRSimilarityCandidate &Cand : Cands) {
- ASSERT_TRUE(Cand.getStartIdx() == InstIdx);
- InstIdx += 3;
- }
- }
-}
-
-// This test ensures that when the first instruction in a sequence is
-// a commutative instruction with the same value (mcomm_inst_same_val), but the
-// corresponding instruction (comm_inst_diff_val) is not, we mark the regions
-// and not similar.
-TEST(IRSimilarityIdentifier, CommutativeSameValueFirstMisMatch) {
- StringRef ModuleString = R"(
- define void @v_1_0(i64 %v_33) {
- entry:
- %comm_inst_same_val = mul i64 undef, undef
- %add = add i64 %comm_inst_same_val, %v_33
- %comm_inst_diff_val = mul i64 0, undef
- %mul.i = add i64 %comm_inst_diff_val, %comm_inst_diff_val
- unreachable
- })";
- LLVMContext Context;
- std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
-
- std::vector<std::vector<IRSimilarityCandidate>> SimilarityCandidates;
- getSimilarities(*M, SimilarityCandidates);
-
- ASSERT_TRUE(SimilarityCandidates.size() == 0);
-}
-
-// This test makes sure that intrinsic functions that are marked commutative
-// are still treated as non-commutative since they are function calls.
-TEST(IRSimilarityIdentifier, IntrinsicCommutative) {
- // If treated as commutative, we will fail to find a valid mapping, causing
- // an assertion error.
- StringRef ModuleString = R"(
- define void @foo() {
- entry:
- %0 = call i16 @llvm.smul.fix.i16(i16 16384, i16 16384, i32 15)
- store i16 %0, i16* undef, align 1
- %1 = icmp eq i16 undef, 8192
- call void @bar()
- %2 = call i16 @llvm.smul.fix.i16(i16 -16384, i16 16384, i32 15)
- store i16 %2, i16* undef, align 1
- %3 = icmp eq i16 undef, -8192
- call void @bar()
- %4 = call i16 @llvm.smul.fix.i16(i16 -16384, i16 -16384, i32 15)
- ret void
- }
-
- declare void @bar()
-
- ; Function Attrs: nofree nosync nounwind readnone speculatable willreturn
- declare i16 @llvm.smul.fix.i16(i16, i16, i32 immarg))";
- LLVMContext Context;
- std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
-
- std::vector<std::vector<IRSimilarityCandidate>> SimilarityCandidates;
- getSimilarities(*M, SimilarityCandidates);
-
- ASSERT_TRUE(SimilarityCandidates.size() == 0);
-}
-
-// This test checks to see whether we can detect different structure in
-// commutative instructions. In this case, the second operand in the second
-// add is different.
-TEST(IRSimilarityIdentifier, NoCommutativeSimilarity) {
- StringRef ModuleString = R"(
- define i32 @f(i32 %a, i32 %b) {
- bb0:
- %0 = add i32 %a, %b
- %1 = add i32 %1, %b
- br label %bb1
- bb1:
- %2 = add i32 %a, %b
- %3 = add i32 %2, %a
- ret i32 0
- })";
- LLVMContext Context;
- std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
-
- std::vector<std::vector<IRSimilarityCandidate>> SimilarityCandidates;
- getSimilarities(*M, SimilarityCandidates);
-
- ASSERT_TRUE(SimilarityCandidates.size() == 0);
-}
-
-// Check that we are not finding similarity in non commutative
-// instructions. That is, while the instruction and operands used are the same
-// in the two subtraction sequences, they are in a different order, and cannot
-// be counted as the same since a subtraction is not commutative.
-TEST(IRSimilarityIdentifier, NonCommutativeDifference) {
- StringRef ModuleString = R"(
- define i32 @f(i32 %a, i32 %b) {
- bb0:
- %0 = sub i32 %a, %b
- %1 = sub i32 %b, %a
- br label %bb1
- bb1:
- %2 = sub i32 %a, %b
- %3 = sub i32 %a, %b
- ret i32 0
- })";
- LLVMContext Context;
- std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
-
- std::vector<std::vector<IRSimilarityCandidate>> SimilarityCandidates;
- getSimilarities(*M, SimilarityCandidates);
-
- ASSERT_TRUE(SimilarityCandidates.empty());
-}
-
-// Check that we find similarity despite changing the register names.
-TEST(IRSimilarityIdentifier, MappingSimilarity) {
- StringRef ModuleString = R"(
- define i32 @f(i32 %a, i32 %b, i32 %c, i32 %d) {
- bb0:
- %0 = add i32 %a, %b
- %1 = sub i32 %b, %a
- br label %bb1
- bb1:
- %2 = add i32 %c, %d
- %3 = sub i32 %d, %c
- ret i32 0
- })";
- LLVMContext Context;
- std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
-
- std::vector<std::vector<IRSimilarityCandidate>> SimilarityCandidates;
- getSimilarities(*M, SimilarityCandidates);
-
- ASSERT_TRUE(SimilarityCandidates.size() == 1);
- for (std::vector<IRSimilarityCandidate> &Cands : SimilarityCandidates) {
- ASSERT_TRUE(Cands.size() == 2);
- unsigned InstIdx = 0;
- for (IRSimilarityCandidate &Cand : Cands) {
- ASSERT_TRUE(Cand.getStartIdx() == InstIdx);
- InstIdx += 3;
- }
- }
-}
-
-// Check that we find instances of swapped predicate isomorphism. That is,
-// for predicates that can be flipped, e.g. greater than to less than,
-// we can identify that instances of these different literal predicates, but are
-// the same within a single swap can be found.
-TEST(IRSimilarityIdentifier, PredicateIsomorphism) {
- StringRef ModuleString = R"(
- define i32 @f(i32 %a, i32 %b) {
- bb0:
- %0 = add i32 %a, %b
- %1 = icmp sgt i32 %b, %a
- br label %bb1
- bb1:
- %2 = add i32 %a, %b
- %3 = icmp slt i32 %a, %b
- ret i32 0
- })";
- LLVMContext Context;
- std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
-
- std::vector<std::vector<IRSimilarityCandidate>> SimilarityCandidates;
- getSimilarities(*M, SimilarityCandidates);
-
- ASSERT_TRUE(SimilarityCandidates.size() == 1);
- for (std::vector<IRSimilarityCandidate> &Cands : SimilarityCandidates) {
- ASSERT_TRUE(Cands.size() == 2);
- unsigned InstIdx = 0;
- for (IRSimilarityCandidate &Cand : Cands) {
- ASSERT_TRUE(Cand.getStartIdx() == InstIdx);
- InstIdx += 3;
- }
- }
-}
-
-// Checks that constants are detected as the same operand in each use in the
-// sequences of instructions. Also checks that we can find structural
-// equivalence using constants. In this case the 1 has the same use pattern as
-// %a.
-TEST(IRSimilarityIdentifier, ConstantMappingSimilarity) {
- StringRef ModuleString = R"(
- define i32 @f(i32 %a, i32 %b) {
- bb0:
- %0 = add i32 1, %b
- %1 = icmp sgt i32 %b, 1
- br label %bb1
- bb1:
- %2 = add i32 %a, %b
- %3 = icmp sgt i32 %b, %a
- ret i32 0
- })";
- LLVMContext Context;
- std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
-
- std::vector<std::vector<IRSimilarityCandidate>> SimilarityCandidates;
- getSimilarities(*M, SimilarityCandidates);
-
- ASSERT_TRUE(SimilarityCandidates.size() == 1);
- for (std::vector<IRSimilarityCandidate> &Cands : SimilarityCandidates) {
- ASSERT_TRUE(Cands.size() == 2);
- unsigned InstIdx = 0;
- for (IRSimilarityCandidate &Cand : Cands) {
- ASSERT_TRUE(Cand.getStartIdx() == InstIdx);
- InstIdx += 3;
- }
- }
-}
-
-// Check that constants are uniquely identified. i.e. two different constants
-// are not considered the same. This means that this should not find any
-// structural similarity.
-TEST(IRSimilarityIdentifier, ConstantMappingDifference) {
- StringRef ModuleString = R"(
- define i32 @f(i32 %a, i32 %b) {
- bb0:
- %0 = add i32 1, %b
- %1 = icmp sgt i32 %b, 2
- br label %bb1
- bb1:
- %2 = add i32 %a, %b
- %3 = icmp slt i32 %a, %b
- ret i32 0
- })";
- LLVMContext Context;
- std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
-
- std::vector<std::vector<IRSimilarityCandidate>> SimilarityCandidates;
- getSimilarities(*M, SimilarityCandidates);
-
- ASSERT_TRUE(SimilarityCandidates.empty());
-}
diff --git a/llvm/utils/gn/secondary/llvm/lib/Analysis/BUILD.gn b/llvm/utils/gn/secondary/llvm/lib/Analysis/BUILD.gn
index 4c237ddfed396..d113cf118c8f2 100644
--- a/llvm/utils/gn/secondary/llvm/lib/Analysis/BUILD.gn
+++ b/llvm/utils/gn/secondary/llvm/lib/Analysis/BUILD.gn
@@ -64,7 +64,6 @@ static_library("Analysis") {
"HashRecognize.cpp",
"HeatUtils.cpp",
"IR2Vec.cpp",
- "IRSimilarityIdentifier.cpp",
"IVDescriptors.cpp",
"IVUsers.cpp",
"ImportedFunctionsInliningStatistics.cpp",
diff --git a/llvm/utils/gn/secondary/llvm/lib/Transforms/IPO/BUILD.gn b/llvm/utils/gn/secondary/llvm/lib/Transforms/IPO/BUILD.gn
index 1d82db40802d7..fec29861eedcb 100644
--- a/llvm/utils/gn/secondary/llvm/lib/Transforms/IPO/BUILD.gn
+++ b/llvm/utils/gn/secondary/llvm/lib/Transforms/IPO/BUILD.gn
@@ -58,7 +58,6 @@ static_library("IPO") {
"GlobalSplit.cpp",
"HotColdSplitting.cpp",
"IPO.cpp",
- "IROutliner.cpp",
"InferFunctionAttrs.cpp",
"Inliner.cpp",
"Instrumentor.cpp",
diff --git a/llvm/utils/gn/secondary/llvm/test/BUILD.gn b/llvm/utils/gn/secondary/llvm/test/BUILD.gn
index d1767feaedc5c..cbc4f28bbaf65 100644
--- a/llvm/utils/gn/secondary/llvm/test/BUILD.gn
+++ b/llvm/utils/gn/secondary/llvm/test/BUILD.gn
@@ -329,7 +329,6 @@ group("test") {
"//llvm/tools/llvm-reduce",
"//llvm/tools/llvm-remarkutil",
"//llvm/tools/llvm-rtdyld",
- "//llvm/tools/llvm-sim",
"//llvm/tools/llvm-size",
"//llvm/tools/llvm-split",
"//llvm/tools/llvm-stress",
diff --git a/llvm/utils/gn/secondary/llvm/tools/llvm-sim/BUILD.gn b/llvm/utils/gn/secondary/llvm/tools/llvm-sim/BUILD.gn
deleted file mode 100644
index a391c0e1c2fcd..0000000000000
--- a/llvm/utils/gn/secondary/llvm/tools/llvm-sim/BUILD.gn
+++ /dev/null
@@ -1,8 +0,0 @@
-executable("llvm-sim") {
- deps = [
- "//llvm/lib/Analysis",
- "//llvm/lib/IRReader",
- "//llvm/lib/Support",
- ]
- sources = [ "llvm-sim.cpp" ]
-}
diff --git a/llvm/utils/gn/secondary/llvm/unittests/Analysis/BUILD.gn b/llvm/utils/gn/secondary/llvm/unittests/Analysis/BUILD.gn
index 51a1f3a78eee0..5e41310d16ce5 100644
--- a/llvm/utils/gn/secondary/llvm/unittests/Analysis/BUILD.gn
+++ b/llvm/utils/gn/secondary/llvm/unittests/Analysis/BUILD.gn
@@ -33,7 +33,6 @@ unittest("AnalysisTests") {
"GlobalsModRefTest.cpp",
"GraphWriterTest.cpp",
"IR2VecTest.cpp",
- "IRSimilarityIdentifierTest.cpp",
"IVDescriptorsTest.cpp",
"InlineCostTest.cpp",
"LastRunTrackingAnalysisTest.cpp",
diff --git a/llvm/utils/profcheck-xfail.txt b/llvm/utils/profcheck-xfail.txt
index 2d80881a847a9..0e90386d0ffd3 100644
--- a/llvm/utils/profcheck-xfail.txt
+++ b/llvm/utils/profcheck-xfail.txt
@@ -4,7 +4,6 @@ CodeGen/WinEH/wineh-scope-statenumbering.ll
CodeGen/WinEH/wineh-setjmp.ll
CodeGen/WinEH/wineh-statenumbering-cleanups.ll
CodeGen/WinEH/wineh-statenumbering.ll
-DebugInfo/AArch64/ir-outliner.ll
DebugInfo/Generic/block-asan.ll
Transforms/AtomicExpand/ARM/atomic-expansion-v7.ll
Transforms/CrossDSOCFI/basic.ll
diff --git a/utils/bazel/llvm-project-overlay/llvm/BUILD.bazel b/utils/bazel/llvm-project-overlay/llvm/BUILD.bazel
index 3a591dad25570..940998fea0261 100644
--- a/utils/bazel/llvm-project-overlay/llvm/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/llvm/BUILD.bazel
@@ -6965,23 +6965,6 @@ cc_binary(
],
)
-cc_binary(
- name = "llvm-sim",
- testonly = True,
- srcs = glob([
- "tools/llvm-sim/*.cpp",
- ]),
- copts = llvm_copts,
- stamp = 0,
- deps = [
- ":Analysis",
- ":Core",
- ":IRReader",
- ":Support",
- ":config",
- ],
-)
-
cc_binary(
name = "llvm-ir2vec",
testonly = True,
>From 245add0dc7da71393600b0e91704dad4eb926831 Mon Sep 17 00:00:00 2001
From: Simon Pilgrim <llvm-dev at redking.me.uk>
Date: Fri, 31 Jul 2026 23:17:07 +0100
Subject: [PATCH 33/43] [X86] getTargetConstantBitsFromNode - ensure constant
data is from a vector type (#213360)
Fixes #213251
---
llvm/lib/Target/X86/X86ISelLowering.cpp | 32 +++++-----
.../CodeGen/X86/vector-shuffle-combining.ll | 60 ++++++++++++++++++-
2 files changed, 75 insertions(+), 17 deletions(-)
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index c78af72f11d0a..44c847565cb69 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -5497,21 +5497,23 @@ static bool getTargetConstantBitsFromNode(SDValue Op, unsigned EltSizeInBits,
}
if (auto *CDS = dyn_cast<ConstantDataSequential>(Cst)) {
Type *Ty = CDS->getType();
- Mask = APInt::getZero(Ty->getPrimitiveSizeInBits());
- Type *EltTy = CDS->getElementType();
- bool IsInteger = EltTy->isIntegerTy();
- bool IsFP =
- EltTy->isHalfTy() || EltTy->isFloatTy() || EltTy->isDoubleTy();
- if (!IsInteger && !IsFP)
- return false;
- unsigned EltBits = EltTy->getPrimitiveSizeInBits();
- for (unsigned I = 0, E = CDS->getNumElements(); I != E; ++I)
- if (IsInteger)
- Mask.insertBits(CDS->getElementAsAPInt(I), I * EltBits);
- else
- Mask.insertBits(CDS->getElementAsAPFloat(I).bitcastToAPInt(),
- I * EltBits);
- return true;
+ if (Ty->isVectorTy()) {
+ Mask = APInt::getZero(Ty->getPrimitiveSizeInBits());
+ Type *EltTy = CDS->getElementType();
+ bool IsInteger = EltTy->isIntegerTy();
+ bool IsFP =
+ EltTy->isHalfTy() || EltTy->isFloatTy() || EltTy->isDoubleTy();
+ if (!IsInteger && !IsFP)
+ return false;
+ unsigned EltBits = EltTy->getPrimitiveSizeInBits();
+ for (unsigned I = 0, E = CDS->getNumElements(); I != E; ++I)
+ if (IsInteger)
+ Mask.insertBits(CDS->getElementAsAPInt(I), I * EltBits);
+ else
+ Mask.insertBits(CDS->getElementAsAPFloat(I).bitcastToAPInt(),
+ I * EltBits);
+ return true;
+ }
}
return false;
};
diff --git a/llvm/test/CodeGen/X86/vector-shuffle-combining.ll b/llvm/test/CodeGen/X86/vector-shuffle-combining.ll
index 4e68a259a075b..b0667cb7bbb5c 100644
--- a/llvm/test/CodeGen/X86/vector-shuffle-combining.ll
+++ b/llvm/test/CodeGen/X86/vector-shuffle-combining.ll
@@ -3621,6 +3621,62 @@ define <2 x i1> @PR179112(<2 x i32> %load) {
ret <2 x i1> %reverse.2
}
+define <8 x float> @PR213251() {
+; SSE2-LABEL: PR213251:
+; SSE2: # %bb.0:
+; SSE2-NEXT: movl $1, (%rax)
+; SSE2-NEXT: movd {{.*#+}} xmm0 = [NaN,0.0E+0,0.0E+0,0.0E+0]
+; SSE2-NEXT: movq {{.*#+}} xmm0 = xmm0[0],zero
+; SSE2-NEXT: xorps %xmm1, %xmm1
+; SSE2-NEXT: shufps {{.*#+}} xmm0 = xmm0[2,0],xmm1[2,3]
+; SSE2-NEXT: retq
+;
+; SSSE3-LABEL: PR213251:
+; SSSE3: # %bb.0:
+; SSSE3-NEXT: movl $1, (%rax)
+; SSSE3-NEXT: movd {{.*#+}} xmm0 = [NaN,0.0E+0,0.0E+0,0.0E+0]
+; SSSE3-NEXT: movq {{.*#+}} xmm0 = xmm0[0],zero
+; SSSE3-NEXT: xorps %xmm1, %xmm1
+; SSSE3-NEXT: shufps {{.*#+}} xmm0 = xmm0[2,0],xmm1[2,3]
+; SSSE3-NEXT: retq
+;
+; SSE41-LABEL: PR213251:
+; SSE41: # %bb.0:
+; SSE41-NEXT: movl $1, (%rax)
+; SSE41-NEXT: insertps {{.*#+}} xmm0 = zero,mem[0],zero,zero
+; SSE41-NEXT: xorps %xmm1, %xmm1
+; SSE41-NEXT: retq
+;
+; AVX1-LABEL: PR213251:
+; AVX1: # %bb.0:
+; AVX1-NEXT: movl $1, (%rax)
+; AVX1-NEXT: vbroadcastss {{.*#+}} xmm0 = [NaN,NaN,NaN,NaN]
+; AVX1-NEXT: vxorps %xmm1, %xmm1, %xmm1
+; AVX1-NEXT: vblendps {{.*#+}} ymm0 = ymm1[0],ymm0[1],ymm1[2,3,4,5,6,7]
+; AVX1-NEXT: retq
+;
+; AVX2-SLOW-LABEL: PR213251:
+; AVX2-SLOW: # %bb.0:
+; AVX2-SLOW-NEXT: movl $1, (%rax)
+; AVX2-SLOW-NEXT: vbroadcastss {{.*#+}} xmm0 = [NaN,NaN,NaN,NaN]
+; AVX2-SLOW-NEXT: vxorps %xmm1, %xmm1, %xmm1
+; AVX2-SLOW-NEXT: vblendps {{.*#+}} ymm0 = ymm1[0],ymm0[1],ymm1[2,3,4,5,6,7]
+; AVX2-SLOW-NEXT: retq
+;
+; AVX2-FAST-LABEL: PR213251:
+; AVX2-FAST: # %bb.0:
+; AVX2-FAST-NEXT: movl $1, (%rax)
+; AVX2-FAST-NEXT: vmovd {{.*#+}} xmm0 = [NaN,0.0E+0,0.0E+0,0.0E+0]
+; AVX2-FAST-NEXT: vpshufb {{.*#+}} ymm0 = zero,zero,zero,zero,ymm0[0,1,2,3],zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero
+; AVX2-FAST-NEXT: retq
+ store i32 1, ptr poison, align 4
+ %f.promoted = load i32, ptr poison, align 4
+ %tobool.not12 = icmp eq i32 %f.promoted, 0
+ %cond13 = select i1 %tobool.not12, float 1.000000e+00, float +qnan
+ %vecins14 = insertelement <8 x float> zeroinitializer, float %cond13, i64 1
+ ret <8 x float> %vecins14
+}
+
; Test case reported on D105827
define void @SpinningCube() {
; SSE2-LABEL: SpinningCube:
@@ -3722,9 +3778,9 @@ define void @autogen_SD25931() {
; CHECK-LABEL: autogen_SD25931:
; CHECK: # %bb.0: # %BB
; CHECK-NEXT: .p2align 4
-; CHECK-NEXT: .LBB144_1: # %CF242
+; CHECK-NEXT: .LBB145_1: # %CF242
; CHECK-NEXT: # =>This Inner Loop Header: Depth=1
-; CHECK-NEXT: jmp .LBB144_1
+; CHECK-NEXT: jmp .LBB145_1
BB:
%Cmp16 = icmp uge <2 x i1> zeroinitializer, zeroinitializer
%Shuff19 = shufflevector <2 x i1> zeroinitializer, <2 x i1> %Cmp16, <2 x i32> <i32 3, i32 1>
>From 15cf68db14bbe9f6c90b0d7e76a0047b1b75104d Mon Sep 17 00:00:00 2001
From: "Moazin K." <mkhatti at nvidia.com>
Date: Fri, 31 Jul 2026 15:21:46 -0700
Subject: [PATCH 34/43] [OpenACC][NFC] Minor clean up in ACCRoutineLowering.
(#213333)
Minor NFC clean up after recent changes to remove nohost handling from
ACCRoutineLowering.
Assisted-by: Codex
---
.../OpenACC/Transforms/ACCRoutineLowering.cpp | 20 ++++++++-----------
1 file changed, 8 insertions(+), 12 deletions(-)
diff --git a/mlir/lib/Dialect/OpenACC/Transforms/ACCRoutineLowering.cpp b/mlir/lib/Dialect/OpenACC/Transforms/ACCRoutineLowering.cpp
index d082ef8be3d17..9d5f0fc434d7e 100644
--- a/mlir/lib/Dialect/OpenACC/Transforms/ACCRoutineLowering.cpp
+++ b/mlir/lib/Dialect/OpenACC/Transforms/ACCRoutineLowering.cpp
@@ -168,15 +168,13 @@ buildRoutineBody(func::FuncOp deviceFunc, func::FuncOp hostFunc,
}
/// Update acc.routine refs
-static LogicalResult finalizeRoutines(
- SmallVectorImpl<std::tuple<func::FuncOp, func::FuncOp, RoutineOp>>
- &accRoutineInfo,
- ModuleOp mod, MLIRContext *ctx) {
- for (auto &[hostFunc, deviceFunc, routineOp] : accRoutineInfo) {
+static void finalizeRoutines(
+ SmallVectorImpl<std::pair<func::FuncOp, RoutineOp>> &accRoutineInfo,
+ MLIRContext *ctx) {
+ for (auto &[deviceFunc, routineOp] : accRoutineInfo) {
routineOp.setFuncNameAttr(SymbolRefAttr::get(ctx, deviceFunc.getName()));
routineOp->moveBefore(deviceFunc);
}
- return success();
}
class ACCRoutineLowering
@@ -197,9 +195,8 @@ class ACCRoutineLowering
IRRewriter rewriter(ctx);
DefaultACCToGPUMappingPolicy policy;
- // Tuple: host function, device function, routine operation
- SmallVector<std::tuple<func::FuncOp, func::FuncOp, RoutineOp>, 4>
- accRoutineInfo;
+ // Pair: device function, routine operation
+ SmallVector<std::pair<func::FuncOp, RoutineOp>, 4> accRoutineInfo;
for (RoutineOp routineOp : mod.getOps<RoutineOp>()) {
if (routineOp.getBindNameValue() ||
@@ -226,12 +223,11 @@ class ACCRoutineLowering
parLevel, policy, rewriter)))
return signalPassFailure();
- accRoutineInfo.push_back({hostFunc, deviceFunc, routineOp});
+ accRoutineInfo.push_back({deviceFunc, routineOp});
symTab.insert(deviceFunc);
}
- if (failed(finalizeRoutines(accRoutineInfo, mod, ctx)))
- return signalPassFailure();
+ finalizeRoutines(accRoutineInfo, ctx);
}
};
>From 5b98324aa8108394ca79647eece868cc7d463275 Mon Sep 17 00:00:00 2001
From: Thurston Dang <thurston at google.com>
Date: Fri, 31 Jul 2026 15:28:13 -0700
Subject: [PATCH 35/43] [DropAssumes] Print drop-deref in pipeline where
appropriate (#211905)
drop-deref was added as an option in #166947 and is parsed correctly,
but is not serialized. This can make it difficult to reduce test cases,
especially automatically with llvm/utils/reduce_pipeline.py.
This patch implements printPipeline() to serialize drop-deref where
appropriate.
---
.../llvm/Transforms/Scalar/DropUnnecessaryAssumes.h | 3 +++
llvm/lib/Transforms/Scalar/DropUnnecessaryAssumes.cpp | 8 ++++++++
llvm/test/Other/new-pm-print-pipeline.ll | 3 +++
3 files changed, 14 insertions(+)
diff --git a/llvm/include/llvm/Transforms/Scalar/DropUnnecessaryAssumes.h b/llvm/include/llvm/Transforms/Scalar/DropUnnecessaryAssumes.h
index e77fb437cf3ff..6b7e82276073f 100644
--- a/llvm/include/llvm/Transforms/Scalar/DropUnnecessaryAssumes.h
+++ b/llvm/include/llvm/Transforms/Scalar/DropUnnecessaryAssumes.h
@@ -23,6 +23,9 @@ struct DropUnnecessaryAssumesPass
: DropDereferenceable(DropDereferenceable) {}
LLVM_ABI PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
+ LLVM_ABI void
+ printPipeline(raw_ostream &OS,
+ function_ref<StringRef(StringRef)> MapClassName2PassName);
private:
bool DropDereferenceable;
diff --git a/llvm/lib/Transforms/Scalar/DropUnnecessaryAssumes.cpp b/llvm/lib/Transforms/Scalar/DropUnnecessaryAssumes.cpp
index f1192db7538ac..d23dfb9331db3 100644
--- a/llvm/lib/Transforms/Scalar/DropUnnecessaryAssumes.cpp
+++ b/llvm/lib/Transforms/Scalar/DropUnnecessaryAssumes.cpp
@@ -152,3 +152,11 @@ DropUnnecessaryAssumesPass::run(Function &F, FunctionAnalysisManager &FAM) {
}
return PreservedAnalyses::all();
}
+
+void DropUnnecessaryAssumesPass::printPipeline(
+ raw_ostream &OS, function_ref<StringRef(StringRef)> MapClassName2PassName) {
+ static_cast<PassInfoMixin<DropUnnecessaryAssumesPass> *>(this)->printPipeline(
+ OS, MapClassName2PassName);
+ if (DropDereferenceable)
+ OS << "<drop-deref>";
+}
diff --git a/llvm/test/Other/new-pm-print-pipeline.ll b/llvm/test/Other/new-pm-print-pipeline.ll
index 2aaf7f182f9e1..110ff23131667 100644
--- a/llvm/test/Other/new-pm-print-pipeline.ll
+++ b/llvm/test/Other/new-pm-print-pipeline.ll
@@ -123,3 +123,6 @@
; RUN: opt -disable-output -disable-verify -print-pipeline-passes -passes='module(asan<>,asan<kernel;use-after-scope>)' < %s | FileCheck %s --match-full-lines --check-prefixes=CHECK-37
; CHECK-37: asan<>,asan<kernel;use-after-scope>
+
+; RUN: opt -disable-output -disable-verify -print-pipeline-passes -passes='drop-unnecessary-assumes,drop-unnecessary-assumes<drop-deref>' < %s | FileCheck %s --check-prefixes=CHECK-38
+; CHECK-38: drop-unnecessary-assumes,drop-unnecessary-assumes<drop-deref>
>From 8cfce9a066716e14b8bd318927b614b87b18dcaa Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Valentin=20Clement=20=28=E3=83=90=E3=83=AC=E3=83=B3?=
=?UTF-8?q?=E3=82=BF=E3=82=A4=E3=83=B3=20=E3=82=AF=E3=83=AC=E3=83=A1?=
=?UTF-8?q?=E3=83=B3=29?= <clementval at gmail.com>
Date: Fri, 31 Jul 2026 16:02:09 -0700
Subject: [PATCH 36/43] [flang][NFC] Rename modfile84.f90 to modfile85.f90
(#213371)
Avoid clash on case insensitive system
---
flang/test/Semantics/{modfile84.f90 => modfile85.f90} | 0
1 file changed, 0 insertions(+), 0 deletions(-)
rename flang/test/Semantics/{modfile84.f90 => modfile85.f90} (100%)
diff --git a/flang/test/Semantics/modfile84.f90 b/flang/test/Semantics/modfile85.f90
similarity index 100%
rename from flang/test/Semantics/modfile84.f90
rename to flang/test/Semantics/modfile85.f90
>From 2572ba033db759ce07d56bf2e2a599be347b5a2a Mon Sep 17 00:00:00 2001
From: Ayokunle Amodu <ayokunle321 at gmail.com>
Date: Fri, 31 Jul 2026 19:18:49 -0400
Subject: [PATCH 37/43] [CIR][AMDGPU] Add support for AMDGCN ldexp builtins
(#198087)
Adds support for the following AMDGCN ldexp builtins:
- __builtin_amdgcn_ldexp (double)
- __builtin_amdgcn_ldexpf (float)
- __builtin_amdgcn_ldexph (half)
These are lowered to the `llvm.ldexp` intrinsic.
---
clang/lib/CIR/CodeGen/CIRGenBuiltinAMDGPU.cpp | 18 ++++++++++++++----
.../CIR/CodeGenHIP/builtins-amdgcn-vi-f16.hip | 10 ++++++++++
clang/test/CIR/CodeGenHIP/builtins-amdgcn.hip | 16 ++++++++++++++++
3 files changed, 40 insertions(+), 4 deletions(-)
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltinAMDGPU.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltinAMDGPU.cpp
index 861ec451e2bc0..e2a1c2b94dec4 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuiltinAMDGPU.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenBuiltinAMDGPU.cpp
@@ -296,10 +296,20 @@ CIRGenFunction::emitAMDGPUBuiltinExpr(unsigned builtinId,
case AMDGPU::BI__builtin_amdgcn_ldexp:
case AMDGPU::BI__builtin_amdgcn_ldexpf:
case AMDGPU::BI__builtin_amdgcn_ldexph: {
- cgm.errorNYI(expr->getSourceRange(),
- std::string("unimplemented AMDGPU builtin call: ") +
- getContext().BuiltinInfo.getName(builtinId));
- return mlir::Value{};
+ mlir::Value src0 = emitScalarExpr(expr->getArg(0));
+ mlir::Value src1 = emitScalarExpr(expr->getArg(1));
+ // For ldexph, the raw instruction has different behavior for out-of-bounds
+ // exponent values (implicit truncation instead of saturate to
+ // short_min/short_max), so truncate the exponent to i16 first.
+ mlir::Value exp =
+ builtinId == AMDGPU::BI__builtin_amdgcn_ldexph
+ ? cir::CastOp::create(builder, getLoc(expr->getExprLoc()),
+ builder.getSInt16Ty(),
+ cir::CastKind::integral, src1)
+ : src1;
+ return builder.emitIntrinsicCallOp(getLoc(expr->getExprLoc()), "ldexp",
+ src0.getType(),
+ mlir::ValueRange{src0, exp});
}
case AMDGPU::BI__builtin_amdgcn_frexp_mant:
case AMDGPU::BI__builtin_amdgcn_frexp_mantf:
diff --git a/clang/test/CIR/CodeGenHIP/builtins-amdgcn-vi-f16.hip b/clang/test/CIR/CodeGenHIP/builtins-amdgcn-vi-f16.hip
index 11a97c9befa9d..e298056ab6d9d 100644
--- a/clang/test/CIR/CodeGenHIP/builtins-amdgcn-vi-f16.hip
+++ b/clang/test/CIR/CodeGenHIP/builtins-amdgcn-vi-f16.hip
@@ -111,3 +111,13 @@ __device__ void test_cos_f16(_Float16* out, _Float16 a) {
__device__ void test_frexp_mant_f16(_Float16* out, _Float16 a) {
*out = __builtin_amdgcn_frexp_manth(a);
}
+
+// CIR-LABEL: @_Z14test_ldexp_f16PDF16_DF16_i
+// CIR: [[TRUNC:%.*]] = cir.cast integral {{.*}} : !s32i -> !s16i
+// CIR: cir.call_llvm_intrinsic "ldexp" {{.*}}, [[TRUNC]] : (!cir.f16, !s16i) -> !cir.f16
+// LLVM: define{{.*}} void @_Z14test_ldexp_f16PDF16_DF16_i
+// LLVM: [[TRUNC:%.*]] = trunc i32 {{.*}} to i16
+// LLVM: call{{.*}} half @llvm.ldexp.f16.i16(half %{{.*}}, i16 [[TRUNC]])
+__device__ void test_ldexp_f16(_Float16* out, _Float16 a, int b) {
+ *out = __builtin_amdgcn_ldexph(a, b);
+}
diff --git a/clang/test/CIR/CodeGenHIP/builtins-amdgcn.hip b/clang/test/CIR/CodeGenHIP/builtins-amdgcn.hip
index 759f981f3fa12..8ba5a354cfefa 100644
--- a/clang/test/CIR/CodeGenHIP/builtins-amdgcn.hip
+++ b/clang/test/CIR/CodeGenHIP/builtins-amdgcn.hip
@@ -239,3 +239,19 @@ __device__ void test_trig_preop_f32(float* out, float a, int b) {
__device__ void test_trig_preop_f64(double* out, double a, int b) {
*out = __builtin_amdgcn_trig_preop(a, b);
}
+
+// CIR-LABEL: @_Z14test_ldexp_f32Pffi
+// CIR: cir.call_llvm_intrinsic "ldexp" {{.*}} : (!cir.float, !s32i) -> !cir.float
+// LLVM: define{{.*}} void @_Z14test_ldexp_f32Pffi
+// LLVM: call{{.*}} float @llvm.ldexp.f32.i32(float %{{.*}}, i32 %{{.*}})
+__device__ void test_ldexp_f32(float* out, float a, int b) {
+ *out = __builtin_amdgcn_ldexpf(a, b);
+}
+
+// CIR-LABEL: @_Z14test_ldexp_f64Pddi
+// CIR: cir.call_llvm_intrinsic "ldexp" {{.*}} : (!cir.double, !s32i) -> !cir.double
+// LLVM: define{{.*}} void @_Z14test_ldexp_f64Pddi
+// LLVM: call{{.*}} double @llvm.ldexp.f64.i32(double %{{.*}}, i32 %{{.*}})
+__device__ void test_ldexp_f64(double* out, double a, int b) {
+ *out = __builtin_amdgcn_ldexp(a, b);
+}
>From 24c801c69f6fe5cbada1eb4548886e861e08ae05 Mon Sep 17 00:00:00 2001
From: Tom Stellard <tstellar at redhat.com>
Date: Fri, 31 Jul 2026 16:32:37 -0700
Subject: [PATCH 38/43] workflows/llvm-abi-tests: Cache the baseline abi
(#211968)
This way we don't need to recompute it for every workflow.
---
.github/workflows/llvm-abi-tests.yml | 23 +++++++++++++++++++++++
1 file changed, 23 insertions(+)
diff --git a/.github/workflows/llvm-abi-tests.yml b/.github/workflows/llvm-abi-tests.yml
index ebd5037998b98..70175b0f39163 100644
--- a/.github/workflows/llvm-abi-tests.yml
+++ b/.github/workflows/llvm-abi-tests.yml
@@ -93,23 +93,37 @@ jobs:
ref: ${{ github.sha }}
repo: ${{ github.repository }}
steps:
+ - name: Check for cached baseline ABI
+ if: ${{ matrix.name == 'build-baseline' }}
+ id: cache
+ uses: actions/cache/restore at 55cc8345863c7cc4c66a329aec7e433d2d1c52a9 #v6.1.0
+ with:
+ key: ${{ matrix.ref}}.abi
+ path: |
+ ${{ matrix.ref }}.abi
+ llvm.symbols
+
- name: Download source code
uses: actions/checkout at df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
+ if: steps.cache.outputs.cache-hit != 'true'
with:
persist-credentials: false
ref: ${{ matrix.ref }}
repository: ${{ matrix.repo }}
- name: Configure
+ if: steps.cache.outputs.cache-hit != 'true'
run: |
mkdir install
cmake -B build -G Ninja -DCMAKE_BUILD_TYPE=Debug -DLLVM_TARGETS_TO_BUILD="" -DLLVM_BUILD_LLVM_DYLIB=ON -DCMAKE_INSTALL_PREFIX="$(pwd)"/install llvm
- name: Build
+ if: steps.cache.outputs.cache-hit != 'true'
# Need to run install-LLVM twice to ensure the symlink is installed (this is a bug).
run: |
ninja -C build install-LLVM
ninja -C build install-LLVM
ninja -C build install-llvm-headers
- name: Dump ABI
+ if: steps.cache.outputs.cache-hit != 'true'
env:
REF: ${{ matrix.ref }}
ABI_HEADERS: ${{ needs.abi-dump-setup.outputs.ABI_HEADERS }}
@@ -138,6 +152,15 @@ jobs:
name: symbol-list
path: llvm.symbols
+ - name: Cache baseline ABI
+ if: ${{ matrix.name == 'build-baseline' }}
+ uses: actions/cache/save at 55cc8345863c7cc4c66a329aec7e433d2d1c52a9 #v6.1.0
+ with:
+ key: ${{ matrix.ref }}.abi
+ path: |
+ ${{ matrix.ref }}.abi
+ llvm.symbols
+
abi-compare:
if: github.repository_owner == 'llvm'
runs-on: ubuntu-24.04
>From 4d985f59da739bcb558bfb9faffdaab59b45f7ba Mon Sep 17 00:00:00 2001
From: Michael Jones <michaelrj at google.com>
Date: Fri, 31 Jul 2026 16:37:32 -0700
Subject: [PATCH 39/43] [libc] Move generated elf header to include (#211428)
The fact that `hdr/elf_proxy.h` was generated with headergen was causing
dependency issues. This shouldn't be necessary, and this PR moves it out
into `include` to avoid needing headergen for an overlay build.
Assisted-by: Automated tooling, human reviewed.
---
libc/cmake/modules/LLVMLibCHeaderRules.cmake | 4 +-
libc/hdr/CMakeLists.txt | 56 +-
libc/hdr/elf_proxy.h | 27 +
libc/include/CMakeLists.txt | 52 +-
libc/include/elf.yaml | 666 +----------------
libc/include/llvm-libc-proxy/CMakeLists.txt | 59 ++
libc/include/llvm-libc-proxy/elf_proxy.yaml | 667 ++++++++++++++++++
.../llvm-project-overlay/libc/BUILD.bazel | 17 +-
.../libc/libc_build_rules.bzl | 2 +
9 files changed, 773 insertions(+), 777 deletions(-)
create mode 100644 libc/hdr/elf_proxy.h
create mode 100644 libc/include/llvm-libc-proxy/CMakeLists.txt
create mode 100644 libc/include/llvm-libc-proxy/elf_proxy.yaml
diff --git a/libc/cmake/modules/LLVMLibCHeaderRules.cmake b/libc/cmake/modules/LLVMLibCHeaderRules.cmake
index d7e996be9e854..88e183d8f4ec4 100644
--- a/libc/cmake/modules/LLVMLibCHeaderRules.cmake
+++ b/libc/cmake/modules/LLVMLibCHeaderRules.cmake
@@ -94,11 +94,9 @@ function(add_gen_header target_name)
set(absolute_path ${CMAKE_CURRENT_SOURCE_DIR}/${ADD_GEN_HDR_GEN_HDR})
file(RELATIVE_PATH relative_path ${LIBC_INCLUDE_SOURCE_DIR} ${absolute_path})
+ set(out_file ${LIBC_INCLUDE_DIR}/${relative_path})
if (ADD_GEN_HDR_PROXY)
- set(out_file ${LIBC_BUILD_DIR}/hdr/${relative_path})
set(proxy_arg "--proxy")
- else()
- set(out_file ${LIBC_INCLUDE_DIR}/${relative_path})
endif()
set(dep_file "${out_file}.d")
set(yaml_file ${CMAKE_SOURCE_DIR}/${ADD_GEN_HDR_YAML_FILE})
diff --git a/libc/hdr/CMakeLists.txt b/libc/hdr/CMakeLists.txt
index f2979866eafbe..a3eb7769e3c91 100644
--- a/libc/hdr/CMakeLists.txt
+++ b/libc/hdr/CMakeLists.txt
@@ -357,60 +357,12 @@ add_proxy_header_library(
libc.include.llvm-libc-macros.elf_macros
)
-add_gen_header(
+add_proxy_header_library(
elf_proxy
- YAML_FILE
- ../libc/include/elf.yaml
- GEN_HDR
+ HDRS
elf_proxy.h
- DEPENDS
- libc.include.llvm_libc_common_h
- libc.include.llvm-libc-types.Elf32_Addr
- libc.include.llvm-libc-types.Elf32_Chdr
- libc.include.llvm-libc-types.Elf32_Dyn
- libc.include.llvm-libc-types.Elf32_Ehdr
- libc.include.llvm-libc-types.Elf32_Half
- libc.include.llvm-libc-types.Elf32_Lword
- libc.include.llvm-libc-types.Elf32_Nhdr
- libc.include.llvm-libc-types.Elf32_Off
- libc.include.llvm-libc-types.Elf32_Phdr
- libc.include.llvm-libc-types.Elf32_Rel
- libc.include.llvm-libc-types.Elf32_Rela
- libc.include.llvm-libc-types.Elf32_Shdr
- libc.include.llvm-libc-types.Elf32_Sword
- libc.include.llvm-libc-types.Elf32_Sym
- libc.include.llvm-libc-types.Elf32_Verdaux
- libc.include.llvm-libc-types.Elf32_Verdef
- libc.include.llvm-libc-types.Elf32_Vernaux
- libc.include.llvm-libc-types.Elf32_Verneed
- libc.include.llvm-libc-types.Elf32_Versym
- libc.include.llvm-libc-types.Elf32_Word
- libc.include.llvm-libc-types.Elf32_Xword
- libc.include.llvm-libc-types.Elf32_auxv_t
- libc.include.llvm-libc-types.Elf64_Addr
- libc.include.llvm-libc-types.Elf64_Chdr
- libc.include.llvm-libc-types.Elf64_Dyn
- libc.include.llvm-libc-types.Elf64_Ehdr
- libc.include.llvm-libc-types.Elf64_Half
- libc.include.llvm-libc-types.Elf64_Lword
- libc.include.llvm-libc-types.Elf64_Nhdr
- libc.include.llvm-libc-types.Elf64_Off
- libc.include.llvm-libc-types.Elf64_Phdr
- libc.include.llvm-libc-types.Elf64_Rel
- libc.include.llvm-libc-types.Elf64_Rela
- libc.include.llvm-libc-types.Elf64_Shdr
- libc.include.llvm-libc-types.Elf64_Sword
- libc.include.llvm-libc-types.Elf64_Sxword
- libc.include.llvm-libc-types.Elf64_Sym
- libc.include.llvm-libc-types.Elf64_Verdaux
- libc.include.llvm-libc-types.Elf64_Verdef
- libc.include.llvm-libc-types.Elf64_Vernaux
- libc.include.llvm-libc-types.Elf64_Verneed
- libc.include.llvm-libc-types.Elf64_Versym
- libc.include.llvm-libc-types.Elf64_Word
- libc.include.llvm-libc-types.Elf64_Xword
- libc.include.llvm-libc-types.Elf64_auxv_t
- PROXY
+ FULL_BUILD_DEPENDS
+ libc.include.llvm-libc-proxy.elf_proxy
)
add_proxy_header_library(
diff --git a/libc/hdr/elf_proxy.h b/libc/hdr/elf_proxy.h
new file mode 100644
index 0000000000000..23e42ddff12f0
--- /dev/null
+++ b/libc/hdr/elf_proxy.h
@@ -0,0 +1,27 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// Proxy header for elf.h.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_HDR_HDR_ELF_PROXY_H
+#define LLVM_LIBC_HDR_HDR_ELF_PROXY_H
+
+#ifdef LIBC_FULL_BUILD
+
+#include "llvm-libc-proxy/elf_proxy.h"
+
+#else // Overlay mode
+
+#include <elf.h>
+
+#endif // LIBC_FULL_BUILD
+
+#endif // LLVM_LIBC_HDR_HDR_ELF_PROXY_H
diff --git a/libc/include/CMakeLists.txt b/libc/include/CMakeLists.txt
index cf8bfb02c3931..196490dcfdcc1 100644
--- a/libc/include/CMakeLists.txt
+++ b/libc/include/CMakeLists.txt
@@ -17,6 +17,9 @@ add_header(
__llvm-libc-common.h
)
+# Has to be after common since elf_proxy depends on common.
+add_subdirectory(llvm-libc-proxy)
+
# TODO: Can we simplify this macro expansion?
# https://github.com/llvm/llvm-project/issues/117254
macro(add_header_macro TARGET_NAME YAML_FILE GEN_HDR DEPENDS)
@@ -604,53 +607,8 @@ add_header_macro(
../libc/include/elf.yaml
elf.h
DEPENDS
- .llvm-libc-macros.elf_macros
- .llvm-libc-macros.sys_auxv_macros
- .llvm-libc-types.Elf32_Addr
- .llvm-libc-types.Elf32_Chdr
- .llvm-libc-types.Elf32_Dyn
- .llvm-libc-types.Elf32_Ehdr
- .llvm-libc-types.Elf32_Half
- .llvm-libc-types.Elf32_Lword
- .llvm-libc-types.Elf32_Nhdr
- .llvm-libc-types.Elf32_Off
- .llvm-libc-types.Elf32_Phdr
- .llvm-libc-types.Elf32_Rel
- .llvm-libc-types.Elf32_Rela
- .llvm-libc-types.Elf32_Shdr
- .llvm-libc-types.Elf32_Sword
- .llvm-libc-types.Elf32_Sym
- .llvm-libc-types.Elf32_Verdaux
- .llvm-libc-types.Elf32_Verdef
- .llvm-libc-types.Elf32_Vernaux
- .llvm-libc-types.Elf32_Verneed
- .llvm-libc-types.Elf32_Versym
- .llvm-libc-types.Elf32_Word
- .llvm-libc-types.Elf32_Xword
- .llvm-libc-types.Elf32_auxv_t
- .llvm-libc-types.Elf64_Addr
- .llvm-libc-types.Elf64_Chdr
- .llvm-libc-types.Elf64_Dyn
- .llvm-libc-types.Elf64_Ehdr
- .llvm-libc-types.Elf64_Half
- .llvm-libc-types.Elf64_Lword
- .llvm-libc-types.Elf64_Nhdr
- .llvm-libc-types.Elf64_Off
- .llvm-libc-types.Elf64_Phdr
- .llvm-libc-types.Elf64_Rel
- .llvm-libc-types.Elf64_Rela
- .llvm-libc-types.Elf64_Shdr
- .llvm-libc-types.Elf64_Sword
- .llvm-libc-types.Elf64_Sxword
- .llvm-libc-types.Elf64_Sym
- .llvm-libc-types.Elf64_Verdaux
- .llvm-libc-types.Elf64_Verdef
- .llvm-libc-types.Elf64_Vernaux
- .llvm-libc-types.Elf64_Verneed
- .llvm-libc-types.Elf64_Versym
- .llvm-libc-types.Elf64_Word
- .llvm-libc-types.Elf64_Xword
- .llvm-libc-types.Elf64_auxv_t
+ .llvm-libc-proxy.elf_proxy
+ .llvm_libc_common_h
)
# TODO: Not all platforms will have a include/sys directory. Add the sys
diff --git a/libc/include/elf.yaml b/libc/include/elf.yaml
index 2b11dfe2a343f..f86463b2f4aa0 100644
--- a/libc/include/elf.yaml
+++ b/libc/include/elf.yaml
@@ -1,667 +1,5 @@
header: elf.h
+public_includes:
+ - llvm-libc-proxy/elf_proxy.h
standards:
- svid
-macros:
- # ELF Header
- - macro_name: EI_NIDENT
- macro_value: 16
- - macro_name: EI_MAG0
- macro_value: 0
- - macro_name: EI_MAG1
- macro_value: 1
- - macro_name: EI_MAG2
- macro_value: 2
- - macro_name: EI_MAG3
- macro_value: 3
- - macro_name: EI_CLASS
- macro_value: 4
- - macro_name: EI_DATA
- macro_value: 5
- - macro_name: EI_VERSION
- macro_value: 6
- - macro_name: EI_OSABI
- macro_value: 7
- - macro_name: EI_ABIVERSION
- macro_value: 8
- - macro_name: EI_PAD
- macro_value: 9
- - macro_name: EI_NIDENT
- macro_value: 16
- - macro_name: ELFMAG0
- macro_value: '0x7f'
- - macro_name: ELFMAG1
- macro_value: "'E'"
- - macro_name: ELFMAG2
- macro_value: "'L'"
- - macro_name: ELFMAG3
- macro_value: "'F'"
- - macro_name: ELFMAG
- macro_value: '"\177ELF"'
- - macro_name: SELFMAG
- macro_value: 4
- - macro_name: ELFCLASSNONE
- macro_value: 0
- - macro_name: ELFCLASS32
- macro_value: 1
- - macro_name: ELFCLASS64
- macro_value: 2
- - macro_name: ELFDATANONE
- macro_value: 0
- - macro_name: ELFDATA2LSB
- macro_value: 1
- - macro_name: ELFDATA2MSB
- macro_value: 2
- - macro_name: ELFOSABI_NONE
- macro_value: 0
- - macro_name: ELFOSABI_LINUX
- macro_value: 3
- - macro_name: ET_NONE
- macro_value: 0
- - macro_name: ET_REL
- macro_value: 1
- - macro_name: ET_EXEC
- macro_value: 2
- - macro_name: ET_DYN
- macro_value: 3
- - macro_name: ET_CORE
- macro_value: 4
- - macro_name: ET_LOOS
- macro_value: '0xfe00'
- - macro_name: ET_HIOS
- macro_value: '0xfeff'
- - macro_name: ET_LOPROC
- macro_value: '0xff00'
- - macro_name: ET_HIPROC
- macro_value: '0xffff'
- - macro_name: EM_NONE
- macro_value: 0
- - macro_name: EM_386
- macro_value: 3
- - macro_name: EM_ARM
- macro_value: 40
- - macro_name: EM_X86_64
- macro_value: 62
- - macro_name: EM_AARCH64
- macro_value: 183
- - macro_name: EM_RISCV
- macro_value: 243
- - macro_name: EV_NONE
- macro_value: 0
- - macro_name: EV_CURRENT
- macro_value: 1
- # Sections
- - macro_name: SHN_UNDEF
- macro_value: 0
- - macro_name: SHN_LORESERVE
- macro_value: '0xff00'
- - macro_name: SHN_LOPROC
- macro_value: '0xff00'
- - macro_name: SHN_HIPROC
- macro_value: '0xff1f'
- - macro_name: SHN_LOOS
- macro_value: '0xff20'
- - macro_name: SHN_HIOS
- macro_value: '0xff3f'
- - macro_name: SHN_ABS
- macro_value: '0xfff1'
- - macro_name: SHN_COMMON
- macro_value: '0xfff2'
- - macro_name: SHN_XINDEX
- macro_value: '0xffff'
- - macro_name: SHN_HIRESERVE
- macro_value: '0xffff'
- - macro_name: SHT_NULL
- macro_value: 0
- - macro_name: SHT_PROGBITS
- macro_value: 1
- - macro_name: SHT_SYMTAB
- macro_value: 2
- - macro_name: SHT_STRTAB
- macro_value: 3
- - macro_name: SHT_RELA
- macro_value: 4
- - macro_name: SHT_HASH
- macro_value: 5
- - macro_name: SHT_DYNAMIC
- macro_value: 6
- - macro_name: SHT_NOTE
- macro_value: 7
- - macro_name: SHT_NOBITS
- macro_value: 8
- - macro_name: SHT_REL
- macro_value: 9
- - macro_name: SHT_SHLIB
- macro_value: 10
- - macro_name: SHT_DYNSYM
- macro_value: 11
- - macro_name: SHT_INIT_ARRAY
- macro_value: 14
- - macro_name: SHT_FINI_ARRAY
- macro_value: 15
- - macro_name: SHT_PREINIT_ARRAY
- macro_value: 16
- - macro_name: SHT_GROUP
- macro_value: 17
- - macro_name: SHT_SYMTAB_SHNDX
- macro_value: 18
- - macro_name: SHT_LOOS
- macro_value: '0x60000000'
- - macro_name: SHT_HIOS
- macro_value: '0x6fffffff'
- - macro_name: SHT_LOPROC
- macro_value: '0x70000000'
- - macro_name: SHT_HIPROC
- macro_value: '0x7fffffff'
- - macro_name: SHT_LOUSER
- macro_value: '0x80000000'
- - macro_name: SHT_HIUSER
- macro_value: '0xffffffff'
- - macro_name: SHF_WRITE
- macro_value: '0x1'
- - macro_name: SHF_ALLOC
- macro_value: '0x2'
- - macro_name: SHF_EXECINSTR
- macro_value: '0x4'
- - macro_name: SHF_MERGE
- macro_value: '0x10'
- - macro_name: SHF_STRINGS
- macro_value: '0x20'
- - macro_name: SHF_INFO_LINK
- macro_value: '0x40'
- - macro_name: SHF_LINK_ORDER
- macro_value: '0x80'
- - macro_name: SHF_OS_NONCONFORMING
- macro_value: '0x100'
- - macro_name: SHF_GROUP
- macro_value: '0x200'
- - macro_name: SHF_TLS
- macro_value: '0x400'
- - macro_name: SHF_COMPRESSED
- macro_value: '0x800'
- - macro_name: SHF_MASKOS
- macro_value: '0x0ff00000'
- - macro_name: SHF_MASKPROC
- macro_value: '0xf0000000'
- - macro_name: ELFCOMPRESS_ZLIB
- macro_value: 1
- - macro_name: ELFCOMPRESS_ZSTD
- macro_value: 2
- - macro_name: ELFCOMPRESS_LOOS
- macro_value: '0x60000000'
- - macro_name: ELFCOMPRESS_HIOS
- macro_value: '0x6fffffff'
- - macro_name: ELFCOMPRESS_LOPROC
- macro_value: '0x70000000'
- - macro_name: ELFCOMPRESS_HIPROC
- macro_value: '0x7fffffff'
- # Symbol Table
- - macro_name: STN_UNDEF
- macro_value: 0
- - macro_name: STB_LOCAL
- macro_value: 0
- - macro_name: STB_GLOBAL
- macro_value: 1
- - macro_name: STB_WEAK
- macro_value: 2
- - macro_name: STB_LOOS
- macro_value: 10
- - macro_name: STB_HIOS
- macro_value: 12
- - macro_name: STB_LOPROC
- macro_value: 13
- - macro_name: STB_HIPROC
- macro_value: 15
- - macro_name: STT_NOTYPE
- macro_value: 0
- - macro_name: STT_OBJECT
- macro_value: 1
- - macro_name: STT_FUNC
- macro_value: 2
- - macro_name: STT_SECTION
- macro_value: 3
- - macro_name: STT_FILE
- macro_value: 4
- - macro_name: STT_COMMON
- macro_value: 5
- - macro_name: STT_TLS
- macro_value: 6
- - macro_name: STT_LOOS
- macro_value: 10
- - macro_name: STT_HIOS
- macro_value: 12
- - macro_name: STT_LOPROC
- macro_value: 13
- - macro_name: STT_HIPROC
- macro_value: 15
- - macro_name: STV_DEFAULT
- macro_value: 0
- - macro_name: STV_INTERNAL
- macro_value: 1
- - macro_name: STV_HIDDEN
- macro_value: 2
- - macro_name: STV_PROTECTED
- macro_value: 3
- # Program Loading
- - macro_name: PT_NULL
- macro_value: 0
- - macro_name: PT_LOAD
- macro_value: 1
- - macro_name: PT_DYNAMIC
- macro_value: 2
- - macro_name: PT_INTERP
- macro_value: 3
- - macro_name: PT_NOTE
- macro_value: 4
- - macro_name: PT_SHLIB
- macro_value: 5
- - macro_name: PT_PHDR
- macro_value: 6
- - macro_name: PT_TLS
- macro_value: 7
- - macro_name: PT_LOOS
- macro_value: '0x60000000'
- - macro_name: PT_HIOS
- macro_value: '0x6fffffff'
- - macro_name: PT_LOPROC
- macro_value: '0x70000000'
- - macro_name: PT_HIPROC
- macro_value: '0x7fffffff'
- - macro_name: PT_GNU_EH_FRAME
- macro_value: '0x6474e550'
- standards:
- - gnu
- - macro_name: PT_GNU_STACK
- macro_value: '0x6474e551'
- standards:
- - gnu
- - macro_name: PT_GNU_RELRO
- macro_value: '0x6474e552'
- standards:
- - gnu
- - macro_name: PT_GNU_PROPERTY
- macro_value: '0x6474e553'
- - macro_name: PF_X
- macro_value: '0x1'
- - macro_name: PF_W
- macro_value: '0x2'
- - macro_name: PF_R
- macro_value: '0x4'
- - macro_name: PF_MASKOS
- macro_value: '0x0ff00000'
- - macro_name: PF_MASKPROC
- macro_value: '0xf0000000'
- # Dynamic Linking
- - macro_name: DT_NULL
- macro_value: 0
- - macro_name: DT_NEEDED
- macro_value: 1
- - macro_name: DT_PLTRELSZ
- macro_value: 2
- - macro_name: DT_PLTGOT
- macro_value: 3
- - macro_name: DT_HASH
- macro_value: 4
- - macro_name: DT_STRTAB
- macro_value: 5
- - macro_name: DT_SYMTAB
- macro_value: 6
- - macro_name: DT_RELA
- macro_value: 7
- - macro_name: DT_RELASZ
- macro_value: 8
- - macro_name: DT_RELAENT
- macro_value: 9
- - macro_name: DT_STRSZ
- macro_value: 10
- - macro_name: DT_SYMENT
- macro_value: 11
- - macro_name: DT_INIT
- macro_value: 12
- - macro_name: DT_FINI
- macro_value: 13
- - macro_name: DT_SONAME
- macro_value: 14
- - macro_name: DT_RPATH
- macro_value: 15
- - macro_name: DT_SYMBOLIC
- macro_value: 16
- - macro_name: DT_REL
- macro_value: 17
- - macro_name: DT_RELSZ
- macro_value: 18
- - macro_name: DT_RELENT
- macro_value: 19
- - macro_name: DT_PLTREL
- macro_value: 20
- - macro_name: DT_DEBUG
- macro_value: 21
- - macro_name: DT_TEXTREL
- macro_value: 22
- - macro_name: DT_JMPREL
- macro_value: 23
- - macro_name: DT_BIND_NOW
- macro_value: 24
- - macro_name: DT_INIT_ARRAY
- macro_value: 25
- - macro_name: DT_FINI_ARRAY
- macro_value: 26
- - macro_name: DT_INIT_ARRAYSZ
- macro_value: 27
- - macro_name: DT_FINI_ARRAYSZ
- macro_value: 28
- - macro_name: DT_RUNPATH
- macro_value: 29
- - macro_name: DT_FLAGS
- macro_value: 30
- - macro_name: DT_ENCODING
- macro_value: 32
- - macro_name: DT_PREINIT_ARRAY
- macro_value: 32
- - macro_name: DT_PREINIT_ARRAYSZ
- macro_value: 33
- - macro_name: DT_SYMTAB_SHNDX
- macro_value: 34
- - macro_name: DT_LOOS
- macro_value: '0x6000000D'
- - macro_name: DT_HIOS
- macro_value: '0x6ffff000'
- - macro_name: DT_LOPROC
- macro_value: '0x70000000'
- - macro_name: DT_HIPROC
- macro_value: '0x7fffffff'
- - macro_name: DT_ADDRRNGLO
- macro_value: '0x6ffffe00'
- - macro_name: DT_GNU_HASH
- macro_value: '0x6ffffef5'
- standards:
- - gnu
- - macro_name: DT_TLSDESC_PLT
- macro_value: '0x6ffffef6'
- standards:
- - gnu
- - macro_name: DT_TLSDESC_GOT
- macro_value: '0x6ffffef7'
- standards:
- - gnu
- - macro_name: DT_GNU_CONFLICT
- macro_value: '0x6ffffef8'
- standards:
- - gnu
- - macro_name: DT_GNU_LIBLIST
- macro_value: '0x6ffffef9'
- standards:
- - gnu
- - macro_name: DT_CONFIG
- macro_value: '0x6ffffefa'
- - macro_name: DT_DEPAUDIT
- macro_value: '0x6ffffefb'
- - macro_name: DT_AUDIT
- macro_value: '0x6ffffefc'
- - macro_name: DT_PLTPAD
- macro_value: '0x6ffffefd'
- - macro_name: DT_MOVETAB
- macro_value: '0x6ffffefe'
- - macro_name: DT_SYMINFO
- macro_value: '0x6ffffeff'
- - macro_name: DT_ADDRRNGHI
- macro_value: '0x6ffffeff'
- - macro_name: DT_VERSYM
- macro_value: '0x6ffffff0'
- - macro_name: DT_RELACOUNT
- macro_value: '0x6ffffff9'
- - macro_name: DT_RELCOUNT
- macro_value: '0x6ffffffa'
- - macro_name: DT_VERDEF
- macro_value: '0x6ffffffc'
- - macro_name: DT_VERDEFNUM
- macro_value: '0x6ffffffd'
- - macro_name: DT_VERNEED
- macro_value: '0x6ffffffe'
- - macro_name: DT_VERNEEDNUM
- macro_value: '0x6fffffff'
- - macro_name: DF_ORIGIN
- macro_value: '0x1'
- - macro_name: DF_SYMBOLIC
- macro_value: '0x2'
- - macro_name: DF_TEXTREL
- macro_value: '0x4'
- - macro_name: DF_BIND_NOW
- macro_value: '0x8'
- - macro_name: DF_STATIC_TLS
- macro_value: '0x10'
- # Notes used in ET_CORE.
- - macro_name: NN_PRSTATUS
- macro_value: '"CORE"'
- - macro_name: NT_PRSTATUS
- macro_value: 1
- - macro_name: NN_PRFPREG
- macro_value: '"CORE"'
- - macro_name: NT_PRFPREG
- macro_value: 2
- - macro_name: NT_FPREGSET
- macro_value: 2
- - macro_name: NN_PRPSINFO
- macro_value: '"CORE"'
- - macro_name: NT_PRPSINFO
- macro_value: 3
- - macro_name: NN_TASKSTRUCT
- macro_value: '"CORE"'
- - macro_name: NT_TASKSTRUCT
- macro_value: 4
- - macro_name: NT_PRXREG
- macro_value: 4
- - macro_name: NT_PLATFORM
- macro_value: 5
- - macro_name: NN_AUXV
- macro_value: '"CORE"'
- - macro_name: NT_AUXV
- macro_value: 6
- - macro_name: NN_SIGINFO
- macro_value: '"CORE"'
- - macro_name: NT_SIGINFO
- macro_value: '0x53494749'
- - macro_name: NN_FILE
- macro_value: '"CORE"'
- - macro_name: NT_FILE
- macro_value: '0x46494c45'
- - macro_name: NT_PRFPXREG
- macro_value: 20
- # Notes used by GNU toolchain.
- - macro_name: NT_GNU_ABI_TAG
- macro_value: 1
- standards:
- - gnu
- - macro_name: NT_GNU_HWCAP
- macro_value: 2
- standards:
- - gnu
- - macro_name: NT_GNU_BUILD_ID
- macro_value: 3
- standards:
- - gnu
- - macro_name: NT_GNU_GOLD_VERSION
- macro_value: 4
- standards:
- - gnu
- - macro_name: NT_GNU_PROPERTY_TYPE_0
- macro_value: 5
- standards:
- - gnu
- # Symbol Versioning
- - macro_name: VER_DEF_NONE
- macro_value: 0
- - macro_name: VER_DEF_CURRENT
- macro_value: 1
- - macro_name: VER_DEF_NUM
- macro_value: 2
- - macro_name: VER_FLG_BASE
- macro_value: '0x1'
- - macro_name: VER_FLG_WEAK
- macro_value: '0x2'
- - macro_name: VER_NDX_LOCAL
- macro_value: 0
- - macro_name: VER_NDX_GLOBAL
- macro_value: 1
- - macro_name: VER_NDX_LORESERVE
- macro_value: '0xff00'
- - macro_name: VER_NDX_ELIMINATE
- macro_value: '0xff01'
- # Values used in the .note.gnu.property section.
- - macro_name: GNU_PROPERTY_X86_FEATURE_1_AND
- macro_value: '0xc0000002'
- - macro_name: GNU_PROPERTY_X86_FEATURE_1_SHSTK
- macro_value: '0x00000002'
- # Architecture-specific IRELATIVE relocation types
- - macro_name: R_AARCH64_IRELATIVE
- macro_value: 1032
- - macro_name: R_ARM_IRELATIVE
- macro_value: 160
- - macro_name: R_RISCV_IRELATIVE
- macro_value: 58
- - macro_name: R_X86_64_IRELATIVE
- macro_value: 37
- - macro_name: ELF32_ST_BIND
- macro_header: elf-macros.h
- - macro_name: ELF32_ST_TYPE
- macro_header: elf-macros.h
- - macro_name: ELF32_ST_INFO
- macro_header: elf-macros.h
- - macro_name: ELF64_ST_BIND
- macro_header: elf-macros.h
- - macro_name: ELF64_ST_TYPE
- macro_header: elf-macros.h
- - macro_name: ELF64_ST_INFO
- macro_header: elf-macros.h
- - macro_name: ELF32_ST_VISIBILITY
- macro_header: elf-macros.h
- - macro_name: ELF64_ST_VISIBILITY
- macro_header: elf-macros.h
- - macro_name: ELF32_R_SYM
- macro_header: elf-macros.h
- - macro_name: ELF32_R_TYPE
- macro_header: elf-macros.h
- - macro_name: ELF32_R_INFO
- macro_header: elf-macros.h
- - macro_name: ELF64_R_SYM
- macro_header: elf-macros.h
- - macro_name: ELF64_R_TYPE
- macro_header: elf-macros.h
- - macro_name: ELF64_R_INFO
- macro_header: elf-macros.h
- - macro_name: PT_AARCH64_MEMTAG_MTE
- macro_value: '0x70000002'
- - macro_name: PN_XNUM
- macro_value: '0xffff'
- - macro_name: ELFCLASSNUM
- macro_value: 3
- - macro_name: EV_NUM
- macro_value: 2
- - macro_name: AT_NULL
- macro_header: sys-auxv-macros.h
- - macro_name: AT_IGNORE
- macro_header: sys-auxv-macros.h
- - macro_name: AT_EXECFD
- macro_header: sys-auxv-macros.h
- - macro_name: AT_PHDR
- macro_header: sys-auxv-macros.h
- - macro_name: AT_PHENT
- macro_header: sys-auxv-macros.h
- - macro_name: AT_PHNUM
- macro_header: sys-auxv-macros.h
- - macro_name: AT_PAGESZ
- macro_header: sys-auxv-macros.h
- - macro_name: AT_BASE
- macro_header: sys-auxv-macros.h
- - macro_name: AT_FLAGS
- macro_header: sys-auxv-macros.h
- - macro_name: AT_ENTRY
- macro_header: sys-auxv-macros.h
- - macro_name: AT_NOTELF
- macro_header: sys-auxv-macros.h
- - macro_name: AT_UID
- macro_header: sys-auxv-macros.h
- - macro_name: AT_EUID
- macro_header: sys-auxv-macros.h
- - macro_name: AT_GID
- macro_header: sys-auxv-macros.h
- - macro_name: AT_EGID
- macro_header: sys-auxv-macros.h
- - macro_name: AT_PLATFORM
- macro_header: sys-auxv-macros.h
- - macro_name: AT_HWCAP
- macro_header: sys-auxv-macros.h
- - macro_name: AT_CLKTCK
- macro_header: sys-auxv-macros.h
- - macro_name: AT_SECURE
- macro_header: sys-auxv-macros.h
- - macro_name: AT_BASE_PLATFORM
- macro_header: sys-auxv-macros.h
- - macro_name: AT_RANDOM
- macro_header: sys-auxv-macros.h
- - macro_name: AT_HWCAP2
- macro_header: sys-auxv-macros.h
- - macro_name: AT_RSEQ_FEATURE_SIZE
- macro_header: sys-auxv-macros.h
- - macro_name: AT_RSEQ_ALIGN
- macro_header: sys-auxv-macros.h
- - macro_name: AT_HWCAP3
- macro_header: sys-auxv-macros.h
- - macro_name: AT_HWCAP4
- macro_header: sys-auxv-macros.h
- - macro_name: AT_EXECFN
- macro_header: sys-auxv-macros.h
- - macro_name: AT_SYSINFO
- macro_header: sys-auxv-macros.h
- - macro_name: AT_SYSINFO_EHDR
- macro_header: sys-auxv-macros.h
- - macro_name: AT_MINSIGSTKSZ
- macro_header: sys-auxv-macros.h
-types:
- - type_name: Elf32_Addr
- - type_name: Elf32_Chdr
- - type_name: Elf32_Dyn
- - type_name: Elf32_Ehdr
- - type_name: Elf32_Half
- - type_name: Elf32_Lword
- - type_name: Elf32_Nhdr
- - type_name: Elf32_Off
- - type_name: Elf32_Phdr
- - type_name: Elf32_Rel
- - type_name: Elf32_Rela
- - type_name: Elf32_Shdr
- - type_name: Elf32_Sword
- - type_name: Elf32_Sym
- - type_name: Elf32_Verdaux
- - type_name: Elf32_Verdef
- - type_name: Elf32_Vernaux
- - type_name: Elf32_Verneed
- - type_name: Elf32_Versym
- - type_name: Elf32_Word
- - type_name: Elf32_Xword
- - type_name: Elf32_auxv_t
- - type_name: Elf64_Addr
- - type_name: Elf64_Chdr
- - type_name: Elf64_Dyn
- - type_name: Elf64_Ehdr
- - type_name: Elf64_Half
- - type_name: Elf64_Lword
- - type_name: Elf64_Nhdr
- - type_name: Elf64_Off
- - type_name: Elf64_Phdr
- - type_name: Elf64_Rel
- - type_name: Elf64_Rela
- - type_name: Elf64_Shdr
- - type_name: Elf64_Sword
- - type_name: Elf64_Sxword
- - type_name: Elf64_Sym
- - type_name: Elf64_Verdaux
- - type_name: Elf64_Verdef
- - type_name: Elf64_Vernaux
- - type_name: Elf64_Verneed
- - type_name: Elf64_Versym
- - type_name: Elf64_Word
- - type_name: Elf64_Xword
- - type_name: Elf64_auxv_t
-enums: []
-objects: []
-functions: []
diff --git a/libc/include/llvm-libc-proxy/CMakeLists.txt b/libc/include/llvm-libc-proxy/CMakeLists.txt
new file mode 100644
index 0000000000000..56409c8f1e627
--- /dev/null
+++ b/libc/include/llvm-libc-proxy/CMakeLists.txt
@@ -0,0 +1,59 @@
+file(MAKE_DIRECTORY ${LIBC_INCLUDE_DIR}/llvm-libc-proxy)
+
+add_gen_header(
+ elf_proxy
+ YAML_FILE
+ ../libc/include/llvm-libc-proxy/elf_proxy.yaml
+ GEN_HDR
+ elf_proxy.h
+ DEPENDS
+ libc.include.llvm_libc_common_h
+ libc.include.llvm-libc-macros.elf_macros
+ libc.include.llvm-libc-macros.sys_auxv_macros
+ libc.include.llvm-libc-types.Elf32_Addr
+ libc.include.llvm-libc-types.Elf32_Chdr
+ libc.include.llvm-libc-types.Elf32_Dyn
+ libc.include.llvm-libc-types.Elf32_Ehdr
+ libc.include.llvm-libc-types.Elf32_Half
+ libc.include.llvm-libc-types.Elf32_Lword
+ libc.include.llvm-libc-types.Elf32_Nhdr
+ libc.include.llvm-libc-types.Elf32_Off
+ libc.include.llvm-libc-types.Elf32_Phdr
+ libc.include.llvm-libc-types.Elf32_Rel
+ libc.include.llvm-libc-types.Elf32_Rela
+ libc.include.llvm-libc-types.Elf32_Shdr
+ libc.include.llvm-libc-types.Elf32_Sword
+ libc.include.llvm-libc-types.Elf32_Sym
+ libc.include.llvm-libc-types.Elf32_Verdaux
+ libc.include.llvm-libc-types.Elf32_Verdef
+ libc.include.llvm-libc-types.Elf32_Vernaux
+ libc.include.llvm-libc-types.Elf32_Verneed
+ libc.include.llvm-libc-types.Elf32_Versym
+ libc.include.llvm-libc-types.Elf32_Word
+ libc.include.llvm-libc-types.Elf32_Xword
+ libc.include.llvm-libc-types.Elf32_auxv_t
+ libc.include.llvm-libc-types.Elf64_Addr
+ libc.include.llvm-libc-types.Elf64_Chdr
+ libc.include.llvm-libc-types.Elf64_Dyn
+ libc.include.llvm-libc-types.Elf64_Ehdr
+ libc.include.llvm-libc-types.Elf64_Half
+ libc.include.llvm-libc-types.Elf64_Lword
+ libc.include.llvm-libc-types.Elf64_Nhdr
+ libc.include.llvm-libc-types.Elf64_Off
+ libc.include.llvm-libc-types.Elf64_Phdr
+ libc.include.llvm-libc-types.Elf64_Rel
+ libc.include.llvm-libc-types.Elf64_Rela
+ libc.include.llvm-libc-types.Elf64_Shdr
+ libc.include.llvm-libc-types.Elf64_Sword
+ libc.include.llvm-libc-types.Elf64_Sxword
+ libc.include.llvm-libc-types.Elf64_Sym
+ libc.include.llvm-libc-types.Elf64_Verdaux
+ libc.include.llvm-libc-types.Elf64_Verdef
+ libc.include.llvm-libc-types.Elf64_Vernaux
+ libc.include.llvm-libc-types.Elf64_Verneed
+ libc.include.llvm-libc-types.Elf64_Versym
+ libc.include.llvm-libc-types.Elf64_Word
+ libc.include.llvm-libc-types.Elf64_Xword
+ libc.include.llvm-libc-types.Elf64_auxv_t
+ PROXY
+)
diff --git a/libc/include/llvm-libc-proxy/elf_proxy.yaml b/libc/include/llvm-libc-proxy/elf_proxy.yaml
new file mode 100644
index 0000000000000..2b11dfe2a343f
--- /dev/null
+++ b/libc/include/llvm-libc-proxy/elf_proxy.yaml
@@ -0,0 +1,667 @@
+header: elf.h
+standards:
+ - svid
+macros:
+ # ELF Header
+ - macro_name: EI_NIDENT
+ macro_value: 16
+ - macro_name: EI_MAG0
+ macro_value: 0
+ - macro_name: EI_MAG1
+ macro_value: 1
+ - macro_name: EI_MAG2
+ macro_value: 2
+ - macro_name: EI_MAG3
+ macro_value: 3
+ - macro_name: EI_CLASS
+ macro_value: 4
+ - macro_name: EI_DATA
+ macro_value: 5
+ - macro_name: EI_VERSION
+ macro_value: 6
+ - macro_name: EI_OSABI
+ macro_value: 7
+ - macro_name: EI_ABIVERSION
+ macro_value: 8
+ - macro_name: EI_PAD
+ macro_value: 9
+ - macro_name: EI_NIDENT
+ macro_value: 16
+ - macro_name: ELFMAG0
+ macro_value: '0x7f'
+ - macro_name: ELFMAG1
+ macro_value: "'E'"
+ - macro_name: ELFMAG2
+ macro_value: "'L'"
+ - macro_name: ELFMAG3
+ macro_value: "'F'"
+ - macro_name: ELFMAG
+ macro_value: '"\177ELF"'
+ - macro_name: SELFMAG
+ macro_value: 4
+ - macro_name: ELFCLASSNONE
+ macro_value: 0
+ - macro_name: ELFCLASS32
+ macro_value: 1
+ - macro_name: ELFCLASS64
+ macro_value: 2
+ - macro_name: ELFDATANONE
+ macro_value: 0
+ - macro_name: ELFDATA2LSB
+ macro_value: 1
+ - macro_name: ELFDATA2MSB
+ macro_value: 2
+ - macro_name: ELFOSABI_NONE
+ macro_value: 0
+ - macro_name: ELFOSABI_LINUX
+ macro_value: 3
+ - macro_name: ET_NONE
+ macro_value: 0
+ - macro_name: ET_REL
+ macro_value: 1
+ - macro_name: ET_EXEC
+ macro_value: 2
+ - macro_name: ET_DYN
+ macro_value: 3
+ - macro_name: ET_CORE
+ macro_value: 4
+ - macro_name: ET_LOOS
+ macro_value: '0xfe00'
+ - macro_name: ET_HIOS
+ macro_value: '0xfeff'
+ - macro_name: ET_LOPROC
+ macro_value: '0xff00'
+ - macro_name: ET_HIPROC
+ macro_value: '0xffff'
+ - macro_name: EM_NONE
+ macro_value: 0
+ - macro_name: EM_386
+ macro_value: 3
+ - macro_name: EM_ARM
+ macro_value: 40
+ - macro_name: EM_X86_64
+ macro_value: 62
+ - macro_name: EM_AARCH64
+ macro_value: 183
+ - macro_name: EM_RISCV
+ macro_value: 243
+ - macro_name: EV_NONE
+ macro_value: 0
+ - macro_name: EV_CURRENT
+ macro_value: 1
+ # Sections
+ - macro_name: SHN_UNDEF
+ macro_value: 0
+ - macro_name: SHN_LORESERVE
+ macro_value: '0xff00'
+ - macro_name: SHN_LOPROC
+ macro_value: '0xff00'
+ - macro_name: SHN_HIPROC
+ macro_value: '0xff1f'
+ - macro_name: SHN_LOOS
+ macro_value: '0xff20'
+ - macro_name: SHN_HIOS
+ macro_value: '0xff3f'
+ - macro_name: SHN_ABS
+ macro_value: '0xfff1'
+ - macro_name: SHN_COMMON
+ macro_value: '0xfff2'
+ - macro_name: SHN_XINDEX
+ macro_value: '0xffff'
+ - macro_name: SHN_HIRESERVE
+ macro_value: '0xffff'
+ - macro_name: SHT_NULL
+ macro_value: 0
+ - macro_name: SHT_PROGBITS
+ macro_value: 1
+ - macro_name: SHT_SYMTAB
+ macro_value: 2
+ - macro_name: SHT_STRTAB
+ macro_value: 3
+ - macro_name: SHT_RELA
+ macro_value: 4
+ - macro_name: SHT_HASH
+ macro_value: 5
+ - macro_name: SHT_DYNAMIC
+ macro_value: 6
+ - macro_name: SHT_NOTE
+ macro_value: 7
+ - macro_name: SHT_NOBITS
+ macro_value: 8
+ - macro_name: SHT_REL
+ macro_value: 9
+ - macro_name: SHT_SHLIB
+ macro_value: 10
+ - macro_name: SHT_DYNSYM
+ macro_value: 11
+ - macro_name: SHT_INIT_ARRAY
+ macro_value: 14
+ - macro_name: SHT_FINI_ARRAY
+ macro_value: 15
+ - macro_name: SHT_PREINIT_ARRAY
+ macro_value: 16
+ - macro_name: SHT_GROUP
+ macro_value: 17
+ - macro_name: SHT_SYMTAB_SHNDX
+ macro_value: 18
+ - macro_name: SHT_LOOS
+ macro_value: '0x60000000'
+ - macro_name: SHT_HIOS
+ macro_value: '0x6fffffff'
+ - macro_name: SHT_LOPROC
+ macro_value: '0x70000000'
+ - macro_name: SHT_HIPROC
+ macro_value: '0x7fffffff'
+ - macro_name: SHT_LOUSER
+ macro_value: '0x80000000'
+ - macro_name: SHT_HIUSER
+ macro_value: '0xffffffff'
+ - macro_name: SHF_WRITE
+ macro_value: '0x1'
+ - macro_name: SHF_ALLOC
+ macro_value: '0x2'
+ - macro_name: SHF_EXECINSTR
+ macro_value: '0x4'
+ - macro_name: SHF_MERGE
+ macro_value: '0x10'
+ - macro_name: SHF_STRINGS
+ macro_value: '0x20'
+ - macro_name: SHF_INFO_LINK
+ macro_value: '0x40'
+ - macro_name: SHF_LINK_ORDER
+ macro_value: '0x80'
+ - macro_name: SHF_OS_NONCONFORMING
+ macro_value: '0x100'
+ - macro_name: SHF_GROUP
+ macro_value: '0x200'
+ - macro_name: SHF_TLS
+ macro_value: '0x400'
+ - macro_name: SHF_COMPRESSED
+ macro_value: '0x800'
+ - macro_name: SHF_MASKOS
+ macro_value: '0x0ff00000'
+ - macro_name: SHF_MASKPROC
+ macro_value: '0xf0000000'
+ - macro_name: ELFCOMPRESS_ZLIB
+ macro_value: 1
+ - macro_name: ELFCOMPRESS_ZSTD
+ macro_value: 2
+ - macro_name: ELFCOMPRESS_LOOS
+ macro_value: '0x60000000'
+ - macro_name: ELFCOMPRESS_HIOS
+ macro_value: '0x6fffffff'
+ - macro_name: ELFCOMPRESS_LOPROC
+ macro_value: '0x70000000'
+ - macro_name: ELFCOMPRESS_HIPROC
+ macro_value: '0x7fffffff'
+ # Symbol Table
+ - macro_name: STN_UNDEF
+ macro_value: 0
+ - macro_name: STB_LOCAL
+ macro_value: 0
+ - macro_name: STB_GLOBAL
+ macro_value: 1
+ - macro_name: STB_WEAK
+ macro_value: 2
+ - macro_name: STB_LOOS
+ macro_value: 10
+ - macro_name: STB_HIOS
+ macro_value: 12
+ - macro_name: STB_LOPROC
+ macro_value: 13
+ - macro_name: STB_HIPROC
+ macro_value: 15
+ - macro_name: STT_NOTYPE
+ macro_value: 0
+ - macro_name: STT_OBJECT
+ macro_value: 1
+ - macro_name: STT_FUNC
+ macro_value: 2
+ - macro_name: STT_SECTION
+ macro_value: 3
+ - macro_name: STT_FILE
+ macro_value: 4
+ - macro_name: STT_COMMON
+ macro_value: 5
+ - macro_name: STT_TLS
+ macro_value: 6
+ - macro_name: STT_LOOS
+ macro_value: 10
+ - macro_name: STT_HIOS
+ macro_value: 12
+ - macro_name: STT_LOPROC
+ macro_value: 13
+ - macro_name: STT_HIPROC
+ macro_value: 15
+ - macro_name: STV_DEFAULT
+ macro_value: 0
+ - macro_name: STV_INTERNAL
+ macro_value: 1
+ - macro_name: STV_HIDDEN
+ macro_value: 2
+ - macro_name: STV_PROTECTED
+ macro_value: 3
+ # Program Loading
+ - macro_name: PT_NULL
+ macro_value: 0
+ - macro_name: PT_LOAD
+ macro_value: 1
+ - macro_name: PT_DYNAMIC
+ macro_value: 2
+ - macro_name: PT_INTERP
+ macro_value: 3
+ - macro_name: PT_NOTE
+ macro_value: 4
+ - macro_name: PT_SHLIB
+ macro_value: 5
+ - macro_name: PT_PHDR
+ macro_value: 6
+ - macro_name: PT_TLS
+ macro_value: 7
+ - macro_name: PT_LOOS
+ macro_value: '0x60000000'
+ - macro_name: PT_HIOS
+ macro_value: '0x6fffffff'
+ - macro_name: PT_LOPROC
+ macro_value: '0x70000000'
+ - macro_name: PT_HIPROC
+ macro_value: '0x7fffffff'
+ - macro_name: PT_GNU_EH_FRAME
+ macro_value: '0x6474e550'
+ standards:
+ - gnu
+ - macro_name: PT_GNU_STACK
+ macro_value: '0x6474e551'
+ standards:
+ - gnu
+ - macro_name: PT_GNU_RELRO
+ macro_value: '0x6474e552'
+ standards:
+ - gnu
+ - macro_name: PT_GNU_PROPERTY
+ macro_value: '0x6474e553'
+ - macro_name: PF_X
+ macro_value: '0x1'
+ - macro_name: PF_W
+ macro_value: '0x2'
+ - macro_name: PF_R
+ macro_value: '0x4'
+ - macro_name: PF_MASKOS
+ macro_value: '0x0ff00000'
+ - macro_name: PF_MASKPROC
+ macro_value: '0xf0000000'
+ # Dynamic Linking
+ - macro_name: DT_NULL
+ macro_value: 0
+ - macro_name: DT_NEEDED
+ macro_value: 1
+ - macro_name: DT_PLTRELSZ
+ macro_value: 2
+ - macro_name: DT_PLTGOT
+ macro_value: 3
+ - macro_name: DT_HASH
+ macro_value: 4
+ - macro_name: DT_STRTAB
+ macro_value: 5
+ - macro_name: DT_SYMTAB
+ macro_value: 6
+ - macro_name: DT_RELA
+ macro_value: 7
+ - macro_name: DT_RELASZ
+ macro_value: 8
+ - macro_name: DT_RELAENT
+ macro_value: 9
+ - macro_name: DT_STRSZ
+ macro_value: 10
+ - macro_name: DT_SYMENT
+ macro_value: 11
+ - macro_name: DT_INIT
+ macro_value: 12
+ - macro_name: DT_FINI
+ macro_value: 13
+ - macro_name: DT_SONAME
+ macro_value: 14
+ - macro_name: DT_RPATH
+ macro_value: 15
+ - macro_name: DT_SYMBOLIC
+ macro_value: 16
+ - macro_name: DT_REL
+ macro_value: 17
+ - macro_name: DT_RELSZ
+ macro_value: 18
+ - macro_name: DT_RELENT
+ macro_value: 19
+ - macro_name: DT_PLTREL
+ macro_value: 20
+ - macro_name: DT_DEBUG
+ macro_value: 21
+ - macro_name: DT_TEXTREL
+ macro_value: 22
+ - macro_name: DT_JMPREL
+ macro_value: 23
+ - macro_name: DT_BIND_NOW
+ macro_value: 24
+ - macro_name: DT_INIT_ARRAY
+ macro_value: 25
+ - macro_name: DT_FINI_ARRAY
+ macro_value: 26
+ - macro_name: DT_INIT_ARRAYSZ
+ macro_value: 27
+ - macro_name: DT_FINI_ARRAYSZ
+ macro_value: 28
+ - macro_name: DT_RUNPATH
+ macro_value: 29
+ - macro_name: DT_FLAGS
+ macro_value: 30
+ - macro_name: DT_ENCODING
+ macro_value: 32
+ - macro_name: DT_PREINIT_ARRAY
+ macro_value: 32
+ - macro_name: DT_PREINIT_ARRAYSZ
+ macro_value: 33
+ - macro_name: DT_SYMTAB_SHNDX
+ macro_value: 34
+ - macro_name: DT_LOOS
+ macro_value: '0x6000000D'
+ - macro_name: DT_HIOS
+ macro_value: '0x6ffff000'
+ - macro_name: DT_LOPROC
+ macro_value: '0x70000000'
+ - macro_name: DT_HIPROC
+ macro_value: '0x7fffffff'
+ - macro_name: DT_ADDRRNGLO
+ macro_value: '0x6ffffe00'
+ - macro_name: DT_GNU_HASH
+ macro_value: '0x6ffffef5'
+ standards:
+ - gnu
+ - macro_name: DT_TLSDESC_PLT
+ macro_value: '0x6ffffef6'
+ standards:
+ - gnu
+ - macro_name: DT_TLSDESC_GOT
+ macro_value: '0x6ffffef7'
+ standards:
+ - gnu
+ - macro_name: DT_GNU_CONFLICT
+ macro_value: '0x6ffffef8'
+ standards:
+ - gnu
+ - macro_name: DT_GNU_LIBLIST
+ macro_value: '0x6ffffef9'
+ standards:
+ - gnu
+ - macro_name: DT_CONFIG
+ macro_value: '0x6ffffefa'
+ - macro_name: DT_DEPAUDIT
+ macro_value: '0x6ffffefb'
+ - macro_name: DT_AUDIT
+ macro_value: '0x6ffffefc'
+ - macro_name: DT_PLTPAD
+ macro_value: '0x6ffffefd'
+ - macro_name: DT_MOVETAB
+ macro_value: '0x6ffffefe'
+ - macro_name: DT_SYMINFO
+ macro_value: '0x6ffffeff'
+ - macro_name: DT_ADDRRNGHI
+ macro_value: '0x6ffffeff'
+ - macro_name: DT_VERSYM
+ macro_value: '0x6ffffff0'
+ - macro_name: DT_RELACOUNT
+ macro_value: '0x6ffffff9'
+ - macro_name: DT_RELCOUNT
+ macro_value: '0x6ffffffa'
+ - macro_name: DT_VERDEF
+ macro_value: '0x6ffffffc'
+ - macro_name: DT_VERDEFNUM
+ macro_value: '0x6ffffffd'
+ - macro_name: DT_VERNEED
+ macro_value: '0x6ffffffe'
+ - macro_name: DT_VERNEEDNUM
+ macro_value: '0x6fffffff'
+ - macro_name: DF_ORIGIN
+ macro_value: '0x1'
+ - macro_name: DF_SYMBOLIC
+ macro_value: '0x2'
+ - macro_name: DF_TEXTREL
+ macro_value: '0x4'
+ - macro_name: DF_BIND_NOW
+ macro_value: '0x8'
+ - macro_name: DF_STATIC_TLS
+ macro_value: '0x10'
+ # Notes used in ET_CORE.
+ - macro_name: NN_PRSTATUS
+ macro_value: '"CORE"'
+ - macro_name: NT_PRSTATUS
+ macro_value: 1
+ - macro_name: NN_PRFPREG
+ macro_value: '"CORE"'
+ - macro_name: NT_PRFPREG
+ macro_value: 2
+ - macro_name: NT_FPREGSET
+ macro_value: 2
+ - macro_name: NN_PRPSINFO
+ macro_value: '"CORE"'
+ - macro_name: NT_PRPSINFO
+ macro_value: 3
+ - macro_name: NN_TASKSTRUCT
+ macro_value: '"CORE"'
+ - macro_name: NT_TASKSTRUCT
+ macro_value: 4
+ - macro_name: NT_PRXREG
+ macro_value: 4
+ - macro_name: NT_PLATFORM
+ macro_value: 5
+ - macro_name: NN_AUXV
+ macro_value: '"CORE"'
+ - macro_name: NT_AUXV
+ macro_value: 6
+ - macro_name: NN_SIGINFO
+ macro_value: '"CORE"'
+ - macro_name: NT_SIGINFO
+ macro_value: '0x53494749'
+ - macro_name: NN_FILE
+ macro_value: '"CORE"'
+ - macro_name: NT_FILE
+ macro_value: '0x46494c45'
+ - macro_name: NT_PRFPXREG
+ macro_value: 20
+ # Notes used by GNU toolchain.
+ - macro_name: NT_GNU_ABI_TAG
+ macro_value: 1
+ standards:
+ - gnu
+ - macro_name: NT_GNU_HWCAP
+ macro_value: 2
+ standards:
+ - gnu
+ - macro_name: NT_GNU_BUILD_ID
+ macro_value: 3
+ standards:
+ - gnu
+ - macro_name: NT_GNU_GOLD_VERSION
+ macro_value: 4
+ standards:
+ - gnu
+ - macro_name: NT_GNU_PROPERTY_TYPE_0
+ macro_value: 5
+ standards:
+ - gnu
+ # Symbol Versioning
+ - macro_name: VER_DEF_NONE
+ macro_value: 0
+ - macro_name: VER_DEF_CURRENT
+ macro_value: 1
+ - macro_name: VER_DEF_NUM
+ macro_value: 2
+ - macro_name: VER_FLG_BASE
+ macro_value: '0x1'
+ - macro_name: VER_FLG_WEAK
+ macro_value: '0x2'
+ - macro_name: VER_NDX_LOCAL
+ macro_value: 0
+ - macro_name: VER_NDX_GLOBAL
+ macro_value: 1
+ - macro_name: VER_NDX_LORESERVE
+ macro_value: '0xff00'
+ - macro_name: VER_NDX_ELIMINATE
+ macro_value: '0xff01'
+ # Values used in the .note.gnu.property section.
+ - macro_name: GNU_PROPERTY_X86_FEATURE_1_AND
+ macro_value: '0xc0000002'
+ - macro_name: GNU_PROPERTY_X86_FEATURE_1_SHSTK
+ macro_value: '0x00000002'
+ # Architecture-specific IRELATIVE relocation types
+ - macro_name: R_AARCH64_IRELATIVE
+ macro_value: 1032
+ - macro_name: R_ARM_IRELATIVE
+ macro_value: 160
+ - macro_name: R_RISCV_IRELATIVE
+ macro_value: 58
+ - macro_name: R_X86_64_IRELATIVE
+ macro_value: 37
+ - macro_name: ELF32_ST_BIND
+ macro_header: elf-macros.h
+ - macro_name: ELF32_ST_TYPE
+ macro_header: elf-macros.h
+ - macro_name: ELF32_ST_INFO
+ macro_header: elf-macros.h
+ - macro_name: ELF64_ST_BIND
+ macro_header: elf-macros.h
+ - macro_name: ELF64_ST_TYPE
+ macro_header: elf-macros.h
+ - macro_name: ELF64_ST_INFO
+ macro_header: elf-macros.h
+ - macro_name: ELF32_ST_VISIBILITY
+ macro_header: elf-macros.h
+ - macro_name: ELF64_ST_VISIBILITY
+ macro_header: elf-macros.h
+ - macro_name: ELF32_R_SYM
+ macro_header: elf-macros.h
+ - macro_name: ELF32_R_TYPE
+ macro_header: elf-macros.h
+ - macro_name: ELF32_R_INFO
+ macro_header: elf-macros.h
+ - macro_name: ELF64_R_SYM
+ macro_header: elf-macros.h
+ - macro_name: ELF64_R_TYPE
+ macro_header: elf-macros.h
+ - macro_name: ELF64_R_INFO
+ macro_header: elf-macros.h
+ - macro_name: PT_AARCH64_MEMTAG_MTE
+ macro_value: '0x70000002'
+ - macro_name: PN_XNUM
+ macro_value: '0xffff'
+ - macro_name: ELFCLASSNUM
+ macro_value: 3
+ - macro_name: EV_NUM
+ macro_value: 2
+ - macro_name: AT_NULL
+ macro_header: sys-auxv-macros.h
+ - macro_name: AT_IGNORE
+ macro_header: sys-auxv-macros.h
+ - macro_name: AT_EXECFD
+ macro_header: sys-auxv-macros.h
+ - macro_name: AT_PHDR
+ macro_header: sys-auxv-macros.h
+ - macro_name: AT_PHENT
+ macro_header: sys-auxv-macros.h
+ - macro_name: AT_PHNUM
+ macro_header: sys-auxv-macros.h
+ - macro_name: AT_PAGESZ
+ macro_header: sys-auxv-macros.h
+ - macro_name: AT_BASE
+ macro_header: sys-auxv-macros.h
+ - macro_name: AT_FLAGS
+ macro_header: sys-auxv-macros.h
+ - macro_name: AT_ENTRY
+ macro_header: sys-auxv-macros.h
+ - macro_name: AT_NOTELF
+ macro_header: sys-auxv-macros.h
+ - macro_name: AT_UID
+ macro_header: sys-auxv-macros.h
+ - macro_name: AT_EUID
+ macro_header: sys-auxv-macros.h
+ - macro_name: AT_GID
+ macro_header: sys-auxv-macros.h
+ - macro_name: AT_EGID
+ macro_header: sys-auxv-macros.h
+ - macro_name: AT_PLATFORM
+ macro_header: sys-auxv-macros.h
+ - macro_name: AT_HWCAP
+ macro_header: sys-auxv-macros.h
+ - macro_name: AT_CLKTCK
+ macro_header: sys-auxv-macros.h
+ - macro_name: AT_SECURE
+ macro_header: sys-auxv-macros.h
+ - macro_name: AT_BASE_PLATFORM
+ macro_header: sys-auxv-macros.h
+ - macro_name: AT_RANDOM
+ macro_header: sys-auxv-macros.h
+ - macro_name: AT_HWCAP2
+ macro_header: sys-auxv-macros.h
+ - macro_name: AT_RSEQ_FEATURE_SIZE
+ macro_header: sys-auxv-macros.h
+ - macro_name: AT_RSEQ_ALIGN
+ macro_header: sys-auxv-macros.h
+ - macro_name: AT_HWCAP3
+ macro_header: sys-auxv-macros.h
+ - macro_name: AT_HWCAP4
+ macro_header: sys-auxv-macros.h
+ - macro_name: AT_EXECFN
+ macro_header: sys-auxv-macros.h
+ - macro_name: AT_SYSINFO
+ macro_header: sys-auxv-macros.h
+ - macro_name: AT_SYSINFO_EHDR
+ macro_header: sys-auxv-macros.h
+ - macro_name: AT_MINSIGSTKSZ
+ macro_header: sys-auxv-macros.h
+types:
+ - type_name: Elf32_Addr
+ - type_name: Elf32_Chdr
+ - type_name: Elf32_Dyn
+ - type_name: Elf32_Ehdr
+ - type_name: Elf32_Half
+ - type_name: Elf32_Lword
+ - type_name: Elf32_Nhdr
+ - type_name: Elf32_Off
+ - type_name: Elf32_Phdr
+ - type_name: Elf32_Rel
+ - type_name: Elf32_Rela
+ - type_name: Elf32_Shdr
+ - type_name: Elf32_Sword
+ - type_name: Elf32_Sym
+ - type_name: Elf32_Verdaux
+ - type_name: Elf32_Verdef
+ - type_name: Elf32_Vernaux
+ - type_name: Elf32_Verneed
+ - type_name: Elf32_Versym
+ - type_name: Elf32_Word
+ - type_name: Elf32_Xword
+ - type_name: Elf32_auxv_t
+ - type_name: Elf64_Addr
+ - type_name: Elf64_Chdr
+ - type_name: Elf64_Dyn
+ - type_name: Elf64_Ehdr
+ - type_name: Elf64_Half
+ - type_name: Elf64_Lword
+ - type_name: Elf64_Nhdr
+ - type_name: Elf64_Off
+ - type_name: Elf64_Phdr
+ - type_name: Elf64_Rel
+ - type_name: Elf64_Rela
+ - type_name: Elf64_Shdr
+ - type_name: Elf64_Sword
+ - type_name: Elf64_Sxword
+ - type_name: Elf64_Sym
+ - type_name: Elf64_Verdaux
+ - type_name: Elf64_Verdef
+ - type_name: Elf64_Vernaux
+ - type_name: Elf64_Verneed
+ - type_name: Elf64_Versym
+ - type_name: Elf64_Word
+ - type_name: Elf64_Xword
+ - type_name: Elf64_auxv_t
+enums: []
+objects: []
+functions: []
diff --git a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
index ce42bd9cf8b02..19bf918783073 100644
--- a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
@@ -190,6 +190,10 @@ LLVM_LIBC_HEADERS = [
),
libc_header_info("nl_types"),
libc_header_info("poll"),
+ libc_header_info(
+ "llvm-libc-proxy/elf_proxy",
+ proxy = True,
+ ),
libc_header_info("pthread"),
libc_header_info("sched"),
libc_header_info("search"),
@@ -241,19 +245,12 @@ LLVM_LIBC_HEADERS = [
name = info.target_name,
hdr = info.staging_path,
other_srcs = info.other_srcs,
+ proxy = info.proxy,
yaml_template = info.yaml_template,
)
for info in LLVM_LIBC_HEADERS
]
-# needed for startup and VDSO. Doesn't get placed in /include so is handled separately.
-libc_generated_header(
- name = "hdr_elf_proxy_h",
- hdr = "staging/hdr/elf_proxy.h",
- proxy = True,
- yaml_template = "include/elf.yaml",
-)
-
# Static headers that need to be in staging/include
STATIC_HEADERS = glob(
["include/llvm-libc-types/**/*.h"],
@@ -617,9 +614,7 @@ libc_support_library(
libc_support_library(
name = "hdr_elf_proxy",
- hdrs = ["staging/hdr/elf_proxy.h"],
- includes = ["staging"],
- deps = [":hdr_elf_proxy_h"],
+ hdrs = ["hdr/elf_proxy.h"],
)
libc_support_library(
diff --git a/utils/bazel/llvm-project-overlay/libc/libc_build_rules.bzl b/utils/bazel/llvm-project-overlay/libc/libc_build_rules.bzl
index 9056f9e384b26..da454e84843e5 100644
--- a/utils/bazel/llvm-project-overlay/libc/libc_build_rules.bzl
+++ b/utils/bazel/llvm-project-overlay/libc/libc_build_rules.bzl
@@ -291,11 +291,13 @@ def libc_generated_header(name, hdr, yaml_template, other_srcs = [], proxy = Fal
def libc_header_info(
name,
has_def_template = False,
+ proxy = False,
other_srcs = []):
return struct(
target_name = "include_{}_h".format(name.replace("/", "_")),
staging_path = "staging/include/{}.h".format(name),
yaml_template = "include/{}.yaml".format(name),
+ proxy = proxy,
other_srcs = other_srcs + (["include/{}.h.def".format(name)] if has_def_template else []),
)
>From 3a32fe981c0fe446177d7e1191a58a0fc1cacbb7 Mon Sep 17 00:00:00 2001
From: Tom Stellard <tstellar at redhat.com>
Date: Fri, 31 Jul 2026 17:08:49 -0700
Subject: [PATCH 40/43] Fix matrix
---
.github/workflows/release-documentation.yml | 17 +++++++++--------
1 file changed, 9 insertions(+), 8 deletions(-)
diff --git a/.github/workflows/release-documentation.yml b/.github/workflows/release-documentation.yml
index ca4c7ab6312aa..9bd43a7e7384a 100644
--- a/.github/workflows/release-documentation.yml
+++ b/.github/workflows/release-documentation.yml
@@ -201,14 +201,15 @@ jobs:
contents: write # For man page uploads
id-token: write # For artifact attestations
attestations: write # For artifact attestations
- matrix:
- include:
- - artifact-id: ${{ needs.release-documentation.outputs.man-page-artifact-id }}
- attestation-name: release-man-page-attestation
- digest: ${{ needs.release-documentation.outputs.man-page-digest }}
- - artifact-id: ${{ needs.release-documentation.outputs.doxygen-artifact-id }}
- attestation-name: release-doxygen-attestation
- digest: ${{ needs.release-documentation.outputs.doxygen-digest }}
+ strategy:
+ matrix:
+ include:
+ - artifact-id: ${{ needs.release-documentation.outputs.man-page-artifact-id }}
+ attestation-name: release-man-page-attestation
+ digest: ${{ needs.release-documentation.outputs.man-page-digest }}
+ - artifact-id: ${{ needs.release-documentation.outputs.doxygen-artifact-id }}
+ attestation-name: release-doxygen-attestation
+ digest: ${{ needs.release-documentation.outputs.doxygen-digest }}
steps:
- name: Upload Man Page Artifacts
id: man-page-artifact-upload
>From 91186afbab45006d25b5c4f4599e9fcb5ecf9998 Mon Sep 17 00:00:00 2001
From: Tom Stellard <tstellar at redhat.com>
Date: Fri, 31 Jul 2026 20:44:31 -0700
Subject: [PATCH 41/43] Fix
---
.github/workflows/release-documentation.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/release-documentation.yml b/.github/workflows/release-documentation.yml
index 9bd43a7e7384a..271c276046165 100644
--- a/.github/workflows/release-documentation.yml
+++ b/.github/workflows/release-documentation.yml
@@ -112,7 +112,7 @@ jobs:
./llvm/utils/release/build-docs.sh \
$(test -n "$INPUTS_RELEASE_VERSION" && echo -release "$INPUTS_RELEASE_VERSION" || echo -srcdir llvm)
echo "man-page-tarball-name=$(basename $(find . -iname 'llvm_man_pages-*.tar.xz'))" >> "$GITHUB_OUTPUT"
- echo "doxygen-tarball-name=$(baename $(find . -iname '*doxygen*.tar.xz')) >> "$GITHUB_OUTPUT"
+ echo "doxygen-tarball-name=$(baename $(find . -iname '*doxygen*.tar.xz'))" >> "$GITHUB_OUTPUT"
- name: Generate sha256 digest for tarballs
>From 66da6d0507100376886748b07191a82abbdfb367 Mon Sep 17 00:00:00 2001
From: Tom Stellard <tstellar at redhat.com>
Date: Fri, 31 Jul 2026 21:07:04 -0700
Subject: [PATCH 42/43] Fixes
---
.github/workflows/release-documentation.yml | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/.github/workflows/release-documentation.yml b/.github/workflows/release-documentation.yml
index 271c276046165..153bba056dcd3 100644
--- a/.github/workflows/release-documentation.yml
+++ b/.github/workflows/release-documentation.yml
@@ -112,7 +112,7 @@ jobs:
./llvm/utils/release/build-docs.sh \
$(test -n "$INPUTS_RELEASE_VERSION" && echo -release "$INPUTS_RELEASE_VERSION" || echo -srcdir llvm)
echo "man-page-tarball-name=$(basename $(find . -iname 'llvm_man_pages-*.tar.xz'))" >> "$GITHUB_OUTPUT"
- echo "doxygen-tarball-name=$(baename $(find . -iname '*doxygen*.tar.xz'))" >> "$GITHUB_OUTPUT"
+ echo "doxygen-tarball-name=$(basename $(find . -iname '*doxygen*.tar.xz'))" >> "$GITHUB_OUTPUT"
- name: Generate sha256 digest for tarballs
@@ -120,7 +120,7 @@ jobs:
shell: bash
env:
MAN_PAGE_TARBALL_NAME: ${{ steps.build.outputs.man-page-tarball-name }}
- DOXYGEN_TARBALL_NAME: ${{ steps.build.outputs.man-page-tarball-name }}
+ DOXYGEN_TARBALL_NAME: ${{ steps.build.outputs.doxygen-tarball-name }}
run: |
echo "man-page-digest=$(cat "$MAN_PAGE_TARBALL_NAME" | sha256sum | cut -d ' ' -f 1)" >> "$GITHUB_OUTPUT"
echo "doxygen-digest=$(cat "$DOXYGEN_TARBALL_NAME" | sha256sum | cut -d ' ' -f 1)" >> "$GITHUB_OUTPUT"
@@ -217,7 +217,7 @@ jobs:
with:
release-version: ${{ inputs.release-version }}
artifact-id: ${{ matrix.artifact-id }}
- attestation-name: ${{ runner.os }}-${{ runner.arch }}-${{ matrix.attestation_name }}
+ attestation-name: ${{ runner.os }}-${{ runner.arch }}-${{ matrix.attestation-name }}
digest: ${{ matrix.digest }}
upload: ${{ inputs.upload }}
LLVM_TOKEN_GENERATOR_CLIENT_ID: ${{ secrets.LLVM_TOKEN_GENERATOR_CLIENT_ID }}
>From db7adbddd6d5555701ba7efd609744cd4589b268 Mon Sep 17 00:00:00 2001
From: Tom Stellard <tstellar at redhat.com>
Date: Fri, 31 Jul 2026 21:36:31 -0700
Subject: [PATCH 43/43] Debug
---
.github/workflows/release-documentation.yml | 1 +
1 file changed, 1 insertion(+)
diff --git a/.github/workflows/release-documentation.yml b/.github/workflows/release-documentation.yml
index 153bba056dcd3..2d550c536a528 100644
--- a/.github/workflows/release-documentation.yml
+++ b/.github/workflows/release-documentation.yml
@@ -111,6 +111,7 @@ jobs:
run: |
./llvm/utils/release/build-docs.sh \
$(test -n "$INPUTS_RELEASE_VERSION" && echo -release "$INPUTS_RELEASE_VERSION" || echo -srcdir llvm)
+ ls -ltr
echo "man-page-tarball-name=$(basename $(find . -iname 'llvm_man_pages-*.tar.xz'))" >> "$GITHUB_OUTPUT"
echo "doxygen-tarball-name=$(basename $(find . -iname '*doxygen*.tar.xz'))" >> "$GITHUB_OUTPUT"
More information about the llvm-branch-commits
mailing list