about summary refs log tree commit diff
path: root/compiler/rustc_codegen_gcc
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_codegen_gcc')
-rw-r--r--compiler/rustc_codegen_gcc/.github/workflows/ci.yml48
-rw-r--r--compiler/rustc_codegen_gcc/.github/workflows/failures.yml129
-rw-r--r--compiler/rustc_codegen_gcc/.github/workflows/gcc12.yml115
-rw-r--r--compiler/rustc_codegen_gcc/.github/workflows/m68k.yml139
-rw-r--r--compiler/rustc_codegen_gcc/.github/workflows/release.yml34
-rw-r--r--compiler/rustc_codegen_gcc/.github/workflows/stdarch.yml32
-rw-r--r--compiler/rustc_codegen_gcc/.gitignore1
-rw-r--r--compiler/rustc_codegen_gcc/.ignore10
-rw-r--r--compiler/rustc_codegen_gcc/Cargo.lock261
-rw-r--r--compiler/rustc_codegen_gcc/Cargo.toml7
-rw-r--r--compiler/rustc_codegen_gcc/Readme.md144
-rwxr-xr-xcompiler/rustc_codegen_gcc/build.sh67
-rw-r--r--compiler/rustc_codegen_gcc/build_sysroot/Cargo.toml2
-rwxr-xr-xcompiler/rustc_codegen_gcc/build_sysroot/build_sysroot.sh6
-rwxr-xr-xcompiler/rustc_codegen_gcc/build_sysroot/prepare_sysroot_src.sh39
-rw-r--r--compiler/rustc_codegen_gcc/build_system/Cargo.lock7
-rw-r--r--compiler/rustc_codegen_gcc/build_system/Cargo.toml8
-rw-r--r--compiler/rustc_codegen_gcc/build_system/src/build.rs248
-rw-r--r--compiler/rustc_codegen_gcc/build_system/src/config.rs149
-rw-r--r--compiler/rustc_codegen_gcc/build_system/src/main.rs67
-rw-r--r--compiler/rustc_codegen_gcc/build_system/src/prepare.rs255
-rw-r--r--compiler/rustc_codegen_gcc/build_system/src/rustc_info.rs12
-rw-r--r--compiler/rustc_codegen_gcc/build_system/src/test.rs15
-rw-r--r--compiler/rustc_codegen_gcc/build_system/src/utils.rs240
-rwxr-xr-xcompiler/rustc_codegen_gcc/cargo.sh2
-rw-r--r--compiler/rustc_codegen_gcc/config.sh77
-rw-r--r--compiler/rustc_codegen_gcc/cross_patches/0001-Disable-libstd-and-libtest-dylib.patch39
-rw-r--r--compiler/rustc_codegen_gcc/doc/add-attribute.md17
-rw-r--r--compiler/rustc_codegen_gcc/doc/gimple.md111
-rw-r--r--compiler/rustc_codegen_gcc/doc/sending-gcc-patch.md44
-rw-r--r--compiler/rustc_codegen_gcc/doc/tests.md5
-rw-r--r--compiler/rustc_codegen_gcc/example/alloc_example.rs3
-rw-r--r--compiler/rustc_codegen_gcc/example/alloc_system.rs21
-rw-r--r--compiler/rustc_codegen_gcc/example/arbitrary_self_types_pointers_and_wrappers.rs1
-rw-r--r--compiler/rustc_codegen_gcc/example/mini_core.rs11
-rw-r--r--compiler/rustc_codegen_gcc/example/mini_core_hello_world.rs8
-rw-r--r--compiler/rustc_codegen_gcc/example/mod_bench.rs3
-rw-r--r--compiler/rustc_codegen_gcc/example/std_example.rs17
-rw-r--r--compiler/rustc_codegen_gcc/failing-lto-tests.txt23
-rw-r--r--compiler/rustc_codegen_gcc/failing-non-lto-tests.txt11
-rw-r--r--compiler/rustc_codegen_gcc/failing-ui-tests.txt34
-rw-r--r--compiler/rustc_codegen_gcc/failing-ui-tests12.txt11
-rw-r--r--compiler/rustc_codegen_gcc/messages.ftl30
-rw-r--r--compiler/rustc_codegen_gcc/patches/0001-Add-stdarch-Cargo.toml-for-testing.patch19
-rw-r--r--compiler/rustc_codegen_gcc/patches/0001-Disable-examples.patch25
-rw-r--r--compiler/rustc_codegen_gcc/patches/libgccjit12/0001-core-Disable-portable-simd-test.patch32
-rwxr-xr-xcompiler/rustc_codegen_gcc/prepare.sh30
-rwxr-xr-xcompiler/rustc_codegen_gcc/prepare_build.sh5
-rw-r--r--compiler/rustc_codegen_gcc/rust-toolchain2
-rwxr-xr-xcompiler/rustc_codegen_gcc/rustup.sh2
-rw-r--r--compiler/rustc_codegen_gcc/src/abi.rs95
-rw-r--r--compiler/rustc_codegen_gcc/src/allocator.rs109
-rw-r--r--compiler/rustc_codegen_gcc/src/asm.rs4
-rw-r--r--compiler/rustc_codegen_gcc/src/attributes.rs105
-rw-r--r--compiler/rustc_codegen_gcc/src/back/lto.rs341
-rw-r--r--compiler/rustc_codegen_gcc/src/back/mod.rs1
-rw-r--r--compiler/rustc_codegen_gcc/src/back/write.rs102
-rw-r--r--compiler/rustc_codegen_gcc/src/base.rs76
-rw-r--r--compiler/rustc_codegen_gcc/src/builder.rs34
-rw-r--r--compiler/rustc_codegen_gcc/src/common.rs16
-rw-r--r--compiler/rustc_codegen_gcc/src/context.rs68
-rw-r--r--compiler/rustc_codegen_gcc/src/declare.rs57
-rw-r--r--compiler/rustc_codegen_gcc/src/errors.rs87
-rw-r--r--compiler/rustc_codegen_gcc/src/gcc_util.rs230
-rw-r--r--compiler/rustc_codegen_gcc/src/int.rs246
-rw-r--r--compiler/rustc_codegen_gcc/src/intrinsic/archs.rs1569
-rw-r--r--compiler/rustc_codegen_gcc/src/intrinsic/llvm.rs44
-rw-r--r--compiler/rustc_codegen_gcc/src/intrinsic/mod.rs151
-rw-r--r--compiler/rustc_codegen_gcc/src/lib.rs196
-rw-r--r--compiler/rustc_codegen_gcc/src/type_.rs14
-rw-r--r--compiler/rustc_codegen_gcc/src/type_of.rs28
-rwxr-xr-xcompiler/rustc_codegen_gcc/test.sh158
-rw-r--r--compiler/rustc_codegen_gcc/tests/lang_tests_common.rs70
-rw-r--r--compiler/rustc_codegen_gcc/tests/run/abort1.rs3
-rw-r--r--compiler/rustc_codegen_gcc/tests/run/abort2.rs3
-rw-r--r--compiler/rustc_codegen_gcc/tests/run/array.rs3
-rw-r--r--compiler/rustc_codegen_gcc/tests/run/asm.rs16
-rw-r--r--compiler/rustc_codegen_gcc/tests/run/assign.rs4
-rw-r--r--compiler/rustc_codegen_gcc/tests/run/closure.rs3
-rw-r--r--compiler/rustc_codegen_gcc/tests/run/condition.rs3
-rw-r--r--compiler/rustc_codegen_gcc/tests/run/empty_main.rs3
-rw-r--r--compiler/rustc_codegen_gcc/tests/run/exit.rs1
-rw-r--r--compiler/rustc_codegen_gcc/tests/run/exit_code.rs1
-rw-r--r--compiler/rustc_codegen_gcc/tests/run/fun_ptr.rs3
-rw-r--r--compiler/rustc_codegen_gcc/tests/run/gep.rs10
-rw-r--r--compiler/rustc_codegen_gcc/tests/run/int_overflow.rs138
-rw-r--r--compiler/rustc_codegen_gcc/tests/run/mut_ref.rs4
-rw-r--r--compiler/rustc_codegen_gcc/tests/run/operations.rs4
-rw-r--r--compiler/rustc_codegen_gcc/tests/run/ptr_cast.rs3
-rw-r--r--compiler/rustc_codegen_gcc/tests/run/return-tuple.rs1
-rw-r--r--compiler/rustc_codegen_gcc/tests/run/slice.rs3
-rw-r--r--compiler/rustc_codegen_gcc/tests/run/static.rs3
-rw-r--r--compiler/rustc_codegen_gcc/tests/run/structs.rs1
-rw-r--r--compiler/rustc_codegen_gcc/tests/run/tuple.rs1
-rw-r--r--compiler/rustc_codegen_gcc/tests/run/volatile.rs26
-rw-r--r--compiler/rustc_codegen_gcc/tools/generate_intrinsics.py8
-rwxr-xr-xcompiler/rustc_codegen_gcc/y.sh8
97 files changed, 5538 insertions, 1134 deletions
diff --git a/compiler/rustc_codegen_gcc/.github/workflows/ci.yml b/compiler/rustc_codegen_gcc/.github/workflows/ci.yml
index d2b7724a221..65e7a697ab0 100644
--- a/compiler/rustc_codegen_gcc/.github/workflows/ci.yml
+++ b/compiler/rustc_codegen_gcc/.github/workflows/ci.yml
@@ -19,9 +19,8 @@ jobs:
       fail-fast: false
       matrix:
         libgccjit_version:
-          - { gcc: "libgccjit.so", extra: "", env_extra: "", artifacts_branch: "master" }
-          - { gcc: "libgccjit_without_int128.so", extra: "", env_extra: "", artifacts_branch: "master-without-128bit-integers" }
-          - { gcc: "libgccjit12.so", extra: "--no-default-features", env_extra: "TEST_FLAGS='-Cpanic=abort -Zpanic-abort-tests'", artifacts_branch: "gcc12" }
+          - { gcc: "libgccjit.so", artifacts_branch: "master" }
+          - { gcc: "libgccjit_without_int128.so", artifacts_branch: "master-without-128bit-integers" }
         commands: [
           "--mini-tests",
           "--std-tests",
@@ -33,47 +32,30 @@ jobs:
           "--extended-regex-tests",
           "--test-successful-rustc --nb-parts 2 --current-part 0",
           "--test-successful-rustc --nb-parts 2 --current-part 1",
-          "--test-failing-rustc",
         ]
 
     steps:
     - uses: actions/checkout@v3
 
-    - uses: actions/checkout@v3
-      with:
-        repository: llvm/llvm-project
-        path: llvm
-
     - name: Install packages
       # `llvm-14-tools` is needed to install the `FileCheck` binary which is used for asm tests.
       run: sudo apt-get install ninja-build ripgrep llvm-14-tools
 
-    - name: Install libgccjit12
-      if: matrix.libgccjit_version.gcc == 'libgccjit12.so'
-      run: sudo apt-get install libgccjit-12-dev
-
     - name: Download artifact
-      if: matrix.libgccjit_version.gcc != 'libgccjit12.so'
       uses: dawidd6/action-download-artifact@v2
       with:
           workflow: main.yml
-          name: ${{ matrix.libgccjit_version.gcc }}
-          path: gcc-build
+          name: gcc-13
+          path: gcc-13
           repo: antoyo/gcc
           branch: ${{ matrix.libgccjit_version.artifacts_branch }}
           event: push
           search_artifacts: true # Because, instead, the action only check the last job ran and that won't work since we want multiple artifacts.
 
     - name: Setup path to libgccjit
-      if: matrix.libgccjit_version.gcc == 'libgccjit12.so'
-      run: echo /usr/lib/gcc/x86_64-linux-gnu/12 > gcc_path
-
-    - name: Setup path to libgccjit
-      if: matrix.libgccjit_version.gcc != 'libgccjit12.so'
       run: |
-          echo $(readlink -f gcc-build) > gcc_path
-          # NOTE: the filename is still libgccjit.so even when the artifact name is different.
-          ln gcc-build/libgccjit.so gcc-build/libgccjit.so.0
+          sudo dpkg --force-overwrite -i gcc-13/gcc-13.deb
+          echo /usr/lib/ > gcc_path
 
     - name: Set env
       run: |
@@ -81,9 +63,6 @@ jobs:
         echo "LD_LIBRARY_PATH=$(cat gcc_path)" >> $GITHUB_ENV
         echo "workspace="$GITHUB_WORKSPACE >> $GITHUB_ENV
 
-    - name: Set RUST_COMPILER_RT_ROOT
-      run: echo "RUST_COMPILER_RT_ROOT="${{ env.workspace }}/llvm/compiler-rt >> $GITHUB_ENV
-
     - name: Cache cargo installed crates
       uses: actions/cache@v3
       with:
@@ -119,16 +98,16 @@ jobs:
 
     - name: Build
       run: |
-        ./prepare_build.sh
-        ${{ matrix.libgccjit_version.env_extra }} ./build.sh ${{ matrix.libgccjit_version.extra }}
-        ${{ matrix.libgccjit_version.env_extra }} cargo test ${{ matrix.libgccjit_version.extra }}
+        ./y.sh prepare --only-libcore
+        ./y.sh build
+        cargo test
         ./clean_all.sh
 
     - name: Prepare dependencies
       run: |
         git config --global user.email "user@example.com"
         git config --global user.name "User"
-        ./prepare.sh
+        ./y.sh prepare
 
     # Compile is a separate step, as the actions-rs/cargo action supports error annotations
     - name: Compile
@@ -137,13 +116,12 @@ jobs:
         command: build
         args: --release
 
-    - name: Add more failing tests for GCC 12
-      if: ${{ matrix.libgccjit_version.gcc == 'libgccjit12.so' }}
-      run: cat failing-ui-tests12.txt >> failing-ui-tests.txt
+    - name: Add more failing tests because the sysroot is not compiled with LTO
+      run: cat failing-non-lto-tests.txt >> failing-ui-tests.txt
 
     - name: Run tests
       run: |
-        ${{ matrix.libgccjit_version.env_extra }} ./test.sh --release --clean --build-sysroot ${{ matrix.commands }} ${{ matrix.libgccjit_version.extra }}
+        ./test.sh --release --clean --build-sysroot ${{ matrix.commands }}
 
   duplicates:
     runs-on: ubuntu-latest
diff --git a/compiler/rustc_codegen_gcc/.github/workflows/failures.yml b/compiler/rustc_codegen_gcc/.github/workflows/failures.yml
new file mode 100644
index 00000000000..27864dcadd0
--- /dev/null
+++ b/compiler/rustc_codegen_gcc/.github/workflows/failures.yml
@@ -0,0 +1,129 @@
+# TODO: refactor to avoid duplication with the ci.yml file.
+name: Failures
+
+on:
+  - pull_request
+
+permissions:
+  contents: read
+
+env:
+  # Enable backtraces for easier debugging
+  RUST_BACKTRACE: 1
+
+jobs:
+  build:
+    runs-on: ubuntu-22.04
+
+    strategy:
+      fail-fast: false
+      matrix:
+        libgccjit_version:
+          - gcc: "libgccjit.so"
+            artifacts_branch: "master"
+          - gcc: "libgccjit_without_int128.so"
+            artifacts_branch: "master-without-128bit-integers"
+          - gcc: "libgccjit12.so"
+            artifacts_branch: "gcc12"
+            extra: "--no-default-features"
+            # FIXME(antoyo): we need to set GCC_EXEC_PREFIX so that the linker can find the linker plugin.
+            # Not sure why it's not found otherwise.
+            env_extra: "TEST_FLAGS='-Cpanic=abort -Zpanic-abort-tests' GCC_EXEC_PREFIX=/usr/lib/gcc/"
+
+    steps:
+    - uses: actions/checkout@v3
+
+    - name: Install packages
+      run: sudo apt-get install ninja-build ripgrep
+
+    - name: Install libgccjit12
+      if: matrix.libgccjit_version.gcc == 'libgccjit12.so'
+      run: sudo apt-get install libgccjit-12-dev
+
+    - name: Setup path to libgccjit
+      if: matrix.libgccjit_version.gcc == 'libgccjit12.so'
+      run: echo /usr/lib/gcc/x86_64-linux-gnu/12 > gcc_path
+
+    - name: Download artifact
+      if: matrix.libgccjit_version.gcc != 'libgccjit12.so'
+      uses: dawidd6/action-download-artifact@v2
+      with:
+          workflow: main.yml
+          name: gcc-13
+          path: gcc-13
+          repo: antoyo/gcc
+          branch: ${{ matrix.libgccjit_version.artifacts_branch }}
+          event: push
+          search_artifacts: true # Because, instead, the action only check the last job ran and that won't work since we want multiple artifacts.
+
+    - name: Setup path to libgccjit
+      if: matrix.libgccjit_version.gcc != 'libgccjit12.so'
+      run: |
+          sudo dpkg --force-overwrite -i gcc-13/gcc-13.deb
+          echo /usr/lib/ > gcc_path
+
+    - name: Set env
+      run: |
+        echo "LIBRARY_PATH=$(cat gcc_path)" >> $GITHUB_ENV
+        echo "LD_LIBRARY_PATH=$(cat gcc_path)" >> $GITHUB_ENV
+        echo "workspace="$GITHUB_WORKSPACE >> $GITHUB_ENV
+
+    - name: Cache cargo installed crates
+      uses: actions/cache@v3
+      with:
+        path: ~/.cargo/bin
+        key: cargo-installed-crates2-ubuntu-latest
+
+    - name: Cache cargo registry
+      uses: actions/cache@v3
+      with:
+        path: ~/.cargo/registry
+        key: ${{ runner.os }}-cargo-registry2-${{ hashFiles('**/Cargo.lock') }}
+
+    - name: Cache cargo index
+      uses: actions/cache@v3
+      with:
+        path: ~/.cargo/git
+        key: ${{ runner.os }}-cargo-index-${{ hashFiles('**/Cargo.lock') }}
+
+    - name: Cache cargo target dir
+      uses: actions/cache@v3
+      with:
+        path: target
+        key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('rust-toolchain') }}
+
+    #- name: Cache rust repository
+      #uses: actions/cache@v3
+      #id: cache-rust-repository
+      #with:
+        #path: rust
+        #key: ${{ runner.os }}-packages-${{ hashFiles('rust/.git/HEAD') }}
+
+    - name: Git config
+      run: |
+        git config --global user.email "user@example.com"
+        git config --global user.name "User"
+
+    - name: Prepare dependencies
+      if: matrix.libgccjit_version.gcc == 'libgccjit12.so'
+      run: ./y.sh prepare --libgccjit12-patches
+
+    - name: Prepare dependencies
+      if: matrix.libgccjit_version.gcc != 'libgccjit12.so'
+      run: ./y.sh prepare
+
+    # Compile is a separate step, as the actions-rs/cargo action supports error annotations
+    - name: Compile
+      uses: actions-rs/cargo@v1.0.3
+      with:
+        command: build
+        args: --release
+
+    - name: Add more failing tests because the sysroot is not compiled with LTO
+      run: cat failing-non-lto-tests.txt >> failing-ui-tests.txt
+
+    - name: Run tests
+      id: tests
+      run: |
+        ${{ matrix.libgccjit_version.env_extra }} ./test.sh --release --clean --build-sysroot --test-failing-rustc ${{ matrix.libgccjit_version.extra }} | tee output_log
+        rg --text "test result" output_log >> $GITHUB_STEP_SUMMARY
diff --git a/compiler/rustc_codegen_gcc/.github/workflows/gcc12.yml b/compiler/rustc_codegen_gcc/.github/workflows/gcc12.yml
new file mode 100644
index 00000000000..a0d363cf1fb
--- /dev/null
+++ b/compiler/rustc_codegen_gcc/.github/workflows/gcc12.yml
@@ -0,0 +1,115 @@
+name: CI libgccjit 12
+
+on:
+  - push
+  - pull_request
+
+permissions:
+  contents: read
+
+env:
+  # Enable backtraces for easier debugging
+  RUST_BACKTRACE: 1
+  TEST_FLAGS: "-Cpanic=abort -Zpanic-abort-tests"
+  # FIXME(antoyo): we need to set GCC_EXEC_PREFIX so that the linker can find the linker plugin.
+  # Not sure why it's not found otherwise.
+  GCC_EXEC_PREFIX: /usr/lib/gcc/
+
+jobs:
+  build:
+    runs-on: ubuntu-22.04
+
+    strategy:
+      fail-fast: false
+      matrix:
+        commands: [
+          "--mini-tests",
+          "--std-tests",
+          # FIXME: re-enable asm tests when GCC can emit in the right syntax.
+          # "--asm-tests",
+          "--test-libcore",
+          "--extended-rand-tests",
+          "--extended-regex-example-tests",
+          "--extended-regex-tests",
+          "--test-successful-rustc --nb-parts 2 --current-part 0",
+          "--test-successful-rustc --nb-parts 2 --current-part 1",
+        ]
+
+    steps:
+    - uses: actions/checkout@v3
+
+    - name: Install packages
+      # `llvm-14-tools` is needed to install the `FileCheck` binary which is used for asm tests.
+      run: sudo apt-get install ninja-build ripgrep llvm-14-tools libgccjit-12-dev
+
+    - name: Setup path to libgccjit
+      run: echo /usr/lib/gcc/x86_64-linux-gnu/12 > gcc_path
+
+    - name: Set env
+      run: |
+        echo "LIBRARY_PATH=$(cat gcc_path)" >> $GITHUB_ENV
+        echo "LD_LIBRARY_PATH=$(cat gcc_path)" >> $GITHUB_ENV
+        echo "workspace="$GITHUB_WORKSPACE >> $GITHUB_ENV
+
+    - name: Cache cargo installed crates
+      uses: actions/cache@v3
+      with:
+        path: ~/.cargo/bin
+        key: cargo-installed-crates2-ubuntu-latest
+
+    - name: Cache cargo registry
+      uses: actions/cache@v3
+      with:
+        path: ~/.cargo/registry
+        key: ${{ runner.os }}-cargo-registry2-${{ hashFiles('**/Cargo.lock') }}
+
+    - name: Cache cargo index
+      uses: actions/cache@v3
+      with:
+        path: ~/.cargo/git
+        key: ${{ runner.os }}-cargo-index-${{ hashFiles('**/Cargo.lock') }}
+
+    - name: Cache cargo target dir
+      uses: actions/cache@v3
+      with:
+        path: target
+        key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('rust-toolchain') }}
+
+    #- name: Cache rust repository
+      ## We only clone the rust repository for rustc tests
+      #if: ${{ contains(matrix.commands, 'rustc') }}
+      #uses: actions/cache@v3
+      #id: cache-rust-repository
+      #with:
+        #path: rust
+        #key: ${{ runner.os }}-packages-${{ hashFiles('rust/.git/HEAD') }}
+
+    - name: Build
+      run: |
+        ./y.sh prepare --only-libcore --libgccjit12-patches
+        ./y.sh build --no-default-features --sysroot-panic-abort
+        cargo test --no-default-features
+        ./clean_all.sh
+
+    - name: Prepare dependencies
+      run: |
+        git config --global user.email "user@example.com"
+        git config --global user.name "User"
+        ./y.sh prepare --libgccjit12-patches
+
+    # Compile is a separate step, as the actions-rs/cargo action supports error annotations
+    - name: Compile
+      uses: actions-rs/cargo@v1.0.3
+      with:
+        command: build
+        args: --release
+
+    - name: Add more failing tests for GCC 12
+      run: cat failing-ui-tests12.txt >> failing-ui-tests.txt
+
+    - name: Add more failing tests because the sysroot is not compiled with LTO
+      run: cat failing-non-lto-tests.txt >> failing-ui-tests.txt
+
+    - name: Run tests
+      run: |
+        ./test.sh --release --clean --build-sysroot ${{ matrix.commands }} --no-default-features
diff --git a/compiler/rustc_codegen_gcc/.github/workflows/m68k.yml b/compiler/rustc_codegen_gcc/.github/workflows/m68k.yml
new file mode 100644
index 00000000000..55ee0a21214
--- /dev/null
+++ b/compiler/rustc_codegen_gcc/.github/workflows/m68k.yml
@@ -0,0 +1,139 @@
+# TODO: check if qemu-user-static-binfmt is needed (perhaps to run some tests since it probably calls exec).
+
+name: m68k CI
+
+on:
+  - push
+  - pull_request
+
+permissions:
+  contents: read
+
+env:
+  # Enable backtraces for easier debugging
+  RUST_BACKTRACE: 1
+  # TODO: remove when confish.sh is removed.
+  OVERWRITE_TARGET_TRIPLE: m68k-unknown-linux-gnu
+
+jobs:
+  build:
+    runs-on: ubuntu-22.04
+
+    strategy:
+      fail-fast: false
+      matrix:
+        commands: [
+          "--mini-tests",
+          "--std-tests",
+          # TODO(antoyo): fix those on m68k.
+          #"--test-libcore",
+          #"--extended-rand-tests",
+          #"--extended-regex-example-tests",
+          #"--extended-regex-tests",
+          #"--test-successful-rustc --nb-parts 2 --current-part 0",
+          #"--test-successful-rustc --nb-parts 2 --current-part 1",
+          #"--test-failing-rustc",
+        ]
+
+    steps:
+    - name: Install packages
+      run: |
+        sudo apt-get update
+        sudo apt-get install qemu qemu-user-static
+
+    - uses: actions/checkout@v3
+
+    - name: Download GCC artifact
+      uses: dawidd6/action-download-artifact@v2
+      with:
+          workflow: m68k.yml
+          name: gcc-m68k-13
+          repo: cross-cg-gcc-tools/cross-gcc
+          branch: master
+          event: push
+
+    - name: Download VM artifact
+      uses: dawidd6/action-download-artifact@v2
+      with:
+          workflow: m68k.yml
+          name: debian-m68k
+          repo: cross-cg-gcc-tools/vms
+          branch: master
+          event: push
+
+    - name: Setup path to libgccjit
+      run: |
+          sudo dpkg -i gcc-m68k-13.deb
+          echo /usr/lib/ > gcc_path
+
+    - name: Set env
+      run: |
+        echo "LIBRARY_PATH=$(cat gcc_path)" >> $GITHUB_ENV
+        echo "LD_LIBRARY_PATH=$(cat gcc_path)" >> $GITHUB_ENV
+        echo "workspace="$GITHUB_WORKSPACE >> $GITHUB_ENV
+
+    - name: Cache cargo installed crates
+      uses: actions/cache@v3
+      with:
+        path: ~/.cargo/bin
+        key: cargo-installed-crates2-ubuntu-latest
+
+    #- name: Cache cargo registry
+      #uses: actions/cache@v3
+      #with:
+        #path: ~/.cargo/registry
+        #key: ${{ runner.os }}-cargo-registry2-${{ hashFiles('**/Cargo.lock') }}
+
+    #- name: Cache cargo index
+      #uses: actions/cache@v3
+      #with:
+        #path: ~/.cargo/git
+        #key: ${{ runner.os }}-cargo-index-${{ hashFiles('**/Cargo.lock') }}
+
+    - name: Cache cargo target dir
+      uses: actions/cache@v3
+      with:
+        path: target
+        key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('rust-toolchain') }}
+
+    #- name: Cache rust repository
+      ## We only clone the rust repository for rustc tests
+      #if: ${{ contains(matrix.commands, 'rustc') }}
+      #uses: actions/cache@v3
+      #id: cache-rust-repository
+      #with:
+        #path: rust
+        #key: ${{ runner.os }}-packages-${{ hashFiles('rust/.git/HEAD') }}
+
+    - name: Prepare VM
+      run: |
+        mkdir vm
+        sudo mount debian-m68k.img vm
+        sudo cp $(which qemu-m68k-static) vm/usr/bin/
+
+    - name: Build
+      run: |
+        ./y.sh prepare --only-libcore --cross
+        ./y.sh build --target-triple m68k-unknown-linux-gnu
+        CG_GCC_TEST_TARGET=m68k-unknown-linux-gnu cargo test
+        ./clean_all.sh
+
+    - name: Prepare dependencies
+      run: |
+        git config --global user.email "user@example.com"
+        git config --global user.name "User"
+        ./y.sh prepare --cross
+
+    # Compile is a separate step, as the actions-rs/cargo action supports error annotations
+    - name: Compile
+      uses: actions-rs/cargo@v1.0.3
+      with:
+        command: build
+        args: --release
+
+    - name: Add more failing tests because the sysroot is not compiled with LTO
+      run: cat failing-non-lto-tests.txt >> failing-ui-tests.txt
+
+    - name: Run tests
+      run: |
+        ./test.sh --release --clean --build-sysroot ${{ matrix.commands }}
diff --git a/compiler/rustc_codegen_gcc/.github/workflows/release.yml b/compiler/rustc_codegen_gcc/.github/workflows/release.yml
index c4e99469bc2..ae1134177a7 100644
--- a/compiler/rustc_codegen_gcc/.github/workflows/release.yml
+++ b/compiler/rustc_codegen_gcc/.github/workflows/release.yml
@@ -18,8 +18,6 @@ jobs:
     strategy:
       fail-fast: false
       matrix:
-        libgccjit_version:
-          - { gcc: "libgccjit.so", artifacts_branch: "master" }
         commands: [
           "--test-successful-rustc --nb-parts 2 --current-part 0",
           "--test-successful-rustc --nb-parts 2 --current-part 1",
@@ -28,11 +26,6 @@ jobs:
     steps:
     - uses: actions/checkout@v3
 
-    - uses: actions/checkout@v3
-      with:
-        repository: llvm/llvm-project
-        path: llvm
-
     - name: Install packages
       run: sudo apt-get install ninja-build ripgrep
 
@@ -40,18 +33,17 @@ jobs:
       uses: dawidd6/action-download-artifact@v2
       with:
           workflow: main.yml
-          name: ${{ matrix.libgccjit_version.gcc }}
-          path: gcc-build
+          name: gcc-13
+          path: gcc-13
           repo: antoyo/gcc
-          branch: ${{ matrix.libgccjit_version.artifacts_branch }}
+          branch: "master"
           event: push
           search_artifacts: true # Because, instead, the action only check the last job ran and that won't work since we want multiple artifacts.
 
     - name: Setup path to libgccjit
       run: |
-          echo $(readlink -f gcc-build) > gcc_path
-          # NOTE: the filename is still libgccjit.so even when the artifact name is different.
-          ln gcc-build/libgccjit.so gcc-build/libgccjit.so.0
+          sudo dpkg --force-overwrite -i gcc-13/gcc-13.deb
+          echo /usr/lib/ > gcc_path
 
     - name: Set env
       run: |
@@ -59,9 +51,6 @@ jobs:
         echo "LD_LIBRARY_PATH=$(cat gcc_path)" >> $GITHUB_ENV
         echo "workspace="$GITHUB_WORKSPACE >> $GITHUB_ENV
 
-    - name: Set RUST_COMPILER_RT_ROOT
-      run: echo "RUST_COMPILER_RT_ROOT="${{ env.workspace }}/llvm/compiler-rt >> $GITHUB_ENV
-
     - name: Cache cargo installed crates
       uses: actions/cache@v3
       with:
@@ -88,8 +77,8 @@ jobs:
 
     - name: Build
       run: |
-        ./prepare_build.sh
-        ./build.sh --release --release-sysroot
+        ./y.sh prepare --only-libcore
+        EMBED_LTO_BITCODE=1 ./y.sh build --release --release-sysroot
         cargo test
         ./clean_all.sh
 
@@ -97,7 +86,9 @@ jobs:
       run: |
         git config --global user.email "user@example.com"
         git config --global user.name "User"
-        ./prepare.sh
+        ./y.sh prepare
+        # FIXME(antoyo): we cannot enable LTO for stdarch tests currently because of some failing LTO tests using proc-macros.
+        echo -n 'lto = "fat"' >> build_sysroot/Cargo.toml
 
     # Compile is a separate step, as the actions-rs/cargo action supports error annotations
     - name: Compile
@@ -106,6 +97,9 @@ jobs:
         command: build
         args: --release
 
+    - name: Add more failing tests because of undefined symbol errors (FIXME)
+      run: cat failing-lto-tests.txt >> failing-ui-tests.txt
+
     - name: Run tests
       run: |
-        ./test.sh --release --clean --release-sysroot --build-sysroot ${{ matrix.commands }}
+        EMBED_LTO_BITCODE=1 ./test.sh --release --clean --release-sysroot --build-sysroot ${{ matrix.commands }}
diff --git a/compiler/rustc_codegen_gcc/.github/workflows/stdarch.yml b/compiler/rustc_codegen_gcc/.github/workflows/stdarch.yml
index 556c6444833..28ac3cb6542 100644
--- a/compiler/rustc_codegen_gcc/.github/workflows/stdarch.yml
+++ b/compiler/rustc_codegen_gcc/.github/workflows/stdarch.yml
@@ -18,8 +18,6 @@ jobs:
     strategy:
       fail-fast: false
       matrix:
-        libgccjit_version:
-          - { gcc: "libgccjit.so", artifacts_branch: "master" }
         cargo_runner: [
           "sde -future -rtm_mode full --",
           "",
@@ -28,11 +26,6 @@ jobs:
     steps:
     - uses: actions/checkout@v3
 
-    - uses: actions/checkout@v3
-      with:
-        repository: llvm/llvm-project
-        path: llvm
-
     - name: Install packages
       run: sudo apt-get install ninja-build ripgrep
 
@@ -54,18 +47,17 @@ jobs:
       uses: dawidd6/action-download-artifact@v2
       with:
           workflow: main.yml
-          name: ${{ matrix.libgccjit_version.gcc }}
-          path: gcc-build
+          name: gcc-13
+          path: gcc-13
           repo: antoyo/gcc
-          branch: ${{ matrix.libgccjit_version.artifacts_branch }}
+          branch: "master"
           event: push
           search_artifacts: true # Because, instead, the action only check the last job ran and that won't work since we want multiple artifacts.
 
     - name: Setup path to libgccjit
       run: |
-          echo $(readlink -f gcc-build) > gcc_path
-          # NOTE: the filename is still libgccjit.so even when the artifact name is different.
-          ln gcc-build/libgccjit.so gcc-build/libgccjit.so.0
+          sudo dpkg --force-overwrite -i gcc-13/gcc-13.deb
+          echo /usr/lib/ > gcc_path
 
     - name: Set env
       run: |
@@ -73,9 +65,6 @@ jobs:
         echo "LD_LIBRARY_PATH=$(cat gcc_path)" >> $GITHUB_ENV
         echo "workspace="$GITHUB_WORKSPACE >> $GITHUB_ENV
 
-    - name: Set RUST_COMPILER_RT_ROOT
-      run: echo "RUST_COMPILER_RT_ROOT="${{ env.workspace }}/llvm/compiler-rt >> $GITHUB_ENV
-
     - name: Cache cargo installed crates
       uses: actions/cache@v3
       with:
@@ -102,8 +91,8 @@ jobs:
 
     - name: Build
       run: |
-        ./prepare_build.sh
-        ./build.sh --release --release-sysroot
+        ./y.sh prepare --only-libcore
+        ./y.sh build --release --release-sysroot
         cargo test
 
     - name: Clean
@@ -115,7 +104,7 @@ jobs:
       run: |
         git config --global user.email "user@example.com"
         git config --global user.name "User"
-        ./prepare.sh
+        ./y.sh prepare
 
     # Compile is a separate step, as the actions-rs/cargo action supports error annotations
     - name: Compile
@@ -133,10 +122,11 @@ jobs:
       if: ${{ !matrix.cargo_runner }}
       run: |
         cd build_sysroot/sysroot_src/library/stdarch/
-        CHANNEL=release TARGET=x86_64-unknown-linux-gnu ../../../../cargo.sh test
+        CHANNEL=release TARGET=x86_64-unknown-linux-gnu CG_RUSTFLAGS="-Ainternal_features" ../../../../cargo.sh test
 
     - name: Run stdarch tests
       if: ${{ matrix.cargo_runner }}
       run: |
         cd build_sysroot/sysroot_src/library/stdarch/
-        STDARCH_TEST_EVERYTHING=1 CHANNEL=release CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_RUNNER="${{ matrix.cargo_runner }}" TARGET=x86_64-unknown-linux-gnu ../../../../cargo.sh test -- --skip rtm --skip tbm --skip sse4a
+        # FIXME: these tests fail when the sysroot is compiled with LTO because of a missing symbol in proc-macro.
+        STDARCH_TEST_EVERYTHING=1 CHANNEL=release CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_RUNNER="${{ matrix.cargo_runner }}" TARGET=x86_64-unknown-linux-gnu CG_RUSTFLAGS="-Ainternal_features" ../../../../cargo.sh test -- --skip rtm --skip tbm --skip sse4a
diff --git a/compiler/rustc_codegen_gcc/.gitignore b/compiler/rustc_codegen_gcc/.gitignore
index c5ed7de200c..b44d1aa78c2 100644
--- a/compiler/rustc_codegen_gcc/.gitignore
+++ b/compiler/rustc_codegen_gcc/.gitignore
@@ -25,3 +25,4 @@ tools/llvmint
 tools/llvmint-2
 # The `llvm` folder is generated by the `tools/generate_intrinsics.py` script to update intrinsics.
 llvm
+build_system/target
diff --git a/compiler/rustc_codegen_gcc/.ignore b/compiler/rustc_codegen_gcc/.ignore
new file mode 100644
index 00000000000..d8d189e5c7c
--- /dev/null
+++ b/compiler/rustc_codegen_gcc/.ignore
@@ -0,0 +1,10 @@
+!/build_sysroot/sysroot_src
+!/simple-raytracer
+!/regex
+!/rand
+!/test-backend
+!/gcc_path
+!/benchmarks
+!*gimple*
+!*asm*
+!.github
diff --git a/compiler/rustc_codegen_gcc/Cargo.lock b/compiler/rustc_codegen_gcc/Cargo.lock
index 1c8754bf675..b8e2e5d8080 100644
--- a/compiler/rustc_codegen_gcc/Cargo.lock
+++ b/compiler/rustc_codegen_gcc/Cargo.lock
@@ -4,9 +4,9 @@ version = 3
 
 [[package]]
 name = "aho-corasick"
-version = "0.7.18"
+version = "1.0.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f"
+checksum = "43f6cb1bf222025340178f382c426f13757b2960e89779dfcb319c32542a5a41"
 dependencies = [
  "memchr",
 ]
@@ -18,12 +18,51 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
 
 [[package]]
+name = "bitflags"
+version = "2.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635"
+
+[[package]]
+name = "cc"
+version = "1.0.79"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"
+
+[[package]]
 name = "cfg-if"
 version = "1.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
 
 [[package]]
+name = "errno"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a"
+dependencies = [
+ "errno-dragonfly",
+ "libc",
+ "windows-sys",
+]
+
+[[package]]
+name = "errno-dragonfly"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf"
+dependencies = [
+ "cc",
+ "libc",
+]
+
+[[package]]
+name = "fastrand"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6999dc1837253364c2ebb0704ba97994bd874e8f195d665c50b7548f6ea92764"
+
+[[package]]
 name = "fm"
 version = "0.1.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -35,7 +74,7 @@ dependencies = [
 [[package]]
 name = "gccjit"
 version = "1.0.0"
-source = "git+https://github.com/antoyo/gccjit.rs#d6e52626cfc6f487094a5d5ac66302baf3439984"
+source = "git+https://github.com/antoyo/gccjit.rs#c52a218f5529321285b4489e5562a00e5428e033"
 dependencies = [
  "gccjit_sys",
 ]
@@ -43,7 +82,7 @@ dependencies = [
 [[package]]
 name = "gccjit_sys"
 version = "0.0.1"
-source = "git+https://github.com/antoyo/gccjit.rs#d6e52626cfc6f487094a5d5ac66302baf3439984"
+source = "git+https://github.com/antoyo/gccjit.rs#c52a218f5529321285b4489e5562a00e5428e033"
 dependencies = [
  "libc",
 ]
@@ -58,24 +97,10 @@ dependencies = [
 ]
 
 [[package]]
-name = "getrandom"
-version = "0.2.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753"
-dependencies = [
- "cfg-if",
- "libc",
- "wasi",
-]
-
-[[package]]
 name = "hermit-abi"
-version = "0.1.19"
+version = "0.3.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
-dependencies = [
- "libc",
-]
+checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286"
 
 [[package]]
 name = "lang_tester"
@@ -95,86 +120,55 @@ dependencies = [
 
 [[package]]
 name = "libc"
-version = "0.2.112"
+version = "0.2.147"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1b03d17f364a3a042d5e5d46b053bbbf82c92c9430c592dd4c064dc6ee997125"
+checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3"
 
 [[package]]
-name = "memchr"
-version = "2.4.1"
+name = "linux-raw-sys"
+version = "0.4.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a"
+checksum = "57bcfdad1b858c2db7c38303a6d2ad4dfaf5eb53dfeb0910128b2c26d6158503"
 
 [[package]]
-name = "num_cpus"
-version = "1.13.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3"
-dependencies = [
- "hermit-abi",
- "libc",
-]
-
-[[package]]
-name = "ppv-lite86"
-version = "0.2.15"
+name = "memchr"
+version = "2.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ed0cfbc8191465bed66e1718596ee0b0b35d5ee1f41c5df2189d0fe8bde535ba"
+checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
 
 [[package]]
-name = "rand"
-version = "0.8.4"
+name = "num_cpus"
+version = "1.16.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8"
+checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43"
 dependencies = [
+ "hermit-abi",
  "libc",
- "rand_chacha",
- "rand_core",
- "rand_hc",
-]
-
-[[package]]
-name = "rand_chacha"
-version = "0.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
-dependencies = [
- "ppv-lite86",
- "rand_core",
-]
-
-[[package]]
-name = "rand_core"
-version = "0.6.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7"
-dependencies = [
- "getrandom",
 ]
 
 [[package]]
-name = "rand_hc"
-version = "0.3.1"
+name = "object"
+version = "0.30.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7"
+checksum = "03b4680b86d9cfafba8fc491dc9b6df26b68cf40e9e6cd73909194759a63c385"
 dependencies = [
- "rand_core",
+ "memchr",
 ]
 
 [[package]]
 name = "redox_syscall"
-version = "0.2.10"
+version = "0.3.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff"
+checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29"
 dependencies = [
- "bitflags",
+ "bitflags 1.3.2",
 ]
 
 [[package]]
 name = "regex"
-version = "1.5.4"
+version = "1.8.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461"
+checksum = "d0ab3ca65655bb1e41f2a8c8cd662eb4fb035e67c3f78da1d61dffe89d07300f"
 dependencies = [
  "aho-corasick",
  "memchr",
@@ -183,18 +177,9 @@ dependencies = [
 
 [[package]]
 name = "regex-syntax"
-version = "0.6.25"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b"
-
-[[package]]
-name = "remove_dir_all"
-version = "0.5.3"
+version = "0.7.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7"
-dependencies = [
- "winapi",
-]
+checksum = "436b050e76ed2903236f032a59761c1eb99e1b0aead2c257922771dab1fc8c78"
 
 [[package]]
 name = "rustc_codegen_gcc"
@@ -202,11 +187,25 @@ version = "0.1.0"
 dependencies = [
  "gccjit",
  "lang_tester",
+ "object",
  "smallvec",
  "tempfile",
 ]
 
 [[package]]
+name = "rustix"
+version = "0.38.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "19ed4fa021d81c8392ce04db050a3da9a60299050b7ae1cf482d862b54a7218f"
+dependencies = [
+ "bitflags 2.4.0",
+ "errno",
+ "libc",
+ "linux-raw-sys",
+ "windows-sys",
+]
+
+[[package]]
 name = "same-file"
 version = "1.0.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -223,23 +222,22 @@ checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0"
 
 [[package]]
 name = "tempfile"
-version = "3.2.0"
+version = "3.7.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22"
+checksum = "dc02fddf48964c42031a0b3fe0428320ecf3a73c401040fc0096f97794310651"
 dependencies = [
  "cfg-if",
- "libc",
- "rand",
+ "fastrand",
  "redox_syscall",
- "remove_dir_all",
- "winapi",
+ "rustix",
+ "windows-sys",
 ]
 
 [[package]]
 name = "termcolor"
-version = "1.1.2"
+version = "1.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4"
+checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6"
 dependencies = [
  "winapi-util",
 ]
@@ -255,9 +253,9 @@ dependencies = [
 
 [[package]]
 name = "unicode-width"
-version = "0.1.9"
+version = "0.1.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973"
+checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b"
 
 [[package]]
 name = "wait-timeout"
@@ -270,22 +268,15 @@ dependencies = [
 
 [[package]]
 name = "walkdir"
-version = "2.3.2"
+version = "2.3.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56"
+checksum = "36df944cda56c7d8d8b7496af378e6b16de9284591917d307c9b4d313c44e698"
 dependencies = [
  "same-file",
- "winapi",
  "winapi-util",
 ]
 
 [[package]]
-name = "wasi"
-version = "0.10.2+wasi-snapshot-preview1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"
-
-[[package]]
 name = "winapi"
 version = "0.3.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -315,3 +306,69 @@ name = "winapi-x86_64-pc-windows-gnu"
 version = "0.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
+
+[[package]]
+name = "windows-sys"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
+dependencies = [
+ "windows-targets",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.48.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f"
+dependencies = [
+ "windows_aarch64_gnullvm",
+ "windows_aarch64_msvc",
+ "windows_i686_gnu",
+ "windows_i686_msvc",
+ "windows_x86_64_gnu",
+ "windows_x86_64_gnullvm",
+ "windows_x86_64_msvc",
+]
+
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc"
+
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3"
+
+[[package]]
+name = "windows_i686_gnu"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241"
+
+[[package]]
+name = "windows_i686_msvc"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00"
+
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a"
diff --git a/compiler/rustc_codegen_gcc/Cargo.toml b/compiler/rustc_codegen_gcc/Cargo.toml
index 81066d9ce1f..b0b3aeecdbd 100644
--- a/compiler/rustc_codegen_gcc/Cargo.toml
+++ b/compiler/rustc_codegen_gcc/Cargo.toml
@@ -18,7 +18,6 @@ path = "tests/lang_tests_release.rs"
 harness = false
 
 [features]
-default = ["master"]
 master = ["gccjit/master"]
 
 [dependencies]
@@ -27,7 +26,13 @@ gccjit = { git = "https://github.com/antoyo/gccjit.rs" }
 # Local copy.
 #gccjit = { path = "../gccjit.rs" }
 
+object = { version = "0.30.1", default-features = false, features = [
+    "std",
+    "read",
+] }
 smallvec = { version = "1.6.1", features = ["union", "may_dangle"] }
+# TODO(antoyo): make tempfile optional.
+tempfile = "3.7.1"
 
 [dev-dependencies]
 lang_tester = "0.3.9"
diff --git a/compiler/rustc_codegen_gcc/Readme.md b/compiler/rustc_codegen_gcc/Readme.md
index a93637d9038..95fc6374c09 100644
--- a/compiler/rustc_codegen_gcc/Readme.md
+++ b/compiler/rustc_codegen_gcc/Readme.md
@@ -1,6 +1,7 @@
 # WIP libgccjit codegen backend for rust
 
 [![Chat on IRC](https://img.shields.io/badge/irc.libera.chat-%23rustc__codegen__gcc-blue.svg)](https://web.libera.chat/#rustc_codegen_gcc)
+[![Chat on Matrix](https://img.shields.io/badge/matrix.org-%23rustc__codegen__gcc-blue.svg)](https://matrix.to/#/#rustc_codegen_gcc:matrix.org)
 
 This is a GCC codegen for rustc, which means it can be loaded by the existing rustc frontend, but benefits from GCC: more architectures are supported and GCC's optimizations are used.
 
@@ -14,9 +15,7 @@ A secondary goal is to check if using the gcc backend will provide any run-time
 ## Building
 
 **This requires a patched libgccjit in order to work.
-The patches in [this repository](https://github.com/antoyo/libgccjit-patches) need to be applied.
-(Those patches should work when applied on master, but in case it doesn't work, they are known to work when applied on 079c23cfe079f203d5df83fea8e92a60c7d7e878.)
-You can also use my [fork of gcc](https://github.com/antoyo/gcc) which already includes these patches.**
+You need to use my [fork of gcc](https://github.com/antoyo/gcc) which already includes these patches.**
 
 To build it (most of these instructions come from [here](https://gcc.gnu.org/onlinedocs/jit/internals/index.html), so don't hesitate to take a look there if you encounter an issue):
 
@@ -56,18 +55,11 @@ $ make check-jit RUNTESTFLAGS="-v -v -v jit.exp=jit.dg/test-asm.cc"
 $ dirname $(readlink -f `find . -name libgccjit.so`) > gcc_path
 ```
 
-You also need to set RUST_COMPILER_RT_ROOT:
-
-```bash
-$ git clone https://github.com/llvm/llvm-project llvm --depth 1 --single-branch
-$ export RUST_COMPILER_RT_ROOT="$PWD/llvm/compiler-rt"
-```
-
 Then you can run commands like this:
 
 ```bash
-$ ./prepare.sh # download and patch sysroot src and install hyperfine for benchmarking
-$ LIBRARY_PATH=$(cat gcc_path) LD_LIBRARY_PATH=$(cat gcc_path) ./build.sh --release
+$ ./y.sh prepare # download and patch sysroot src and install hyperfine for benchmarking
+$ LIBRARY_PATH=$(cat gcc_path) LD_LIBRARY_PATH=$(cat gcc_path) ./y.sh build --release
 ```
 
 To run the tests:
@@ -78,22 +70,37 @@ $ ./test.sh --release
 
 ## Usage
 
-`$cg_gccjit_dir` is the directory you cloned this repo into in the following instructions.
+`$CG_GCCJIT_DIR` is the directory you cloned this repo into in the following instructions:
+
+```bash
+export CG_GCCJIT_DIR=[the full path to rustc_codegen_gcc]
+```
 
 ### Cargo
 
 ```bash
-$ CHANNEL="release" $cg_gccjit_dir/cargo.sh run
+$ CHANNEL="release" $CG_GCCJIT_DIR/cargo.sh run
 ```
 
 If you compiled cg_gccjit in debug mode (aka you didn't pass `--release` to `./test.sh`) you should use `CHANNEL="debug"` instead or omit `CHANNEL="release"` completely.
 
+### LTO
+
+To use LTO, you need to set the variable `FAT_LTO=1` and `EMBED_LTO_BITCODE=1` in addition to setting `lto = "fat"` in the `Cargo.toml`.
+Don't set `FAT_LTO` when compiling the sysroot, though: only set `EMBED_LTO_BITCODE=1`.
+
+Failing to set `EMBED_LTO_BITCODE` will give you the following error:
+
+```
+error: failed to copy bitcode to object file: No such file or directory (os error 2)
+```
+
 ### Rustc
 
 > You should prefer using the Cargo method.
 
 ```bash
-$ rustc +$(cat $cg_gccjit_dir/rust-toolchain) -Cpanic=abort -Zcodegen-backend=$cg_gccjit_dir/target/release/librustc_codegen_gcc.so --sysroot $cg_gccjit_dir/build_sysroot/sysroot my_crate.rs
+$ LIBRARY_PATH=$(cat gcc_path) LD_LIBRARY_PATH=$(cat gcc_path) rustc +$(cat $CG_GCCJIT_DIR/rust-toolchain | grep 'channel' | cut -d '=' -f 2 | sed 's/"//g' | sed 's/ //g') -Cpanic=abort -Zcodegen-backend=$CG_GCCJIT_DIR/target/release/librustc_codegen_gcc.so --sysroot $CG_GCCJIT_DIR/build_sysroot/sysroot my_crate.rs
 ```
 
 ## Env vars
@@ -105,8 +112,18 @@ $ rustc +$(cat $cg_gccjit_dir/rust-toolchain) -Cpanic=abort -Zcodegen-backend=$c
     object files when their content should have been changed by a change to cg_gccjit.</dd>
     <dt>CG_GCCJIT_DISPLAY_CG_TIME</dt>
     <dd>Display the time it took to perform codegen for a crate</dd>
+    <dt>CG_RUSTFLAGS</dt>
+    <dd>Send additional flags to rustc. Can be used to build the sysroot without unwinding by setting `CG_RUSTFLAGS=-Cpanic=abort`.</dd>
+    <dt>CG_GCCJIT_DUMP_TO_FILE</dt>
+    <dd>Dump a C-like representation to /tmp/gccjit_dumps and enable debug info in order to debug this C-like representation.</dd>
 </dl>
 
+## Licensing
+
+While this crate is licensed under a dual Apache/MIT license, it links to `libgccjit` which is under the GPLv3+ and thus, the resulting toolchain (rustc + GCC codegen) will need to be released under the GPL license.
+
+However, programs compiled with `rustc_codegen_gcc` do not need to be released under a GPL license.
+
 ## Debugging
 
 Sometimes, libgccjit will crash and output an error like this:
@@ -182,6 +199,61 @@ set substitute-path /usr/src/debug/gcc /path/to/gcc-repo/gcc
 
 TODO(antoyo): but that's not what I remember I was doing.
 
+### `failed to build archive` error
+
+When you get this error:
+
+```
+error: failed to build archive: failed to open object file: No such file or directory (os error 2)
+```
+
+That can be caused by the fact that you try to compile with `lto = "fat"`, but you didn't compile the sysroot with LTO.
+(Not sure if that's the reason since I cannot reproduce anymore. Maybe it happened when forgetting setting `FAT_LTO`.)
+
+### ld: cannot find crtbegin.o
+
+When compiling an executable with libgccijt, if setting the `*LIBRARY_PATH` variables to the install directory, you will get the following errors:
+
+```
+ld: cannot find crtbegin.o: No such file or directory
+ld: cannot find -lgcc: No such file or directory
+ld: cannot find -lgcc: No such file or directory
+libgccjit.so: error: error invoking gcc driver
+```
+
+To fix this, set the variables to `gcc-build/build/gcc`.
+
+### How to debug GCC LTO
+
+Run do the command with `-v -save-temps` and then extract the `lto1` line from the output and run that under the debugger.
+
+### How to send arguments to the GCC linker
+
+```
+CG_RUSTFLAGS="-Clink-args=-save-temps -v" ../cargo.sh build
+```
+
+### How to see the personality functions in the asm dump
+
+```
+CG_RUSTFLAGS="-Clink-arg=-save-temps -v -Clink-arg=-dA" ../cargo.sh build
+```
+
+### How to see the LLVM IR for a sysroot crate
+
+```
+cargo build -v --target x86_64-unknown-linux-gnu -Zbuild-std
+# Take the command from the output and add --emit=llvm-ir
+```
+
+### To prevent the linker from unmangling symbols
+
+Run with:
+
+```
+COLLECT_NO_DEMANGLE=1
+```
+
 ### How to use a custom-build rustc
 
  * Build the stage2 compiler (`rustup toolchain link debug-current build/x86_64-unknown-linux-gnu/stage2`).
@@ -215,6 +287,16 @@ git checkout sync_branch_name
 git merge master
 ```
 
+To send the changes to the rust repo:
+
+```bash
+cd ../rust
+git pull origin master
+git checkout -b subtree-update_cg_gcc_YYYY-MM-DD
+PATH="$HOME/bin:$PATH" ~/bin/git-subtree pull --prefix=compiler/rustc_codegen_gcc/ https://github.com/rust-lang/rustc_codegen_gcc.git master
+git push
+```
+
 TODO: write a script that does the above.
 
 https://rust-lang.zulipchat.com/#narrow/stream/301329-t-devtools/topic/subtree.20madness/near/258877725
@@ -223,20 +305,34 @@ https://rust-lang.zulipchat.com/#narrow/stream/301329-t-devtools/topic/subtree.2
 
 `rustc` needs to be built without `jemalloc` so that `mem-trace` can overload `malloc` since `jemalloc` is linked statically, so a `LD_PRELOAD`-ed library won't a chance to intercept the calls to `malloc`.
 
+### How to generate GIMPLE
+
+If you need to check what gccjit is generating (GIMPLE), then take a look at how to
+generate it in [gimple.md](./doc/gimple.md).
+
 ### How to build a cross-compiling libgccjit
 
 #### Building libgccjit
 
- * Follow these instructions: https://preshing.com/20141119/how-to-build-a-gcc-cross-compiler/ with the following changes:
- * Configure gcc with `../gcc/configure --enable-host-shared --disable-multilib --enable-languages=c,jit,c++ --disable-bootstrap --enable-checking=release --prefix=/opt/m68k-gcc/ --target=m68k-linux --without-headers`.
- * Some shells, like fish, don't define the environment variable `$MACHTYPE`.
- * Add `CFLAGS="-Wno-error=attributes -g -O2"` at the end of the configure command for building glibc (`CFLAGS="-Wno-error=attributes -Wno-error=array-parameter -Wno-error=stringop-overflow -Wno-error=array-bounds -g -O2"` for glibc 2.31, which is useful for Debian).
+ * Follow the instructions on [this repo](https://github.com/cross-cg-gcc-tools/cross-gcc).
 
 #### Configuring rustc_codegen_gcc
 
- * Set `TARGET_TRIPLE="m68k-unknown-linux-gnu"` in config.sh.
- * Since rustc doesn't support this architecture yet, set it back to `TARGET_TRIPLE="mips-unknown-linux-gnu"` (or another target having the same attributes). Alternatively, create a [target specification file](https://book.avr-rust.com/005.1-the-target-specification-json-file.html) (note that the `arch` specified in this file must be supported by the rust compiler).
- * Set `linker='-Clinker=m68k-linux-gcc'`.
+ * Run `./y.sh prepare --cross` so that the sysroot is patched for the cross-compiling case.
  * Set the path to the cross-compiling libgccjit in `gcc_path`.
- * Comment the line: `context.add_command_line_option("-masm=intel");` in src/base.rs.
- * (might not be necessary) Disable the compilation of libstd.so (and possibly libcore.so?).
+ * Make sure you have the linker for your target (for instance `m68k-unknown-linux-gnu-gcc`) in your `$PATH`. Currently, the linker name is hardcoded as being `$TARGET-gcc`. Specify the target when building the sysroot: `./y.sh build --target-triple m68k-unknown-linux-gnu`.
+ * Build your project by specifying the target: `OVERWRITE_TARGET_TRIPLE=m68k-unknown-linux-gnu ../cargo.sh build --target m68k-unknown-linux-gnu`.
+
+If the target is not yet supported by the Rust compiler, create a [target specification file](https://docs.rust-embedded.org/embedonomicon/custom-target.html) (note that the `arch` specified in this file must be supported by the rust compiler).
+Then, you can use it the following way:
+
+ * Add the target specification file using `--target` as an **absolute** path to build the sysroot: `./y.sh build --target-triple m68k-unknown-linux-gnu --target $(pwd)/m68k-unknown-linux-gnu.json`
+ * Build your project by specifying the target specification file: `OVERWRITE_TARGET_TRIPLE=m68k-unknown-linux-gnu ../cargo.sh build --target path/to/m68k-unknown-linux-gnu.json`.
+
+If you get the following error:
+
+```
+/usr/bin/ld: unrecognised emulation mode: m68kelf
+```
+
+Make sure you set `gcc_path` to the install directory.
diff --git a/compiler/rustc_codegen_gcc/build.sh b/compiler/rustc_codegen_gcc/build.sh
deleted file mode 100755
index ba0d0d04948..00000000000
--- a/compiler/rustc_codegen_gcc/build.sh
+++ /dev/null
@@ -1,67 +0,0 @@
-#!/usr/bin/env bash
-
-#set -x
-set -e
-
-codegen_channel=debug
-sysroot_channel=debug
-
-flags=
-
-while [[ $# -gt 0 ]]; do
-    case $1 in
-        --release)
-            codegen_channel=release
-            shift
-            ;;
-        --release-sysroot)
-            sysroot_channel=release
-            shift
-            ;;
-        --no-default-features)
-            flags="$flags --no-default-features"
-            shift
-            ;;
-        --features)
-            shift
-            flags="$flags --features $1"
-            shift
-            ;;
-        *)
-            echo "Unknown option $1"
-            exit 1
-            ;;
-    esac
-done
-
-if [ -f ./gcc_path ]; then
-    export GCC_PATH=$(cat gcc_path)
-else
-    echo 'Please put the path to your custom build of libgccjit in the file `gcc_path`, see Readme.md for details'
-    exit 1
-fi
-
-export LD_LIBRARY_PATH="$GCC_PATH"
-export LIBRARY_PATH="$GCC_PATH"
-
-if [[ "$codegen_channel" == "release" ]]; then
-    export CHANNEL='release'
-    CARGO_INCREMENTAL=1 cargo rustc --release $flags
-else
-    echo $LD_LIBRARY_PATH
-    export CHANNEL='debug'
-    cargo rustc $flags
-fi
-
-source config.sh
-
-rm -r target/out || true
-mkdir -p target/out/gccjit
-
-echo "[BUILD] sysroot"
-if [[ "$sysroot_channel" == "release" ]]; then
-    time ./build_sysroot/build_sysroot.sh --release
-else
-    time ./build_sysroot/build_sysroot.sh
-fi
-
diff --git a/compiler/rustc_codegen_gcc/build_sysroot/Cargo.toml b/compiler/rustc_codegen_gcc/build_sysroot/Cargo.toml
index a84f86a8218..e5658273c97 100644
--- a/compiler/rustc_codegen_gcc/build_sysroot/Cargo.toml
+++ b/compiler/rustc_codegen_gcc/build_sysroot/Cargo.toml
@@ -2,6 +2,7 @@
 authors = ["bjorn3 <bjorn3@users.noreply.github.com>"]
 name = "sysroot"
 version = "0.0.0"
+resolver = "2"
 
 [dependencies]
 core = { path = "./sysroot_src/library/core" }
@@ -18,3 +19,4 @@ rustc-std-workspace-std = { path = "./sysroot_src/library/rustc-std-workspace-st
 
 [profile.release]
 debug = true
+#lto = "fat" # TODO(antoyo): re-enable when the failing LTO tests regarding proc-macros are fixed.
diff --git a/compiler/rustc_codegen_gcc/build_sysroot/build_sysroot.sh b/compiler/rustc_codegen_gcc/build_sysroot/build_sysroot.sh
index 9d692d599f6..116fd36e7a7 100755
--- a/compiler/rustc_codegen_gcc/build_sysroot/build_sysroot.sh
+++ b/compiler/rustc_codegen_gcc/build_sysroot/build_sysroot.sh
@@ -5,9 +5,9 @@
 set -e
 cd $(dirname "$0")
 
-pushd ../ >/dev/null
+pushd ../
 source ./config.sh
-popd >/dev/null
+popd
 
 # Cleanup for previous run
 #     v Clean target dir except for build scripts and incremental cache
@@ -22,7 +22,7 @@ if [[ "$1" == "--release" ]]; then
     RUSTFLAGS="$RUSTFLAGS -Zmir-opt-level=3" cargo build --target $TARGET_TRIPLE --release
 else
     sysroot_channel='debug'
-    cargo build --target $TARGET_TRIPLE --features compiler_builtins/c
+    cargo build --target $TARGET_TRIPLE
 fi
 
 # Copy files to sysroot
diff --git a/compiler/rustc_codegen_gcc/build_sysroot/prepare_sysroot_src.sh b/compiler/rustc_codegen_gcc/build_sysroot/prepare_sysroot_src.sh
deleted file mode 100755
index 71b3876bac2..00000000000
--- a/compiler/rustc_codegen_gcc/build_sysroot/prepare_sysroot_src.sh
+++ /dev/null
@@ -1,39 +0,0 @@
-#!/usr/bin/env bash
-set -e
-cd $(dirname "$0")
-
-SRC_DIR=$(dirname $(rustup which rustc))"/../lib/rustlib/src/rust/"
-DST_DIR="sysroot_src"
-
-if [ ! -e $SRC_DIR ]; then
-    echo "Please install rust-src component"
-    exit 1
-fi
-
-rm -rf $DST_DIR
-mkdir -p $DST_DIR/library
-cp -r $SRC_DIR/library $DST_DIR/
-
-pushd $DST_DIR
-echo "[GIT] init"
-git init
-echo "[GIT] add"
-git add .
-echo "[GIT] commit"
-
-# This is needed on systems where nothing is configured.
-# git really needs something here, or it will fail.
-# Even using --author is not enough.
-git config user.email || git config user.email "none@example.com"
-git config user.name || git config user.name "None"
-
-git commit -m "Initial commit" -q
-for file in $(ls ../../patches/ | grep -v patcha); do
-    echo "[GIT] apply" $file
-    git apply ../../patches/$file
-    git add -A
-    git commit --no-gpg-sign -m "Patch $file"
-done
-popd
-
-echo "Successfully prepared libcore for building"
diff --git a/compiler/rustc_codegen_gcc/build_system/Cargo.lock b/compiler/rustc_codegen_gcc/build_system/Cargo.lock
new file mode 100644
index 00000000000..86268e19160
--- /dev/null
+++ b/compiler/rustc_codegen_gcc/build_system/Cargo.lock
@@ -0,0 +1,7 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "y"
+version = "0.1.0"
diff --git a/compiler/rustc_codegen_gcc/build_system/Cargo.toml b/compiler/rustc_codegen_gcc/build_system/Cargo.toml
new file mode 100644
index 00000000000..f36709ea036
--- /dev/null
+++ b/compiler/rustc_codegen_gcc/build_system/Cargo.toml
@@ -0,0 +1,8 @@
+[package]
+name = "y"
+version = "0.1.0"
+edition = "2021"
+
+[[bin]]
+name = "y"
+path = "src/main.rs"
diff --git a/compiler/rustc_codegen_gcc/build_system/src/build.rs b/compiler/rustc_codegen_gcc/build_system/src/build.rs
new file mode 100644
index 00000000000..eaca7a987d6
--- /dev/null
+++ b/compiler/rustc_codegen_gcc/build_system/src/build.rs
@@ -0,0 +1,248 @@
+use crate::config::{set_config, ConfigInfo};
+use crate::utils::{
+    get_gcc_path, run_command, run_command_with_output_and_env, walk_dir,
+};
+use std::collections::HashMap;
+use std::ffi::OsStr;
+use std::fs;
+use std::path::Path;
+
+#[derive(Default)]
+struct BuildArg {
+    codegen_release_channel: bool,
+    sysroot_release_channel: bool,
+    sysroot_panic_abort: bool,
+    flags: Vec<String>,
+    gcc_path: String,
+}
+
+impl BuildArg {
+    fn new() -> Result<Option<Self>, String> {
+        let gcc_path = get_gcc_path()?;
+        let mut build_arg = Self {
+            gcc_path,
+            ..Default::default()
+        };
+        // We skip binary name and the `build` command.
+        let mut args = std::env::args().skip(2);
+
+        while let Some(arg) = args.next() {
+            match arg.as_str() {
+                "--release" => build_arg.codegen_release_channel = true,
+                "--release-sysroot" => build_arg.sysroot_release_channel = true,
+                "--no-default-features" => {
+                    build_arg.flags.push("--no-default-features".to_string());
+                }
+                "--sysroot-panic-abort" => {
+                    build_arg.sysroot_panic_abort = true;
+                },
+                "--features" => {
+                    if let Some(arg) = args.next() {
+                        build_arg.flags.push("--features".to_string());
+                        build_arg.flags.push(arg.as_str().into());
+                    } else {
+                        return Err(
+                            "Expected a value after `--features`, found nothing".to_string()
+                        );
+                    }
+                }
+                "--help" => {
+                    Self::usage();
+                    return Ok(None);
+                }
+                "--target-triple" => {
+                    if args.next().is_some() {
+                        // Handled in config.rs.
+                    } else {
+                        return Err(
+                            "Expected a value after `--target-triple`, found nothing".to_string()
+                        );
+                    }
+                }
+                "--target" => {
+                    if args.next().is_some() {
+                        // Handled in config.rs.
+                    } else {
+                        return Err(
+                            "Expected a value after `--target`, found nothing".to_string()
+                        );
+                    }
+                }
+                arg => return Err(format!("Unknown argument `{}`", arg)),
+            }
+        }
+        Ok(Some(build_arg))
+    }
+
+    fn usage() {
+        println!(
+            r#"
+`build` command help:
+
+    --release              : Build codegen in release mode
+    --release-sysroot      : Build sysroot in release mode
+    --sysroot-panic-abort  : Build the sysroot without unwinding support.
+    --no-default-features  : Add `--no-default-features` flag
+    --features [arg]       : Add a new feature [arg]
+    --target-triple [arg]  : Set the target triple to [arg]
+    --help                 : Show this help
+"#
+        )
+    }
+}
+
+fn build_sysroot(
+    env: &mut HashMap<String, String>,
+    args: &BuildArg,
+    config: &ConfigInfo,
+) -> Result<(), String> {
+    std::env::set_current_dir("build_sysroot")
+        .map_err(|error| format!("Failed to go to `build_sysroot` directory: {:?}", error))?;
+    // Cleanup for previous run
+    // Clean target dir except for build scripts and incremental cache
+    let _ = walk_dir(
+        "target",
+        |dir: &Path| {
+            for top in &["debug", "release"] {
+                let _ = fs::remove_dir_all(dir.join(top).join("build"));
+                let _ = fs::remove_dir_all(dir.join(top).join("deps"));
+                let _ = fs::remove_dir_all(dir.join(top).join("examples"));
+                let _ = fs::remove_dir_all(dir.join(top).join("native"));
+
+                let _ = walk_dir(
+                    dir.join(top),
+                    |sub_dir: &Path| {
+                        if sub_dir
+                            .file_name()
+                            .map(|filename| filename.to_str().unwrap().starts_with("libsysroot"))
+                            .unwrap_or(false)
+                        {
+                            let _ = fs::remove_dir_all(sub_dir);
+                        }
+                        Ok(())
+                    },
+                    |file: &Path| {
+                        if file
+                            .file_name()
+                            .map(|filename| filename.to_str().unwrap().starts_with("libsysroot"))
+                            .unwrap_or(false)
+                        {
+                            let _ = fs::remove_file(file);
+                        }
+                        Ok(())
+                    },
+                );
+            }
+            Ok(())
+        },
+        |_| Ok(()),
+    );
+
+    let _ = fs::remove_file("Cargo.lock");
+    let _ = fs::remove_file("test_target/Cargo.lock");
+    let _ = fs::remove_dir_all("sysroot");
+
+    // Builds libs
+    let mut rustflags = env
+        .get("RUSTFLAGS")
+        .cloned()
+        .unwrap_or_default();
+    if args.sysroot_panic_abort {
+        rustflags.push_str(" -Cpanic=abort -Zpanic-abort-tests");
+    }
+    env.insert(
+        "RUSTFLAGS".to_string(),
+        format!("{} -Zmir-opt-level=3", rustflags),
+    );
+    let channel = if args.sysroot_release_channel {
+        run_command_with_output_and_env(
+            &[
+                &"cargo",
+                &"build",
+                &"--target",
+                &config.target,
+                &"--release",
+            ],
+            None,
+            Some(&env),
+        )?;
+        "release"
+    } else {
+        run_command_with_output_and_env(
+            &[
+                &"cargo",
+                &"build",
+                &"--target",
+                &config.target,
+            ],
+            None,
+            Some(env),
+        )?;
+        "debug"
+    };
+
+    // Copy files to sysroot
+    let sysroot_path = format!("sysroot/lib/rustlib/{}/lib/", config.target_triple);
+    fs::create_dir_all(&sysroot_path)
+        .map_err(|error| format!("Failed to create directory `{}`: {:?}", sysroot_path, error))?;
+    let copier = |dir_to_copy: &Path| {
+        run_command(&[&"cp", &"-r", &dir_to_copy, &sysroot_path], None).map(|_| ())
+    };
+    walk_dir(
+        &format!("target/{}/{}/deps", config.target_triple, channel),
+        copier,
+        copier,
+    )?;
+
+    Ok(())
+}
+
+fn build_codegen(args: &BuildArg) -> Result<(), String> {
+    let mut env = HashMap::new();
+
+    env.insert("LD_LIBRARY_PATH".to_string(), args.gcc_path.clone());
+    env.insert("LIBRARY_PATH".to_string(), args.gcc_path.clone());
+
+    let mut command: Vec<&dyn AsRef<OsStr>> = vec![&"cargo", &"rustc"];
+    if args.codegen_release_channel {
+        command.push(&"--release");
+        env.insert("CHANNEL".to_string(), "release".to_string());
+        env.insert("CARGO_INCREMENTAL".to_string(), "1".to_string());
+    } else {
+        env.insert("CHANNEL".to_string(), "debug".to_string());
+    }
+    let flags = args.flags.iter().map(|s| s.as_str()).collect::<Vec<_>>();
+    for flag in &flags {
+        command.push(flag);
+    }
+    run_command_with_output_and_env(&command, None, Some(&env))?;
+
+    let config = set_config(&mut env, &[], Some(&args.gcc_path))?;
+
+    // We voluntarily ignore the error.
+    let _ = fs::remove_dir_all("target/out");
+    let gccjit_target = "target/out/gccjit";
+    fs::create_dir_all(gccjit_target).map_err(|error| {
+        format!(
+            "Failed to create directory `{}`: {:?}",
+            gccjit_target, error
+        )
+    })?;
+
+    println!("[BUILD] sysroot");
+    build_sysroot(
+        &mut env,
+        args,
+        &config,
+    )?;
+    Ok(())
+}
+
+pub fn run() -> Result<(), String> {
+    let args = match BuildArg::new()? {
+        Some(args) => args,
+        None => return Ok(()),
+    };
+    build_codegen(&args)?;
+    Ok(())
+}
diff --git a/compiler/rustc_codegen_gcc/build_system/src/config.rs b/compiler/rustc_codegen_gcc/build_system/src/config.rs
new file mode 100644
index 00000000000..64d9bd73e01
--- /dev/null
+++ b/compiler/rustc_codegen_gcc/build_system/src/config.rs
@@ -0,0 +1,149 @@
+use crate::utils::{get_gcc_path, get_os_name, get_rustc_host_triple};
+use std::collections::HashMap;
+use std::env as std_env;
+
+pub struct ConfigInfo {
+    pub target: String,
+    pub target_triple: String,
+    pub rustc_command: Vec<String>,
+}
+
+// Returns the beginning for the command line of rustc.
+pub fn set_config(
+    env: &mut HashMap<String, String>,
+    test_flags: &[String],
+    gcc_path: Option<&str>,
+) -> Result<ConfigInfo, String> {
+    env.insert("CARGO_INCREMENTAL".to_string(), "0".to_string());
+
+    let gcc_path = match gcc_path {
+        Some(path) => path.to_string(),
+        None => get_gcc_path()?,
+    };
+    env.insert("GCC_PATH".to_string(), gcc_path.clone());
+
+    let os_name = get_os_name()?;
+    let dylib_ext = match os_name.as_str() {
+        "Linux" => "so",
+        "Darwin" => "dylib",
+        os => return Err(format!("unsupported OS `{}`", os)),
+    };
+    let host_triple = get_rustc_host_triple()?;
+    let mut linker = None;
+    let mut target_triple = host_triple.clone();
+    let mut target = target_triple.clone();
+
+    // We skip binary name and the command.
+    let mut args = std::env::args().skip(2);
+
+    let mut set_target_triple = false;
+    let mut set_target = false;
+    while let Some(arg) = args.next() {
+        match arg.as_str() {
+            "--target-triple" => {
+                if let Some(arg) = args.next() {
+                    target_triple = arg;
+                    set_target_triple = true;
+                } else {
+                    return Err(
+                        "Expected a value after `--target-triple`, found nothing".to_string()
+                    );
+                }
+            },
+            "--target" => {
+                if let Some(arg) = args.next() {
+                    target = arg;
+                    set_target = true;
+                } else {
+                    return Err(
+                        "Expected a value after `--target`, found nothing".to_string()
+                    );
+                }
+            },
+            _ => (),
+        }
+    }
+
+    if set_target_triple && !set_target {
+        target = target_triple.clone();
+    }
+
+    if host_triple != target_triple {
+        linker = Some(format!("-Clinker={}-gcc", target_triple));
+    }
+    let current_dir =
+        std_env::current_dir().map_err(|error| format!("`current_dir` failed: {:?}", error))?;
+    let channel = if let Some(channel) = env.get("CHANNEL") {
+        channel.as_str()
+    } else {
+        "debug"
+    };
+    let cg_backend_path = current_dir
+        .join("target")
+        .join(channel)
+        .join(&format!("librustc_codegen_gcc.{}", dylib_ext));
+    let sysroot_path = current_dir.join("build_sysroot/sysroot");
+    let mut rustflags = Vec::new();
+    if let Some(cg_rustflags) = env.get("CG_RUSTFLAGS") {
+        rustflags.push(cg_rustflags.clone());
+    }
+    if let Some(linker) = linker {
+        rustflags.push(linker.to_string());
+    }
+    rustflags.extend_from_slice(&[
+        "-Csymbol-mangling-version=v0".to_string(),
+        "-Cdebuginfo=2".to_string(),
+        format!("-Zcodegen-backend={}", cg_backend_path.display()),
+        "--sysroot".to_string(),
+        sysroot_path.display().to_string(),
+    ]);
+
+    // Since we don't support ThinLTO, disable LTO completely when not trying to do LTO.
+    // TODO(antoyo): remove when we can handle ThinLTO.
+    if !env.contains_key(&"FAT_LTO".to_string()) {
+        rustflags.push("-Clto=off".to_string());
+    }
+    rustflags.extend_from_slice(test_flags);
+    // FIXME(antoyo): remove once the atomic shim is gone
+    if os_name == "Darwin" {
+        rustflags.extend_from_slice(&[
+            "-Clink-arg=-undefined".to_string(),
+            "-Clink-arg=dynamic_lookup".to_string(),
+        ]);
+    }
+    env.insert("RUSTFLAGS".to_string(), rustflags.join(" "));
+    // display metadata load errors
+    env.insert("RUSTC_LOG".to_string(), "warn".to_string());
+
+    let sysroot = current_dir.join(&format!(
+        "build_sysroot/sysroot/lib/rustlib/{}/lib",
+        target_triple
+    ));
+    let ld_library_path = format!(
+        "{target}:{sysroot}:{gcc_path}",
+        target = current_dir.join("target/out").display(),
+        sysroot = sysroot.display(),
+    );
+    env.insert("LD_LIBRARY_PATH".to_string(), ld_library_path.clone());
+    env.insert("DYLD_LIBRARY_PATH".to_string(), ld_library_path);
+
+    // NOTE: To avoid the -fno-inline errors, use /opt/gcc/bin/gcc instead of cc.
+    // To do so, add a symlink for cc to /opt/gcc/bin/gcc in our PATH.
+    // Another option would be to add the following Rust flag: -Clinker=/opt/gcc/bin/gcc
+    let path = std::env::var("PATH").unwrap_or_default();
+    env.insert("PATH".to_string(), format!("/opt/gcc/bin:{}", path));
+
+    let mut rustc_command = vec!["rustc".to_string()];
+    rustc_command.extend_from_slice(&rustflags);
+    rustc_command.extend_from_slice(&[
+        "-L".to_string(),
+        "crate=target/out".to_string(),
+        "--out-dir".to_string(),
+        "target/out".to_string(),
+    ]);
+    Ok(ConfigInfo {
+        target,
+        target_triple,
+        rustc_command,
+    })
+}
diff --git a/compiler/rustc_codegen_gcc/build_system/src/main.rs b/compiler/rustc_codegen_gcc/build_system/src/main.rs
new file mode 100644
index 00000000000..bff82b6e3e5
--- /dev/null
+++ b/compiler/rustc_codegen_gcc/build_system/src/main.rs
@@ -0,0 +1,67 @@
+use std::env;
+use std::process;
+
+mod build;
+mod config;
+mod prepare;
+mod rustc_info;
+mod test;
+mod utils;
+
+macro_rules! arg_error {
+    ($($err:tt)*) => {{
+        eprintln!($($err)*);
+        eprintln!();
+        usage();
+        std::process::exit(1);
+    }};
+}
+
+fn usage() {
+    println!(
+        "\
+Available commands for build_system:
+
+    prepare  : Run prepare command
+    build    : Run build command
+    test     : Run test command
+    --help   : Show this message"
+    );
+}
+
+pub enum Command {
+    Prepare,
+    Build,
+    Test,
+}
+
+fn main() {
+    if env::var("RUST_BACKTRACE").is_err() {
+        env::set_var("RUST_BACKTRACE", "1");
+    }
+
+    let command = match env::args().nth(1).as_deref() {
+        Some("prepare") => Command::Prepare,
+        Some("build") => Command::Build,
+        Some("test") => Command::Test,
+        Some("--help") => {
+            usage();
+            process::exit(0);
+        }
+        Some(flag) if flag.starts_with('-') => arg_error!("Expected command found flag {}", flag),
+        Some(command) => arg_error!("Unknown command {}", command),
+        None => {
+            usage();
+            process::exit(0);
+        }
+    };
+
+    if let Err(e) = match command {
+        Command::Prepare => prepare::run(),
+        Command::Build => build::run(),
+        Command::Test => test::run(),
+    } {
+        eprintln!("Command failed to run: {e:?}");
+        process::exit(1);
+    }
+}
diff --git a/compiler/rustc_codegen_gcc/build_system/src/prepare.rs b/compiler/rustc_codegen_gcc/build_system/src/prepare.rs
new file mode 100644
index 00000000000..6c7c8586834
--- /dev/null
+++ b/compiler/rustc_codegen_gcc/build_system/src/prepare.rs
@@ -0,0 +1,255 @@
+use crate::rustc_info::get_rustc_path;
+use crate::utils::{cargo_install, git_clone, run_command, run_command_with_output, walk_dir};
+
+use std::fs;
+use std::path::Path;
+
+fn prepare_libcore(sysroot_path: &Path, libgccjit12_patches: bool, cross_compile: bool) -> Result<(), String> {
+    let rustc_path = match get_rustc_path() {
+        Some(path) => path,
+        None => return Err("`rustc` path not found".to_string()),
+    };
+
+    let parent = match rustc_path.parent() {
+        Some(path) => path,
+        None => return Err(format!("No parent for `{}`", rustc_path.display())),
+    };
+
+    let rustlib_dir = parent
+        .join("../lib/rustlib/src/rust")
+        .canonicalize()
+        .map_err(|error| format!("Failed to canonicalize path: {:?}", error))?;
+    if !rustlib_dir.is_dir() {
+        return Err("Please install `rust-src` component".to_string());
+    }
+
+    let sysroot_dir = sysroot_path.join("sysroot_src");
+    if sysroot_dir.is_dir() {
+        if let Err(error) = fs::remove_dir_all(&sysroot_dir) {
+            return Err(format!(
+                "Failed to remove `{}`: {:?}",
+                sysroot_dir.display(),
+                error,
+            ));
+        }
+    }
+
+    let sysroot_library_dir = sysroot_dir.join("library");
+    fs::create_dir_all(&sysroot_library_dir).map_err(|error| {
+        format!(
+            "Failed to create folder `{}`: {:?}",
+            sysroot_library_dir.display(),
+            error,
+        )
+    })?;
+
+    run_command(
+        &[&"cp", &"-r", &rustlib_dir.join("library"), &sysroot_dir],
+        None,
+    )?;
+
+    println!("[GIT] init (cwd): `{}`", sysroot_dir.display());
+    run_command(&[&"git", &"init"], Some(&sysroot_dir))?;
+    println!("[GIT] add (cwd): `{}`", sysroot_dir.display());
+    run_command(&[&"git", &"add", &"."], Some(&sysroot_dir))?;
+    println!("[GIT] commit (cwd): `{}`", sysroot_dir.display());
+
+    // This is needed on systems where nothing is configured.
+    // git really needs something here, or it will fail.
+    // Even using --author is not enough.
+    run_command(
+        &[&"git", &"config", &"user.email", &"none@example.com"],
+        Some(&sysroot_dir),
+    )?;
+    run_command(
+        &[&"git", &"config", &"user.name", &"None"],
+        Some(&sysroot_dir),
+    )?;
+    run_command(
+        &[&"git", &"config", &"core.autocrlf", &"false"],
+        Some(&sysroot_dir),
+    )?;
+    run_command(
+        &[&"git", &"config", &"commit.gpgSign", &"false"],
+        Some(&sysroot_dir),
+    )?;
+    run_command(
+        &[&"git", &"commit", &"-m", &"Initial commit", &"-q"],
+        Some(&sysroot_dir),
+    )?;
+
+    let mut patches = Vec::new();
+    walk_dir(
+        "patches",
+        |_| Ok(()),
+        |file_path: &Path| {
+            patches.push(file_path.to_path_buf());
+            Ok(())
+        },
+    )?;
+    if cross_compile {
+        walk_dir("cross_patches", |_| Ok(()), |file_path: &Path| {
+            patches.push(file_path.to_path_buf());
+            Ok(())
+        })?;
+    }
+    if libgccjit12_patches {
+        walk_dir(
+            "patches/libgccjit12",
+            |_| Ok(()),
+            |file_path: &Path| {
+                patches.push(file_path.to_path_buf());
+                Ok(())
+            },
+        )?;
+    }
+    patches.sort();
+    for file_path in patches {
+        println!("[GIT] apply `{}`", file_path.display());
+        let path = Path::new("../..").join(file_path);
+        run_command_with_output(&[&"git", &"apply", &path], Some(&sysroot_dir))?;
+        run_command_with_output(&[&"git", &"add", &"-A"], Some(&sysroot_dir))?;
+        run_command_with_output(
+            &[
+                &"git",
+                &"commit",
+                &"--no-gpg-sign",
+                &"-m",
+                &format!("Patch {}", path.display()),
+            ],
+            Some(&sysroot_dir),
+        )?;
+    }
+    println!("Successfully prepared libcore for building");
+    Ok(())
+}
+
+// build with cg_llvm for perf comparison
+fn build_raytracer(repo_dir: &Path) -> Result<(), String> {
+    run_command(&[&"cargo", &"build"], Some(repo_dir))?;
+    let mv_target = repo_dir.join("raytracer_cg_llvm");
+    if mv_target.is_file() {
+        std::fs::remove_file(&mv_target)
+            .map_err(|e| format!("Failed to remove file `{}`: {e:?}", mv_target.display()))?;
+    }
+    run_command(
+        &[&"mv", &"target/debug/main", &"raytracer_cg_llvm"],
+        Some(repo_dir),
+    )?;
+    Ok(())
+}
+
+fn clone_and_setup<F>(repo_url: &str, checkout_commit: &str, extra: Option<F>) -> Result<(), String>
+where
+    F: Fn(&Path) -> Result<(), String>,
+{
+    let clone_result = git_clone(repo_url, None)?;
+    if !clone_result.ran_clone {
+        println!("`{}` has already been cloned", clone_result.repo_name);
+    }
+    let repo_path = Path::new(&clone_result.repo_name);
+    run_command(&[&"git", &"checkout", &"--", &"."], Some(&repo_path))?;
+    run_command(&[&"git", &"checkout", &checkout_commit], Some(&repo_path))?;
+    let filter = format!("-{}-", clone_result.repo_name);
+    walk_dir(
+        "crate_patches",
+        |_| Ok(()),
+        |file_path| {
+            let patch = file_path.as_os_str().to_str().unwrap();
+            if patch.contains(&filter) && patch.ends_with(".patch") {
+                run_command_with_output(
+                    &[&"git", &"am", &file_path.canonicalize().unwrap()],
+                    Some(&repo_path),
+                )?;
+            }
+            Ok(())
+        },
+    )?;
+    if let Some(extra) = extra {
+        extra(&repo_path)?;
+    }
+    Ok(())
+}
+
+struct PrepareArg {
+    cross_compile: bool,
+    only_libcore: bool,
+    libgccjit12_patches: bool,
+}
+
+impl PrepareArg {
+    fn new() -> Result<Option<Self>, String> {
+        let mut only_libcore = false;
+        let mut cross_compile = false;
+        let mut libgccjit12_patches = false;
+
+        for arg in std::env::args().skip(2) {
+            match arg.as_str() {
+                "--only-libcore" => only_libcore = true,
+                "--cross" => cross_compile = true,
+                "--libgccjit12-patches" => libgccjit12_patches = true,
+                "--help" => {
+                    Self::usage();
+                    return Ok(None);
+                }
+                a => return Err(format!("Unknown argument `{a}`")),
+            }
+        }
+        Ok(Some(Self {
+            cross_compile,
+            only_libcore,
+            libgccjit12_patches,
+        }))
+    }
+
+    fn usage() {
+        println!(
+            r#"
+`prepare` command help:
+
+    --only-libcore           : Only setup libcore and don't clone other repositories
+    --cross                  : Apply the patches needed to do cross-compilation
+    --libgccjit12-patches    : Apply patches needed for libgccjit12
+    --help                   : Show this help
+"#
+        )
+    }
+}
+
+pub fn run() -> Result<(), String> {
+    let args = match PrepareArg::new()? {
+        Some(a) => a,
+        None => return Ok(()),
+    };
+    let sysroot_path = Path::new("build_sysroot");
+    prepare_libcore(sysroot_path, args.libgccjit12_patches, args.cross_compile)?;
+
+    if !args.only_libcore {
+        cargo_install("hyperfine")?;
+
+        let to_clone = &[
+            (
+                "https://github.com/rust-random/rand.git",
+                "0f933f9c7176e53b2a3c7952ded484e1783f0bf1",
+                None,
+            ),
+            (
+                "https://github.com/rust-lang/regex.git",
+                "341f207c1071f7290e3f228c710817c280c8dca1",
+                None,
+            ),
+            (
+                "https://github.com/ebobby/simple-raytracer",
+                "804a7a21b9e673a482797aa289a18ed480e4d813",
+                Some(build_raytracer),
+            ),
+        ];
+
+        for (repo_url, checkout_commit, cb) in to_clone {
+            clone_and_setup(repo_url, checkout_commit, *cb)?;
+        }
+    }
+
+    println!("Successfully ran `prepare`");
+    Ok(())
+}
diff --git a/compiler/rustc_codegen_gcc/build_system/src/rustc_info.rs b/compiler/rustc_codegen_gcc/build_system/src/rustc_info.rs
new file mode 100644
index 00000000000..0988b56d81e
--- /dev/null
+++ b/compiler/rustc_codegen_gcc/build_system/src/rustc_info.rs
@@ -0,0 +1,12 @@
+use std::path::{Path, PathBuf};
+
+use crate::utils::run_command;
+
+pub fn get_rustc_path() -> Option<PathBuf> {
+    if let Ok(rustc) = std::env::var("RUSTC") {
+        return Some(PathBuf::from(rustc));
+    }
+    run_command(&[&"rustup", &"which", &"rustc"], None)
+        .ok()
+        .map(|out| Path::new(String::from_utf8(out.stdout).unwrap().trim()).to_path_buf())
+}
diff --git a/compiler/rustc_codegen_gcc/build_system/src/test.rs b/compiler/rustc_codegen_gcc/build_system/src/test.rs
new file mode 100644
index 00000000000..4c8c63e59ab
--- /dev/null
+++ b/compiler/rustc_codegen_gcc/build_system/src/test.rs
@@ -0,0 +1,15 @@
+use crate::utils::run_command_with_output;
+
+fn get_args<'a>(args: &mut Vec<&'a dyn AsRef<std::ffi::OsStr>>, extra_args: &'a Vec<String>) {
+    for extra_arg in extra_args {
+        args.push(extra_arg);
+    }
+}
+
+pub fn run() -> Result<(), String> {
+    let mut args: Vec<&dyn AsRef<std::ffi::OsStr>> = vec![&"bash", &"test.sh"];
+    let extra_args = std::env::args().skip(2).collect::<Vec<_>>();
+    get_args(&mut args, &extra_args);
+    let current_dir = std::env::current_dir().map_err(|error| format!("`current_dir` failed: {:?}", error))?;
+    run_command_with_output(args.as_slice(), Some(&current_dir))
+}
diff --git a/compiler/rustc_codegen_gcc/build_system/src/utils.rs b/compiler/rustc_codegen_gcc/build_system/src/utils.rs
new file mode 100644
index 00000000000..536f33a8029
--- /dev/null
+++ b/compiler/rustc_codegen_gcc/build_system/src/utils.rs
@@ -0,0 +1,240 @@
+use std::collections::HashMap;
+use std::ffi::OsStr;
+use std::fmt::Debug;
+use std::fs;
+use std::path::Path;
+use std::process::{Command, ExitStatus, Output};
+
+fn get_command_inner(
+    input: &[&dyn AsRef<OsStr>],
+    cwd: Option<&Path>,
+    env: Option<&HashMap<String, String>>,
+) -> Command {
+    let (cmd, args) = match input {
+        [] => panic!("empty command"),
+        [cmd, args @ ..] => (cmd, args),
+    };
+    let mut command = Command::new(cmd);
+    command.args(args);
+    if let Some(cwd) = cwd {
+        command.current_dir(cwd);
+    }
+    if let Some(env) = env {
+        command.envs(env.iter().map(|(k, v)| (k.as_str(), v.as_str())));
+    }
+    command
+}
+
+fn check_exit_status(
+    input: &[&dyn AsRef<OsStr>],
+    cwd: Option<&Path>,
+    exit_status: ExitStatus,
+) -> Result<(), String> {
+    if exit_status.success() {
+        Ok(())
+    } else {
+        Err(format!(
+            "Command `{}`{} exited with status {:?}",
+            input
+                .iter()
+                .map(|s| s.as_ref().to_str().unwrap())
+                .collect::<Vec<_>>()
+                .join(" "),
+            cwd.map(|cwd| format!(" (running in folder `{}`)", cwd.display()))
+                .unwrap_or_default(),
+            exit_status.code(),
+        ))
+    }
+}
+
+fn command_error<D: Debug>(input: &[&dyn AsRef<OsStr>], cwd: &Option<&Path>, error: D) -> String {
+    format!(
+        "Command `{}`{} failed to run: {error:?}",
+        input
+            .iter()
+            .map(|s| s.as_ref().to_str().unwrap())
+            .collect::<Vec<_>>()
+            .join(" "),
+        cwd.as_ref()
+            .map(|cwd| format!(" (running in folder `{}`)", cwd.display(),))
+            .unwrap_or_default(),
+    )
+}
+
+pub fn run_command(input: &[&dyn AsRef<OsStr>], cwd: Option<&Path>) -> Result<Output, String> {
+    run_command_with_env(input, cwd, None)
+}
+
+pub fn run_command_with_env(
+    input: &[&dyn AsRef<OsStr>],
+    cwd: Option<&Path>,
+    env: Option<&HashMap<String, String>>,
+) -> Result<Output, String> {
+    let output = get_command_inner(input, cwd, env)
+        .output()
+        .map_err(|e| command_error(input, &cwd, e))?;
+    check_exit_status(input, cwd, output.status)?;
+    Ok(output)
+}
+
+pub fn run_command_with_output(
+    input: &[&dyn AsRef<OsStr>],
+    cwd: Option<&Path>,
+) -> Result<(), String> {
+    let exit_status = get_command_inner(input, cwd, None)
+        .spawn()
+        .map_err(|e| command_error(input, &cwd, e))?
+        .wait()
+        .map_err(|e| command_error(input, &cwd, e))?;
+    check_exit_status(input, cwd, exit_status)?;
+    Ok(())
+}
+
+pub fn run_command_with_output_and_env(
+    input: &[&dyn AsRef<OsStr>],
+    cwd: Option<&Path>,
+    env: Option<&HashMap<String, String>>,
+) -> Result<(), String> {
+    let exit_status = get_command_inner(input, cwd, env)
+        .spawn()
+        .map_err(|e| command_error(input, &cwd, e))?
+        .wait()
+        .map_err(|e| command_error(input, &cwd, e))?;
+    check_exit_status(input, cwd, exit_status)?;
+    Ok(())
+}
+
+pub fn cargo_install(to_install: &str) -> Result<(), String> {
+    let output = run_command(&[&"cargo", &"install", &"--list"], None)?;
+
+    let to_install_needle = format!("{to_install} ");
+    // cargo install --list returns something like this:
+    //
+    // mdbook-toc v0.8.0:
+    //     mdbook-toc
+    // rust-reduce v0.1.0:
+    //     rust-reduce
+    //
+    // We are only interested into the command name so we only look for lines ending with `:`.
+    if String::from_utf8(output.stdout)
+        .unwrap()
+        .lines()
+        .any(|line| line.ends_with(':') && line.starts_with(&to_install_needle))
+    {
+        return Ok(());
+    }
+    // We voluntarily ignore this error.
+    if run_command_with_output(&[&"cargo", &"install", &to_install], None).is_err() {
+        println!("Skipping installation of `{to_install}`");
+    }
+    Ok(())
+}
+
+pub fn get_os_name() -> Result<String, String> {
+    let output = run_command(&[&"uname"], None)?;
+    let name = std::str::from_utf8(&output.stdout)
+        .unwrap_or("")
+        .trim()
+        .to_string();
+    if !name.is_empty() {
+        Ok(name)
+    } else {
+        Err("Failed to retrieve the OS name".to_string())
+    }
+}
+
+pub fn get_rustc_host_triple() -> Result<String, String> {
+    let output = run_command(&[&"rustc", &"-vV"], None)?;
+    let content = std::str::from_utf8(&output.stdout).unwrap_or("");
+
+    for line in content.split('\n').map(|line| line.trim()) {
+        if !line.starts_with("host:") {
+            continue;
+        }
+        return Ok(line.split(':').nth(1).unwrap().trim().to_string());
+    }
+    Err("Cannot find host triple".to_string())
+}
+
+pub fn get_gcc_path() -> Result<String, String> {
+    let content = match fs::read_to_string("gcc_path") {
+        Ok(content) => content,
+        Err(_) => {
+            return Err(
+                "Please put the path to your custom build of libgccjit in the file \
+                   `gcc_path`, see Readme.md for details"
+                    .into(),
+            )
+        }
+    };
+    match content
+        .split('\n')
+        .map(|line| line.trim())
+        .filter(|line| !line.is_empty())
+        .next()
+    {
+        Some(gcc_path) => {
+            let path = Path::new(gcc_path);
+            if !path.exists() {
+                Err(format!(
+                    "Path `{}` contained in the `gcc_path` file doesn't exist",
+                    gcc_path,
+                ))
+            } else {
+                Ok(gcc_path.into())
+            }
+        }
+        None => Err("No path found in `gcc_path` file".into()),
+    }
+}
+
+pub struct CloneResult {
+    pub ran_clone: bool,
+    pub repo_name: String,
+}
+
+pub fn git_clone(to_clone: &str, dest: Option<&Path>) -> Result<CloneResult, String> {
+    let repo_name = to_clone.split('/').last().unwrap();
+    let repo_name = match repo_name.strip_suffix(".git") {
+        Some(n) => n.to_string(),
+        None => repo_name.to_string(),
+    };
+
+    let dest = dest
+        .map(|dest| dest.join(&repo_name))
+        .unwrap_or_else(|| Path::new(&repo_name).into());
+    if dest.is_dir() {
+        return Ok(CloneResult {
+            ran_clone: false,
+            repo_name,
+        });
+    }
+
+    run_command_with_output(&[&"git", &"clone", &to_clone, &dest], None)?;
+    Ok(CloneResult {
+        ran_clone: true,
+        repo_name,
+    })
+}
+
+pub fn walk_dir<P, D, F>(dir: P, mut dir_cb: D, mut file_cb: F) -> Result<(), String>
+where
+    P: AsRef<Path>,
+    D: FnMut(&Path) -> Result<(), String>,
+    F: FnMut(&Path) -> Result<(), String>,
+{
+    let dir = dir.as_ref();
+    for entry in fs::read_dir(dir)
+        .map_err(|error| format!("Failed to read dir `{}`: {:?}", dir.display(), error))?
+    {
+        let entry = entry
+            .map_err(|error| format!("Failed to read entry in `{}`: {:?}", dir.display(), error))?;
+        let entry_path = entry.path();
+        if entry_path.is_dir() {
+            dir_cb(&entry_path)?;
+        } else {
+            file_cb(&entry_path)?;
+        }
+    }
+    Ok(())
+}
diff --git a/compiler/rustc_codegen_gcc/cargo.sh b/compiler/rustc_codegen_gcc/cargo.sh
index 16e49b20423..b68a08ee88f 100755
--- a/compiler/rustc_codegen_gcc/cargo.sh
+++ b/compiler/rustc_codegen_gcc/cargo.sh
@@ -12,7 +12,7 @@ TOOLCHAIN=$(cat rust-toolchain | grep channel | sed 's/channel = "\(.*\)"/\1/')
 
 popd >/dev/null
 
-if [[ $(rustc -V) != $(rustc +${TOOLCHAIN} -V) ]]; then
+if [[ $(${RUSTC} -V) != $(${RUSTC} +${TOOLCHAIN} -V) ]]; then
     echo "rustc_codegen_gcc is build for $(rustc +${TOOLCHAIN} -V) but the default rustc version is $(rustc -V)."
     echo "Using $(rustc +${TOOLCHAIN} -V)."
 fi
diff --git a/compiler/rustc_codegen_gcc/config.sh b/compiler/rustc_codegen_gcc/config.sh
index 166e83901c4..7ae2175d41d 100644
--- a/compiler/rustc_codegen_gcc/config.sh
+++ b/compiler/rustc_codegen_gcc/config.sh
@@ -4,49 +4,82 @@ export CARGO_INCREMENTAL=0
 
 if [ -f ./gcc_path ]; then
     export GCC_PATH=$(cat gcc_path)
+elif (( $use_system_gcc == 1 )); then
+    echo 'Using system GCC'
 else
     echo 'Please put the path to your custom build of libgccjit in the file `gcc_path`, see Readme.md for details'
     exit 1
 fi
 
+if [[ -z "$RUSTC" ]]; then
+    export RUSTC="rustc"
+fi
+
 unamestr=`uname`
 if [[ "$unamestr" == 'Linux' ]]; then
-   dylib_ext='so'
+    dylib_ext='so'
 elif [[ "$unamestr" == 'Darwin' ]]; then
-   dylib_ext='dylib'
+    dylib_ext='dylib'
 else
-   echo "Unsupported os"
-   exit 1
+    echo "Unsupported os"
+    exit 1
 fi
 
-HOST_TRIPLE=$(rustc -vV | grep host | cut -d: -f2 | tr -d " ")
-TARGET_TRIPLE=$HOST_TRIPLE
-#TARGET_TRIPLE="m68k-unknown-linux-gnu"
+HOST_TRIPLE=$($RUSTC -vV | grep host | cut -d: -f2 | tr -d " ")
+# TODO: remove $OVERWRITE_TARGET_TRIPLE when config.sh is removed.
+TARGET_TRIPLE="${OVERWRITE_TARGET_TRIPLE:-$HOST_TRIPLE}"
 
 linker=''
 RUN_WRAPPER=''
 if [[ "$HOST_TRIPLE" != "$TARGET_TRIPLE" ]]; then
-   if [[ "$TARGET_TRIPLE" == "m68k-unknown-linux-gnu" ]]; then
-       TARGET_TRIPLE="mips-unknown-linux-gnu"
-       linker='-Clinker=m68k-linux-gcc'
-   elif [[ "$TARGET_TRIPLE" == "aarch64-unknown-linux-gnu" ]]; then
-      # We are cross-compiling for aarch64. Use the correct linker and run tests in qemu.
-      linker='-Clinker=aarch64-linux-gnu-gcc'
-      RUN_WRAPPER='qemu-aarch64 -L /usr/aarch64-linux-gnu'
-   else
-      echo "Unknown non-native platform"
-   fi
+    RUN_WRAPPER=run_in_vm
+    if [[ "$TARGET_TRIPLE" == "m68k-unknown-linux-gnu" ]]; then
+        linker='-Clinker=m68k-unknown-linux-gnu-gcc'
+    elif [[ "$TARGET_TRIPLE" == "aarch64-unknown-linux-gnu" ]]; then
+        # We are cross-compiling for aarch64. Use the correct linker and run tests in qemu.
+        linker='-Clinker=aarch64-linux-gnu-gcc'
+    else
+        echo "Unknown non-native platform"
+    fi
 fi
 
-export RUSTFLAGS="$CG_RUSTFLAGS $linker -Csymbol-mangling-version=v0 -Cdebuginfo=2 -Clto=off -Zcodegen-backend=$(pwd)/target/${CHANNEL:-debug}/librustc_codegen_gcc.$dylib_ext --sysroot $(pwd)/build_sysroot/sysroot $TEST_FLAGS"
+# Since we don't support ThinLTO, disable LTO completely when not trying to do LTO.
+# TODO(antoyo): remove when we can handle ThinLTO.
+disable_lto_flags=''
+if [[ ! -v FAT_LTO ]]; then
+    disable_lto_flags='-Clto=off'
+fi
+
+if [[ -z "$BUILTIN_BACKEND" ]]; then
+    export RUSTFLAGS="$CG_RUSTFLAGS $linker -Csymbol-mangling-version=v0 -Cdebuginfo=2 $disable_lto_flags -Zcodegen-backend=$(pwd)/target/${CHANNEL:-debug}/librustc_codegen_gcc.$dylib_ext --sysroot $(pwd)/build_sysroot/sysroot $TEST_FLAGS"
+else
+    export RUSTFLAGS="$CG_RUSTFLAGS $linker -Csymbol-mangling-version=v0 -Cdebuginfo=2 $disable_lto_flags -Zcodegen-backend=gcc $TEST_FLAGS -Cpanic=abort"
+
+    if [[ ! -z "$RUSTC_SYSROOT" ]]; then
+        export RUSTFLAGS="$RUSTFLAGS --sysroot $RUSTC_SYSROOT"
+    fi
+fi
 
 # FIXME(antoyo): remove once the atomic shim is gone
-if [[ `uname` == 'Darwin' ]]; then
-   export RUSTFLAGS="$RUSTFLAGS -Clink-arg=-undefined -Clink-arg=dynamic_lookup"
+if [[ unamestr == 'Darwin' ]]; then
+    export RUSTFLAGS="$RUSTFLAGS -Clink-arg=-undefined -Clink-arg=dynamic_lookup"
 fi
 
-RUSTC="rustc $RUSTFLAGS -L crate=target/out --out-dir target/out"
+if [[ -z "$cargo_target_dir" ]]; then
+    RUST_CMD="$RUSTC $RUSTFLAGS -L crate=target/out --out-dir target/out"
+    cargo_target_dir="target/out"
+else
+    RUST_CMD="$RUSTC $RUSTFLAGS -L crate=$cargo_target_dir --out-dir $cargo_target_dir"
+fi
 export RUSTC_LOG=warn # display metadata load errors
 
-export LD_LIBRARY_PATH="$(pwd)/target/out:$(pwd)/build_sysroot/sysroot/lib/rustlib/$TARGET_TRIPLE/lib:$GCC_PATH"
+export LD_LIBRARY_PATH="$(pwd)/target/out:$(pwd)/build_sysroot/sysroot/lib/rustlib/$TARGET_TRIPLE/lib"
+if [[ ! -z "$:$GCC_PATH" ]]; then
+    export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$GCC_PATH"
+fi
+
 export DYLD_LIBRARY_PATH=$LD_LIBRARY_PATH
+# NOTE: To avoid the -fno-inline errors, use /opt/gcc/bin/gcc instead of cc.
+# To do so, add a symlink for cc to /opt/gcc/bin/gcc in our PATH.
+# Another option would be to add the following Rust flag: -Clinker=/opt/gcc/bin/gcc
+export PATH="/opt/gcc/bin:/opt/m68k-unknown-linux-gnu/bin:$PATH"
diff --git a/compiler/rustc_codegen_gcc/cross_patches/0001-Disable-libstd-and-libtest-dylib.patch b/compiler/rustc_codegen_gcc/cross_patches/0001-Disable-libstd-and-libtest-dylib.patch
new file mode 100644
index 00000000000..74d9c208a05
--- /dev/null
+++ b/compiler/rustc_codegen_gcc/cross_patches/0001-Disable-libstd-and-libtest-dylib.patch
@@ -0,0 +1,39 @@
+From 966beefe08be6045bfcca26079b76a7a80413080 Mon Sep 17 00:00:00 2001
+From: None <none@example.com>
+Date: Thu, 28 Sep 2023 17:37:38 -0400
+Subject: [PATCH] Disable libstd and libtest dylib
+
+---
+ library/std/Cargo.toml  | 2 +-
+ library/test/Cargo.toml | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml
+index 5b21355..cb0c49b 100644
+--- a/library/std/Cargo.toml
++++ b/library/std/Cargo.toml
+@@ -9,7 +9,7 @@ description = "The Rust Standard Library"
+ edition = "2021"
+ 
+ [lib]
+-crate-type = ["dylib", "rlib"]
++crate-type = ["rlib"]
+ 
+ [dependencies]
+ alloc = { path = "../alloc", public = true }
+diff --git a/library/test/Cargo.toml b/library/test/Cargo.toml
+index 91a1abd..a58c160 100644
+--- a/library/test/Cargo.toml
++++ b/library/test/Cargo.toml
+@@ -4,7 +4,7 @@ version = "0.0.0"
+ edition = "2021"
+ 
+ [lib]
+-crate-type = ["dylib", "rlib"]
++crate-type = ["rlib"]
+ 
+ [dependencies]
+ getopts = { version = "0.2.21", features = ['rustc-dep-of-std'] }
+-- 
+2.42.0
+
diff --git a/compiler/rustc_codegen_gcc/doc/add-attribute.md b/compiler/rustc_codegen_gcc/doc/add-attribute.md
new file mode 100644
index 00000000000..ae3bcc5e2eb
--- /dev/null
+++ b/compiler/rustc_codegen_gcc/doc/add-attribute.md
@@ -0,0 +1,17 @@
+# Add support for a new function attribute
+
+To add support for a new function attribute in libgccjit, you need to do the following steps:
+
+ 1. Copy the corresponding function from `c-family/c-attribs.cc` into `jit/dummy-frontend.cc`. For example if you add the `target` attribute, the function name will be `handle_target_attribute`.
+ 2. Copy the corresponding entry from the `c_common_attribute_table` variable in the `c-family/c-attribs.cc` file into the `jit_attribute_table` variable in `jit/dummy-frontend.cc`.
+ 3. Add a new variant in the `gcc_jit_fn_attribute` enum in the `jit/libgccjit.h` file.
+ 4. Add a test to ensure the attribute is correctly applied in `gcc/testsuite/jit.dg/`. Take a look at `gcc/testsuite/jit.dg/test-nonnull.c` if you want an example.
+ 5. Run the example like this (in your `gcc-build` folder): `make check-jit RUNTESTFLAGS="-v -v -v jit.exp=jit.dg/test-nonnull.c"`
+
+Once done, you need to update the [gccjit.rs] crate to add the new enum variant in the corresponding enum (`FnAttribute`).
+
+Finally, you need to update this repository by calling the relevant API you added in [gccjit.rs].
+
+To test it, build `gcc`, run `cargo update -p gccjit` and then you can test the generated output for a given Rust crate.
+
+[gccjit.rs]: https://github.com/antoyo/gccjit.rs
diff --git a/compiler/rustc_codegen_gcc/doc/gimple.md b/compiler/rustc_codegen_gcc/doc/gimple.md
new file mode 100644
index 00000000000..145c4eda3c1
--- /dev/null
+++ b/compiler/rustc_codegen_gcc/doc/gimple.md
@@ -0,0 +1,111 @@
+# GIMPLE
+
+You can see the full documentation about what GIMPLE is [here](https://gcc.gnu.org/onlinedocs/gccint/GIMPLE.html). In this document we will explain how to generate it.
+
+First, we'll copy the content from `gcc/gcc/testsuite/jit.dg/test-const-attribute.c` into a
+file named `local.c` and remove the content we're not interested into:
+
+```diff
+- /* { dg-do compile { target x86_64-*-* } } */
+...
+- /* We don't want set_options() in harness.h to set -O3 to see that the const
+-    attribute affects the optimizations. */
+- #define TEST_ESCHEWS_SET_OPTIONS
+- static void set_options (gcc_jit_context *ctxt, const char *argv0)
+- {
+-   // Set "-O3".
+-   gcc_jit_context_set_int_option(ctxt, GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL, 3);
+- }
+-
+- #define TEST_COMPILING_TO_FILE
+- #define OUTPUT_KIND      GCC_JIT_OUTPUT_KIND_ASSEMBLER
+- #define OUTPUT_FILENAME  "output-of-test-const-attribute.c.s"
+- #include "harness.h"
+...
+- /* { dg-final { jit-verify-output-file-was-created "" } } */
+- /* Check that the loop was optimized away */
+- /* { dg-final { jit-verify-assembler-output-not "jne" } } */
+```
+
+Then we'll add a `main` function which will call the `create_code` function but
+also add the calls we need to generate the GIMPLE:
+
+```C
+int main() {
+    gcc_jit_context *ctxt = gcc_jit_context_acquire();
+    // To set `-O3`, update it depending on your needs.
+    gcc_jit_context_set_int_option(ctxt, GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL, 3);
+    // Very important option to generate the gimple format.
+    gcc_jit_context_set_bool_option(ctxt, GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE, 1);
+    create_code(ctxt, NULL);
+
+    gcc_jit_context_compile(ctxt);
+    // If you want to compile to assembly (or any other format) directly, you can
+    // use the following call instead:
+    // gcc_jit_context_compile_to_file(ctxt, GCC_JIT_OUTPUT_KIND_ASSEMBLER, "out.s");
+
+    return 0;
+}
+```
+
+Then we can compile it by using:
+
+```console
+gcc local.c -I `pwd`/gcc/gcc/jit/ -L `pwd`/gcc-build/gcc -lgccjit -o out
+```
+
+And finally when you run it:
+
+```console
+LD_LIBRARY_PATH=`pwd`/gcc-build/gcc LIBRARY_PATH=`pwd`/gcc-build/gcc ./out
+```
+
+It should display:
+
+```c
+__attribute__((const))
+int xxx ()
+{
+  int D.3394;
+  int sum;
+  int x;
+
+  <D.3377>:
+  x = 45;
+  sum = 0;
+  goto loop_cond;
+  loop_cond:
+  x = x >> 1;
+  if (x != 0) goto after_loop; else goto loop_body;
+  loop_body:
+  _1 = foo (x);
+  _2 = _1 * 2;
+  x = x + _2;
+  goto loop_cond;
+  after_loop:
+  D.3394 = sum;
+  return D.3394;
+}
+```
+
+An alternative way to generate the GIMPLE is to replace:
+
+```c
+    gcc_jit_context_set_bool_option(ctxt, GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE, 1);
+```
+
+with:
+
+```c
+    gcc_jit_context_add_command_line_option(ctxt, "-fdump-tree-gimple");
+```
+
+(although you can have both at the same time too). Then you can compile it like previously. Only one difference: before executing it, I recommend to run:
+
+```console
+rm -rf /tmp/libgccjit-*
+```
+
+to make it easier for you to know which folder to look into.
+
+Once the execution is done, you should now have a file with path looking like `/tmp/libgccjit-9OFqkD/fake.c.006t.gimple` which contains the GIMPLE format.
diff --git a/compiler/rustc_codegen_gcc/doc/sending-gcc-patch.md b/compiler/rustc_codegen_gcc/doc/sending-gcc-patch.md
new file mode 100644
index 00000000000..7a47ef29f3c
--- /dev/null
+++ b/compiler/rustc_codegen_gcc/doc/sending-gcc-patch.md
@@ -0,0 +1,44 @@
+This guide explains what to do to send a GCC patch for review.
+
+All the commands are supposed to be run in the folder where you cloned GCC.
+
+```bash
+./contrib/gcc-changelog/git_check_commit.py
+```
+
+You can provide a specific commit hash:
+
+```bash
+./contrib/gcc-changelog/git_check_commit.py abdef78989
+```
+
+a range:
+
+```bash
+./contrib/gcc-changelog/git_check_commit.py HEAD~2
+```
+
+or even a comparison with a remote branch:
+
+```bash
+./contrib/gcc-changelog/git_check_commit.py upstream/master..HEAD
+```
+
+When there is no more errors, generate the git patch:
+
+```bash
+git format-patch -1 `git rev-parse --short HEAD`
+```
+
+Then you can run the remaining checks using:
+
+```bash
+contrib/check_GNU_style.sh 0001-your-patch.patch
+```
+
+When you have no more errors, you can send the `.patch` file to GCC by sending an
+email to `gcc-patches@gcc.gnu.org` and to the relevant GCC mailing lists
+depending on what your patch changes. You can find the list of the mailing lists
+[here](https://gcc.gnu.org/lists.html).
+
+You can find more information about "contributing to GCC" [here](https://gcc.gnu.org/contribute.html).
diff --git a/compiler/rustc_codegen_gcc/doc/tests.md b/compiler/rustc_codegen_gcc/doc/tests.md
new file mode 100644
index 00000000000..3ac993bc2fd
--- /dev/null
+++ b/compiler/rustc_codegen_gcc/doc/tests.md
@@ -0,0 +1,5 @@
+# Tests
+
+## Show the rustc command for UI tests
+
+Add ` --test-args "--verbose"` to `./x.py test`.
diff --git a/compiler/rustc_codegen_gcc/example/alloc_example.rs b/compiler/rustc_codegen_gcc/example/alloc_example.rs
index 754e7931412..6ed8b9157f2 100644
--- a/compiler/rustc_codegen_gcc/example/alloc_example.rs
+++ b/compiler/rustc_codegen_gcc/example/alloc_example.rs
@@ -1,5 +1,6 @@
 #![feature(start, core_intrinsics, alloc_error_handler, lang_items)]
 #![no_std]
+#![allow(internal_features)]
 
 extern crate alloc;
 extern crate alloc_system;
@@ -17,7 +18,7 @@ extern "C" {
 }
 
 #[panic_handler]
-fn panic_handler(_: &core::panic::PanicInfo) -> ! {
+fn panic_handler(_: &core::panic::PanicInfo<'_>) -> ! {
     core::intrinsics::abort();
 }
 
diff --git a/compiler/rustc_codegen_gcc/example/alloc_system.rs b/compiler/rustc_codegen_gcc/example/alloc_system.rs
index 3deef419f42..945d34063a6 100644
--- a/compiler/rustc_codegen_gcc/example/alloc_system.rs
+++ b/compiler/rustc_codegen_gcc/example/alloc_system.rs
@@ -3,16 +3,16 @@
 
 #![no_std]
 #![feature(allocator_api, rustc_private)]
-#![cfg_attr(any(unix, target_os = "redox"), feature(libc))]
 
 // The minimum alignment guaranteed by the architecture. This value is used to
 // add fast paths for low alignment values.
 #[cfg(any(target_arch = "x86",
               target_arch = "arm",
+              target_arch = "m68k",
               target_arch = "mips",
               target_arch = "mips32r6",
               target_arch = "powerpc",
-              target_arch = "csky"
+              target_arch = "csky",
               target_arch = "powerpc64"))]
 const MIN_ALIGN: usize = 8;
 #[cfg(any(target_arch = "x86_64",
@@ -47,7 +47,18 @@ mod realloc_fallback {
 }
 #[cfg(any(unix, target_os = "redox"))]
 mod platform {
-    extern crate libc;
+    mod libc {
+        use core::ffi::{c_void, c_int};
+
+        #[link(name = "c")]
+        extern "C" {
+            pub fn malloc(size: usize) -> *mut c_void;
+            pub fn realloc(ptr: *mut c_void, size: usize) -> *mut c_void;
+            pub fn calloc(nmemb: usize, size: usize) -> *mut c_void;
+            pub fn free(ptr: *mut u8);
+            pub fn posix_memalign(memptr: *mut *mut c_void, alignment: usize, size: usize) -> c_int;
+        }
+    }
     use core::ptr;
     use MIN_ALIGN;
     use System;
@@ -81,12 +92,12 @@ mod platform {
         }
         #[inline]
         unsafe fn dealloc(&self, ptr: *mut u8, _layout: Layout) {
-            libc::free(ptr as *mut libc::c_void)
+            libc::free(ptr as *mut _)
         }
         #[inline]
         unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
             if layout.align() <= MIN_ALIGN && layout.align() <= new_size {
-                libc::realloc(ptr as *mut libc::c_void, new_size) as *mut u8
+                libc::realloc(ptr as *mut _, new_size) as *mut u8
             } else {
                 self.realloc_fallback(ptr, layout, new_size)
             }
diff --git a/compiler/rustc_codegen_gcc/example/arbitrary_self_types_pointers_and_wrappers.rs b/compiler/rustc_codegen_gcc/example/arbitrary_self_types_pointers_and_wrappers.rs
index 3af0ba09e0b..b299aa87974 100644
--- a/compiler/rustc_codegen_gcc/example/arbitrary_self_types_pointers_and_wrappers.rs
+++ b/compiler/rustc_codegen_gcc/example/arbitrary_self_types_pointers_and_wrappers.rs
@@ -2,6 +2,7 @@
 
 #![feature(arbitrary_self_types, unsize, coerce_unsized, dispatch_from_dyn)]
 #![feature(rustc_attrs)]
+#![allow(internal_features)]
 
 use std::{
     ops::{Deref, CoerceUnsized, DispatchFromDyn},
diff --git a/compiler/rustc_codegen_gcc/example/mini_core.rs b/compiler/rustc_codegen_gcc/example/mini_core.rs
index 0cd7e6047c2..34328520343 100644
--- a/compiler/rustc_codegen_gcc/example/mini_core.rs
+++ b/compiler/rustc_codegen_gcc/example/mini_core.rs
@@ -4,7 +4,7 @@
     thread_local
 )]
 #![no_core]
-#![allow(dead_code)]
+#![allow(dead_code, internal_features)]
 
 #[no_mangle]
 unsafe extern "C" fn _Unwind_Resume() {
@@ -429,6 +429,15 @@ fn panic_cannot_unwind() -> ! {
     }
 }
 
+#[lang = "panic_in_cleanup"]
+#[rustc_nounwind]
+fn panic_in_cleanup() -> ! {
+    unsafe {
+        libc::printf("panic in a destructor during cleanup\n\0" as *const str as *const i8);
+        intrinsics::abort();
+    }
+}
+
 #[lang = "panic_bounds_check"]
 #[track_caller]
 fn panic_bounds_check(index: usize, len: usize) -> ! {
diff --git a/compiler/rustc_codegen_gcc/example/mini_core_hello_world.rs b/compiler/rustc_codegen_gcc/example/mini_core_hello_world.rs
index b93d6859706..40a1ad22c0e 100644
--- a/compiler/rustc_codegen_gcc/example/mini_core_hello_world.rs
+++ b/compiler/rustc_codegen_gcc/example/mini_core_hello_world.rs
@@ -5,7 +5,7 @@
     extern_types, thread_local
 )]
 #![no_core]
-#![allow(dead_code, non_camel_case_types)]
+#![allow(dead_code, internal_features, non_camel_case_types)]
 
 extern crate mini_core;
 
@@ -152,7 +152,8 @@ fn main() {
     let slice = &[0, 1] as &[i32];
     let slice_ptr = slice as *const [i32] as *const i32;
 
-    assert_eq!(slice_ptr as usize % 4, 0);
+    let align = intrinsics::min_align_of::<*const i32>();
+    assert_eq!(slice_ptr as usize % align, 0);
 
     //return;
 
@@ -186,7 +187,10 @@ fn main() {
         let a: &dyn SomeTrait = &"abc\0";
         a.object_safe();
 
+        #[cfg(target_arch="x86_64")]
         assert_eq!(intrinsics::size_of_val(a) as u8, 16);
+        #[cfg(target_arch="m68k")]
+        assert_eq!(intrinsics::size_of_val(a) as u8, 8);
         assert_eq!(intrinsics::size_of_val(&0u32) as u8, 4);
 
         assert_eq!(intrinsics::min_align_of::<u16>() as u8, 2);
diff --git a/compiler/rustc_codegen_gcc/example/mod_bench.rs b/compiler/rustc_codegen_gcc/example/mod_bench.rs
index 5e2e7f25a2c..cae911c1073 100644
--- a/compiler/rustc_codegen_gcc/example/mod_bench.rs
+++ b/compiler/rustc_codegen_gcc/example/mod_bench.rs
@@ -1,11 +1,12 @@
 #![feature(start, core_intrinsics, lang_items)]
 #![no_std]
+#![allow(internal_features)]
 
 #[link(name = "c")]
 extern {}
 
 #[panic_handler]
-fn panic_handler(_: &core::panic::PanicInfo) -> ! {
+fn panic_handler(_: &core::panic::PanicInfo<'_>) -> ! {
     core::intrinsics::abort();
 }
 
diff --git a/compiler/rustc_codegen_gcc/example/std_example.rs b/compiler/rustc_codegen_gcc/example/std_example.rs
index 18f2ddcde12..0f6325c8980 100644
--- a/compiler/rustc_codegen_gcc/example/std_example.rs
+++ b/compiler/rustc_codegen_gcc/example/std_example.rs
@@ -1,9 +1,10 @@
-#![feature(core_intrinsics, generators, generator_trait, is_sorted)]
+#![feature(core_intrinsics, coroutines, coroutine_trait, is_sorted)]
 
 #[cfg(feature="master")]
+#[cfg(target_arch="x86_64")]
 use std::arch::x86_64::*;
 use std::io::Write;
-use std::ops::Generator;
+use std::ops::Coroutine;
 
 extern {
     pub fn printf(format: *const i8, ...) -> i32;
@@ -95,6 +96,7 @@ fn main() {
 
     println!("{:?}", std::intrinsics::caller_location());
 
+    #[cfg(target_arch="x86_64")]
     #[cfg(feature="master")]
     unsafe {
         test_simd();
@@ -108,6 +110,7 @@ fn main() {
 }
 
 #[cfg(feature="master")]
+#[cfg(target_arch="x86_64")]
 #[target_feature(enable = "sse2")]
 unsafe fn test_simd() {
     let x = _mm_setzero_si128();
@@ -136,6 +139,7 @@ unsafe fn test_simd() {
 }
 
 #[cfg(feature="master")]
+#[cfg(target_arch="x86_64")]
 #[target_feature(enable = "sse2")]
 unsafe fn test_mm_slli_si128() {
     #[rustfmt::skip]
@@ -164,6 +168,7 @@ unsafe fn test_mm_slli_si128() {
 
 
 #[cfg(feature="master")]
+#[cfg(target_arch="x86_64")]
 #[target_feature(enable = "sse2")]
 unsafe fn test_mm_movemask_epi8() {
     #[rustfmt::skip]
@@ -178,6 +183,7 @@ unsafe fn test_mm_movemask_epi8() {
 }
 
 #[cfg(feature="master")]
+#[cfg(target_arch="x86_64")]
 #[target_feature(enable = "avx2")]
 unsafe fn test_mm256_movemask_epi8() {
     let a = _mm256_set1_epi8(-1);
@@ -187,6 +193,7 @@ unsafe fn test_mm256_movemask_epi8() {
 }
 
 #[cfg(feature="master")]
+#[cfg(target_arch="x86_64")]
 #[target_feature(enable = "sse2")]
 unsafe fn test_mm_add_epi8() {
     let a = _mm_setr_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
@@ -203,6 +210,7 @@ unsafe fn test_mm_add_epi8() {
 }
 
 #[cfg(feature="master")]
+#[cfg(target_arch="x86_64")]
 #[target_feature(enable = "sse2")]
 unsafe fn test_mm_add_pd() {
     let a = _mm_setr_pd(1.0, 2.0);
@@ -212,6 +220,7 @@ unsafe fn test_mm_add_pd() {
 }
 
 #[cfg(feature="master")]
+#[cfg(target_arch="x86_64")]
 fn assert_eq_m128i(x: std::arch::x86_64::__m128i, y: std::arch::x86_64::__m128i) {
     unsafe {
         assert_eq!(std::mem::transmute::<_, [u8; 16]>(x), std::mem::transmute::<_, [u8; 16]>(y));
@@ -219,6 +228,7 @@ fn assert_eq_m128i(x: std::arch::x86_64::__m128i, y: std::arch::x86_64::__m128i)
 }
 
 #[cfg(feature="master")]
+#[cfg(target_arch="x86_64")]
 #[target_feature(enable = "sse2")]
 pub unsafe fn assert_eq_m128d(a: __m128d, b: __m128d) {
     if _mm_movemask_pd(_mm_cmpeq_pd(a, b)) != 0b11 {
@@ -227,6 +237,7 @@ pub unsafe fn assert_eq_m128d(a: __m128d, b: __m128d) {
 }
 
 #[cfg(feature="master")]
+#[cfg(target_arch="x86_64")]
 #[target_feature(enable = "sse2")]
 unsafe fn test_mm_cvtsi128_si64() {
     let r = _mm_cvtsi128_si64(std::mem::transmute::<[i64; 2], _>([5, 0]));
@@ -234,6 +245,7 @@ unsafe fn test_mm_cvtsi128_si64() {
 }
 
 #[cfg(feature="master")]
+#[cfg(target_arch="x86_64")]
 #[target_feature(enable = "sse4.1")]
 unsafe fn test_mm_cvtepi8_epi16() {
     let a = _mm_set1_epi8(10);
@@ -247,6 +259,7 @@ unsafe fn test_mm_cvtepi8_epi16() {
 }
 
 #[cfg(feature="master")]
+#[cfg(target_arch="x86_64")]
 #[target_feature(enable = "sse4.1")]
 unsafe fn test_mm_extract_epi8() {
     #[rustfmt::skip]
diff --git a/compiler/rustc_codegen_gcc/failing-lto-tests.txt b/compiler/rustc_codegen_gcc/failing-lto-tests.txt
new file mode 100644
index 00000000000..2e0b6134070
--- /dev/null
+++ b/compiler/rustc_codegen_gcc/failing-lto-tests.txt
@@ -0,0 +1,23 @@
+tests/ui/lint/unsafe_code/forge_unsafe_block.rs
+tests/ui/lint/unused-qualification-in-derive-expansion.rs
+tests/ui/macro-quote-test.rs
+tests/ui/macros/proc_macro.rs
+tests/ui/panic-runtime/lto-unwind.rs
+tests/ui/resolve/derive-macro-1.rs
+tests/ui/resolve/derive-macro-2.rs
+tests/ui/rfcs/rfc-2565-param-attrs/param-attrs-pretty.rs
+tests/ui/rfcs/rfc-2565-param-attrs/issue-64682-dropping-first-attrs-in-impl-fns.rs
+tests/ui/rfcs/rfc-3348-c-string-literals/edition-spans.rs
+tests/ui/rust-2018/suggestions-not-always-applicable.rs
+tests/ui/rust-2021/reserved-prefixes-via-macro.rs
+tests/ui/underscore-imports/duplicate.rs
+tests/ui/async-await/issues/issue-60674.rs
+tests/ui/attributes/main-removed-2/main.rs
+tests/ui/cfg/assume-incomplete-release/assume-incomplete.rs
+tests/ui/crate-loading/cross-compiled-proc-macro.rs
+tests/ui/derives/derive-marker-tricky.rs
+tests/ui/diagnostic_namespace/existing_proc_macros.rs
+tests/ui/fmt/format-args-capture-issue-106408.rs
+tests/ui/fmt/indoc-issue-106408.rs
+tests/ui/hygiene/issue-77523-def-site-async-await.rs
+tests/ui/inherent-impls-overlap-check/no-overlap.rs
diff --git a/compiler/rustc_codegen_gcc/failing-non-lto-tests.txt b/compiler/rustc_codegen_gcc/failing-non-lto-tests.txt
new file mode 100644
index 00000000000..4fd60f2b8e4
--- /dev/null
+++ b/compiler/rustc_codegen_gcc/failing-non-lto-tests.txt
@@ -0,0 +1,11 @@
+tests/ui/issues/issue-44056.rs
+tests/ui/lto/fat-lto.rs
+tests/ui/lto/debuginfo-lto.rs
+tests/ui/lto/lto-many-codegen-units.rs
+tests/ui/lto/issue-100772.rs
+tests/ui/lto/lto-rustc-loads-linker-plugin.rs
+tests/ui/panic-runtime/lto-unwind.rs
+tests/ui/sanitize/issue-111184-coroutine-witness.rs
+tests/ui/sepcomp/sepcomp-lib-lto.rs
+tests/ui/lto/lto-opt-level-s.rs
+tests/ui/lto/lto-opt-level-z.rs
diff --git a/compiler/rustc_codegen_gcc/failing-ui-tests.txt b/compiler/rustc_codegen_gcc/failing-ui-tests.txt
index 801464daae9..22044eabe96 100644
--- a/compiler/rustc_codegen_gcc/failing-ui-tests.txt
+++ b/compiler/rustc_codegen_gcc/failing-ui-tests.txt
@@ -1,11 +1,5 @@
-tests/ui/allocator/custom-in-block.rs
-tests/ui/allocator/custom-in-submodule.rs
-tests/ui/allocator/custom.rs
-tests/ui/allocator/hygiene.rs
 tests/ui/allocator/no_std-alloc-error-handler-custom.rs
 tests/ui/allocator/no_std-alloc-error-handler-default.rs
-tests/ui/allocator/xcrate-use.rs
-tests/ui/allocator/xcrate-use2.rs
 tests/ui/asm/may_unwind.rs
 tests/ui/asm/x86_64/multiple-clobber-abi.rs
 tests/ui/debuginfo/debuginfo-emit-llvm-ir-and-split-debuginfo.rs
@@ -14,15 +8,12 @@ tests/ui/linkage-attr/linkage1.rs
 tests/ui/lto/dylib-works.rs
 tests/ui/numbers-arithmetic/saturating-float-casts.rs
 tests/ui/polymorphization/promoted-function.rs
-tests/ui/process/nofile-limit.rs
 tests/ui/sepcomp/sepcomp-cci.rs
 tests/ui/sepcomp/sepcomp-extern.rs
 tests/ui/sepcomp/sepcomp-fns-backwards.rs
 tests/ui/sepcomp/sepcomp-fns.rs
 tests/ui/sepcomp/sepcomp-statics.rs
 tests/ui/simd/intrinsic/generic-arithmetic-pass.rs
-tests/ui/sse2.rs
-tests/ui/target-feature/missing-plusminus.rs
 tests/ui/asm/x86_64/may_unwind.rs
 tests/ui/backtrace.rs
 tests/ui/catch-unwind-bang.rs
@@ -30,8 +21,8 @@ tests/ui/cfg/cfg-panic-abort.rs
 tests/ui/drop/dynamic-drop-async.rs
 tests/ui/drop/repeat-drop.rs
 tests/ui/fmt/format-args-capture.rs
-tests/ui/generator/panic-drops-resume.rs
-tests/ui/generator/panic-drops.rs
+tests/ui/coroutine/panic-drops-resume.rs
+tests/ui/coroutine/panic-drops.rs
 tests/ui/intrinsics/panic-uninitialized-zeroed.rs
 tests/ui/iterators/iter-sum-overflow-debug.rs
 tests/ui/iterators/iter-sum-overflow-overflow-checks.rs
@@ -54,17 +45,30 @@ tests/ui/issues/issue-40883.rs
 tests/ui/issues/issue-43853.rs
 tests/ui/issues/issue-47364.rs
 tests/ui/macros/rfc-2011-nicer-assert-messages/assert-without-captures-does-not-create-unnecessary-code.rs
-tests/ui/rfcs/rfc-2091-track-caller/std-panic-locations.rs
 tests/ui/rfcs/rfc-1857-stabilize-drop-order/drop-order.rs
+tests/ui/rfcs/rfc-2091-track-caller/std-panic-locations.rs
 tests/ui/simd/issue-17170.rs
 tests/ui/simd/issue-39720.rs
 tests/ui/simd/issue-89193.rs
 tests/ui/statics/issue-91050-1.rs
 tests/ui/statics/issue-91050-2.rs
 tests/ui/alloc-error/default-alloc-error-hook.rs
-tests/ui/generator/panic-safe.rs
+tests/ui/coroutine/panic-safe.rs
 tests/ui/issues/issue-14875.rs
 tests/ui/issues/issue-29948.rs
-tests/ui/panic-while-printing.rs
-tests/ui/enum-discriminant/get_discr.rs
 tests/ui/panics/nested_panic_caught.rs
+tests/ui/simd/intrinsic/generic-bswap-byte.rs
+tests/ui/const_prop/ice-issue-111353.rs
+tests/ui/process/println-with-broken-pipe.rs
+tests/ui/panic-runtime/lto-abort.rs
+tests/ui/lto/thin-lto-inlines2.rs
+tests/ui/lto/weak-works.rs
+tests/ui/lto/thin-lto-inlines.rs
+tests/ui/lto/thin-lto-global-allocator.rs
+tests/ui/lto/msvc-imp-present.rs
+tests/ui/lto/lto-thin-rustc-loads-linker-plugin.rs
+tests/ui/lto/all-crates.rs
+tests/ui/async-await/deep-futures-are-freeze.rs
+tests/ui/closures/capture-unsized-by-ref.rs
+tests/ui/coroutine/resume-after-return.rs
+tests/ui/macros/rfc-2011-nicer-assert-messages/all-expr-kinds.rs
diff --git a/compiler/rustc_codegen_gcc/failing-ui-tests12.txt b/compiler/rustc_codegen_gcc/failing-ui-tests12.txt
index 8c27bd8b8ca..f91aa925318 100644
--- a/compiler/rustc_codegen_gcc/failing-ui-tests12.txt
+++ b/compiler/rustc_codegen_gcc/failing-ui-tests12.txt
@@ -19,21 +19,22 @@ tests/ui/simd/intrinsic/generic-reduction-pass.rs
 tests/ui/simd/intrinsic/generic-select-pass.rs
 tests/ui/simd/intrinsic/inlining-issue67557-ice.rs
 tests/ui/simd/intrinsic/inlining-issue67557.rs
-tests/ui/simd/monomorphize-shuffle-index.rs
 tests/ui/simd/shuffle.rs
 tests/ui/simd/simd-bitmask.rs
-tests/ui/generator/resume-after-return.rs
 tests/ui/iterators/iter-step-overflow-debug.rs
-tests/ui/macros/rfc-2011-nicer-assert-messages/all-expr-kinds.rs
 tests/ui/numbers-arithmetic/next-power-of-two-overflow-debug.rs
 tests/ui/privacy/reachable-unnameable-items.rs
-tests/ui/rfc-1937-termination-trait/termination-trait-in-test.rs
+tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-in-test.rs
 tests/ui/async-await/async-fn-size-moved-locals.rs
 tests/ui/async-await/async-fn-size-uninit-locals.rs
 tests/ui/cfg/cfg-panic.rs
-tests/ui/generator/size-moved-locals.rs
+tests/ui/coroutine/size-moved-locals.rs
 tests/ui/macros/rfc-2011-nicer-assert-messages/all-not-available-cases.rs
 tests/ui/simd/intrinsic/generic-gather-pass.rs
 tests/ui/simd/issue-85915-simd-ptrs.rs
 tests/ui/issues/issue-68010-large-zst-consts.rs
 tests/ui/rust-2018/proc-macro-crate-in-paths.rs
+tests/ui/target-feature/missing-plusminus.rs
+tests/ui/sse2.rs
+tests/ui/codegen/issue-79865-llvm-miscompile.rs
+tests/ui/intrinsics/intrinsics-integer.rs
diff --git a/compiler/rustc_codegen_gcc/messages.ftl b/compiler/rustc_codegen_gcc/messages.ftl
index 2fd0daee3e7..5ca0a2e1b6d 100644
--- a/compiler/rustc_codegen_gcc/messages.ftl
+++ b/compiler/rustc_codegen_gcc/messages.ftl
@@ -1,3 +1,7 @@
+codegen_gcc_unknown_ctarget_feature_prefix =
+    unknown feature specified for `-Ctarget-feature`: `{$feature}`
+    .note = features must begin with a `+` to enable or `-` to disable it
+
 codegen_gcc_invalid_minimum_alignment =
     invalid minimum global alignment: {$err}
 
@@ -9,3 +13,29 @@ codegen_gcc_tied_target_features = the target features {$features} must all be e
 
 codegen_gcc_unwinding_inline_asm =
     GCC backend does not support unwinding from inline asm
+
+codegen_gcc_copy_bitcode = failed to copy bitcode to object file: {$err}
+
+codegen_gcc_dynamic_linking_with_lto =
+    cannot prefer dynamic linking when performing LTO
+    .note = only 'staticlib', 'bin', and 'cdylib' outputs are supported with LTO
+
+codegen_gcc_load_bitcode = failed to load bitcode of module "{$name}"
+
+codegen_gcc_lto_disallowed = lto can only be run for executables, cdylibs and static library outputs
+
+codegen_gcc_lto_dylib = lto cannot be used for `dylib` crate type without `-Zdylib-lto`
+
+codegen_gcc_lto_bitcode_from_rlib = failed to get bitcode from object file for LTO ({$gcc_err})
+
+codegen_gcc_unknown_ctarget_feature =
+    unknown feature specified for `-Ctarget-feature`: `{$feature}`
+    .note = it is still passed through to the codegen backend
+    .possible_feature = you might have meant: `{$rust_feature}`
+    .consider_filing_feature_request = consider filing a feature request
+
+codegen_gcc_missing_features =
+    add the missing features in a `target_feature` attribute
+
+codegen_gcc_target_feature_disable_or_enable =
+    the target features {$features} must all be either enabled or disabled together
diff --git a/compiler/rustc_codegen_gcc/patches/0001-Add-stdarch-Cargo.toml-for-testing.patch b/compiler/rustc_codegen_gcc/patches/0001-Add-stdarch-Cargo.toml-for-testing.patch
index 93c63b5dcac..2a55f2cb796 100644
--- a/compiler/rustc_codegen_gcc/patches/0001-Add-stdarch-Cargo.toml-for-testing.patch
+++ b/compiler/rustc_codegen_gcc/patches/0001-Add-stdarch-Cargo.toml-for-testing.patch
@@ -1,25 +1,26 @@
-From c3821e02fbd6cb5ad6e06d759fccdc9073712375 Mon Sep 17 00:00:00 2001
+From b8f3eed3053c9333b5dfbeaeb2a6a65a4b3156df Mon Sep 17 00:00:00 2001
 From: Antoni Boucher <bouanto@zoho.com>
-Date: Tue, 7 Jun 2022 21:40:13 -0400
-Subject: [PATCH] Add stdarch Cargo.toml for testing
+Date: Tue, 29 Aug 2023 13:06:34 -0400
+Subject: [PATCH] Patch 0001-Add-stdarch-Cargo.toml-for-testing.patch
 
 ---
- library/stdarch/Cargo.toml | 20 ++++++++++++++++++++
- 1 file changed, 20 insertions(+)
+ library/stdarch/Cargo.toml | 23 +++++++++++++++++++++++
+ 1 file changed, 23 insertions(+)
  create mode 100644 library/stdarch/Cargo.toml
 
 diff --git a/library/stdarch/Cargo.toml b/library/stdarch/Cargo.toml
 new file mode 100644
-index 0000000..fbe0a95
+index 0000000..4c63700
 --- /dev/null
 +++ b/library/stdarch/Cargo.toml
-@@ -0,0 +1,20 @@
+@@ -0,0 +1,21 @@
 +[workspace]
++resolver = "1"
 +members = [
 +  "crates/core_arch",
 +  "crates/std_detect",
 +  "crates/stdarch-gen",
-+  "examples/"
++  #"examples/"
 +]
 +exclude = [
 +  "crates/wasm-assert-instr-tests"
@@ -35,5 +36,5 @@ index 0000000..fbe0a95
 +opt-level = 3
 +incremental = true
 -- 
-2.26.2.7.g19db9cfb68.dirty
+2.42.0
 
diff --git a/compiler/rustc_codegen_gcc/patches/0001-Disable-examples.patch b/compiler/rustc_codegen_gcc/patches/0001-Disable-examples.patch
deleted file mode 100644
index 1b71df1ca8d..00000000000
--- a/compiler/rustc_codegen_gcc/patches/0001-Disable-examples.patch
+++ /dev/null
@@ -1,25 +0,0 @@
-From a2d53a324a02c04b76c0e9d39dc15cd443a3b8b2 Mon Sep 17 00:00:00 2001
-From: Antoni Boucher <bouanto@zoho.com>
-Date: Fri, 25 Nov 2022 11:18:11 -0500
-Subject: [PATCH] Disable examples
-
----
- library/stdarch/Cargo.toml | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/library/stdarch/Cargo.toml b/library/stdarch/Cargo.toml
-index fbe0a95..748d72d 100644
---- a/library/stdarch/Cargo.toml
-+++ b/library/stdarch/Cargo.toml
-@@ -3,7 +3,7 @@ members = [
-   "crates/core_arch",
-   "crates/std_detect",
-   "crates/stdarch-gen",
--  "examples/"
-+  #"examples/"
- ]
- exclude = [
-   "crates/wasm-assert-instr-tests"
--- 
-2.26.2.7.g19db9cfb68.dirty
-
diff --git a/compiler/rustc_codegen_gcc/patches/libgccjit12/0001-core-Disable-portable-simd-test.patch b/compiler/rustc_codegen_gcc/patches/libgccjit12/0001-core-Disable-portable-simd-test.patch
new file mode 100644
index 00000000000..9520a5a39ed
--- /dev/null
+++ b/compiler/rustc_codegen_gcc/patches/libgccjit12/0001-core-Disable-portable-simd-test.patch
@@ -0,0 +1,32 @@
+From 7bcd24ec6d4a96121874cb1ae5a23ea274aeff34 Mon Sep 17 00:00:00 2001
+From: None <none@example.com>
+Date: Thu, 19 Oct 2023 13:12:51 -0400
+Subject: [PATCH] [core] Disable portable-simd test
+
+---
+ library/core/tests/lib.rs | 2 --
+ 1 file changed, 2 deletions(-)
+
+diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs
+index 5814ed4..194ad4c 100644
+--- a/library/core/tests/lib.rs
++++ b/library/core/tests/lib.rs
+@@ -90,7 +90,6 @@
+ #![feature(unwrap_infallible)]
+ #![feature(pointer_byte_offsets)]
+ #![feature(pointer_is_aligned)]
+-#![feature(portable_simd)]
+ #![feature(ptr_metadata)]
+ #![feature(lazy_cell)]
+ #![feature(unsized_tuple_coercion)]
+@@ -157,7 +156,6 @@ mod pin;
+ mod pin_macro;
+ mod ptr;
+ mod result;
+-mod simd;
+ mod slice;
+ mod str;
+ mod str_lossy;
+-- 
+2.42.0
+
diff --git a/compiler/rustc_codegen_gcc/prepare.sh b/compiler/rustc_codegen_gcc/prepare.sh
deleted file mode 100755
index e98f24c6e12..00000000000
--- a/compiler/rustc_codegen_gcc/prepare.sh
+++ /dev/null
@@ -1,30 +0,0 @@
-#!/usr/bin/env bash
-set -e
-set -v
-
-source prepare_build.sh
-
-cargo install hyperfine || echo "Skipping hyperfine install"
-
-git clone https://github.com/rust-random/rand.git || echo "rust-random/rand has already been cloned"
-pushd rand
-git checkout -- .
-git checkout 0f933f9c7176e53b2a3c7952ded484e1783f0bf1
-git am ../crate_patches/*-rand-*.patch
-popd
-
-git clone https://github.com/rust-lang/regex.git || echo "rust-lang/regex has already been cloned"
-pushd regex
-git checkout -- .
-git checkout 341f207c1071f7290e3f228c710817c280c8dca1
-popd
-
-git clone https://github.com/ebobby/simple-raytracer || echo "ebobby/simple-raytracer has already been cloned"
-pushd simple-raytracer
-git checkout -- .
-git checkout 804a7a21b9e673a482797aa289a18ed480e4d813
-
-# build with cg_llvm for perf comparison
-cargo build
-mv target/debug/main raytracer_cg_llvm
-popd
diff --git a/compiler/rustc_codegen_gcc/prepare_build.sh b/compiler/rustc_codegen_gcc/prepare_build.sh
deleted file mode 100755
index 8194360da4b..00000000000
--- a/compiler/rustc_codegen_gcc/prepare_build.sh
+++ /dev/null
@@ -1,5 +0,0 @@
-#!/usr/bin/env bash
-set -e
-set -v
-
-./build_sysroot/prepare_sysroot_src.sh
diff --git a/compiler/rustc_codegen_gcc/rust-toolchain b/compiler/rustc_codegen_gcc/rust-toolchain
index ebb04d0069c..205ec53b425 100644
--- a/compiler/rustc_codegen_gcc/rust-toolchain
+++ b/compiler/rustc_codegen_gcc/rust-toolchain
@@ -1,3 +1,3 @@
 [toolchain]
-channel = "nightly-2023-06-19"
+channel = "nightly-2023-10-21"
 components = ["rust-src", "rustc-dev", "llvm-tools-preview"]
diff --git a/compiler/rustc_codegen_gcc/rustup.sh b/compiler/rustc_codegen_gcc/rustup.sh
index 041079bc9c6..a4f938e4b5b 100755
--- a/compiler/rustc_codegen_gcc/rustup.sh
+++ b/compiler/rustc_codegen_gcc/rustup.sh
@@ -16,7 +16,7 @@ case $1 in
         done
 
         ./clean_all.sh
-        ./prepare.sh
+        ./y.sh prepare
         ;;
     "commit")
         git add rust-toolchain
diff --git a/compiler/rustc_codegen_gcc/src/abi.rs b/compiler/rustc_codegen_gcc/src/abi.rs
index a49530ebb4c..f601cd95f2a 100644
--- a/compiler/rustc_codegen_gcc/src/abi.rs
+++ b/compiler/rustc_codegen_gcc/src/abi.rs
@@ -1,9 +1,13 @@
+#[cfg(feature = "master")]
+use gccjit::FnAttribute;
 use gccjit::{ToLValue, ToRValue, Type};
 use rustc_codegen_ssa::traits::{AbiBuilderMethods, BaseTypeMethods};
 use rustc_data_structures::fx::FxHashSet;
 use rustc_middle::bug;
 use rustc_middle::ty::Ty;
-use rustc_target::abi::call::{CastTarget, FnAbi, PassMode, Reg, RegKind};
+#[cfg(feature = "master")]
+use rustc_session::config;
+use rustc_target::abi::call::{ArgAttributes, CastTarget, FnAbi, PassMode, Reg, RegKind};
 
 use crate::builder::Builder;
 use crate::context::CodegenCx;
@@ -94,14 +98,23 @@ impl GccType for Reg {
     }
 }
 
+pub struct FnAbiGcc<'gcc> {
+    pub return_type: Type<'gcc>,
+    pub arguments_type: Vec<Type<'gcc>>,
+    pub is_c_variadic: bool,
+    pub on_stack_param_indices: FxHashSet<usize>,
+    #[cfg(feature = "master")]
+    pub fn_attributes: Vec<FnAttribute<'gcc>>,
+}
+
 pub trait FnAbiGccExt<'gcc, 'tcx> {
     // TODO(antoyo): return a function pointer type instead?
-    fn gcc_type(&self, cx: &CodegenCx<'gcc, 'tcx>) -> (Type<'gcc>, Vec<Type<'gcc>>, bool, FxHashSet<usize>);
+    fn gcc_type(&self, cx: &CodegenCx<'gcc, 'tcx>) -> FnAbiGcc<'gcc>;
     fn ptr_to_gcc_type(&self, cx: &CodegenCx<'gcc, 'tcx>) -> Type<'gcc>;
 }
 
 impl<'gcc, 'tcx> FnAbiGccExt<'gcc, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
-    fn gcc_type(&self, cx: &CodegenCx<'gcc, 'tcx>) -> (Type<'gcc>, Vec<Type<'gcc>>, bool, FxHashSet<usize>) {
+    fn gcc_type(&self, cx: &CodegenCx<'gcc, 'tcx>) -> FnAbiGcc<'gcc> {
         let mut on_stack_param_indices = FxHashSet::default();
 
         // This capacity calculation is approximate.
@@ -109,7 +122,7 @@ impl<'gcc, 'tcx> FnAbiGccExt<'gcc, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
             self.args.len() + if let PassMode::Indirect { .. } = self.ret.mode { 1 } else { 0 }
         );
 
-        let return_ty =
+        let return_type =
             match self.ret.mode {
                 PassMode::Ignore => cx.type_void(),
                 PassMode::Direct(_) | PassMode::Pair(..) => self.ret.layout.immediate_gcc_type(cx),
@@ -119,41 +132,89 @@ impl<'gcc, 'tcx> FnAbiGccExt<'gcc, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
                     cx.type_void()
                 }
             };
+        #[cfg(feature = "master")]
+        let mut non_null_args = Vec::new();
+
+        #[cfg(feature = "master")]
+        let mut apply_attrs = |mut ty: Type<'gcc>, attrs: &ArgAttributes, arg_index: usize| {
+            if cx.sess().opts.optimize == config::OptLevel::No {
+                return ty;
+            }
+            if attrs.regular.contains(rustc_target::abi::call::ArgAttribute::NoAlias) {
+                ty = ty.make_restrict()
+            }
+            if attrs.regular.contains(rustc_target::abi::call::ArgAttribute::NonNull) {
+                non_null_args.push(arg_index as i32 + 1);
+            }
+            ty
+        };
+        #[cfg(not(feature = "master"))]
+        let apply_attrs = |ty: Type<'gcc>, _attrs: &ArgAttributes, _arg_index: usize| {
+            ty
+        };
 
         for arg in self.args.iter() {
             let arg_ty = match arg.mode {
                 PassMode::Ignore => continue,
-                PassMode::Direct(_) => arg.layout.immediate_gcc_type(cx),
-                PassMode::Pair(..) => {
-                    argument_tys.push(arg.layout.scalar_pair_element_gcc_type(cx, 0));
-                    argument_tys.push(arg.layout.scalar_pair_element_gcc_type(cx, 1));
+                PassMode::Pair(a, b) => {
+                    let arg_pos = argument_tys.len();
+                    argument_tys.push(apply_attrs(arg.layout.scalar_pair_element_gcc_type(cx, 0), &a, arg_pos));
+                    argument_tys.push(apply_attrs(arg.layout.scalar_pair_element_gcc_type(cx, 1), &b, arg_pos + 1));
                     continue;
                 }
-                PassMode::Indirect { meta_attrs: Some(_), .. } => {
-                    unimplemented!();
-                }
                 PassMode::Cast { ref cast, pad_i32 } => {
                     // add padding
                     if pad_i32 {
                         argument_tys.push(Reg::i32().gcc_type(cx));
                     }
-                    cast.gcc_type(cx)
+                    let ty = cast.gcc_type(cx);
+                    apply_attrs(ty, &cast.attrs, argument_tys.len())
                 }
-                PassMode::Indirect { meta_attrs: None, on_stack: true, .. } => {
+                PassMode::Indirect { attrs: _, meta_attrs: None, on_stack: true } => {
+                    // This is a "byval" argument, so we don't apply the `restrict` attribute on it.
                     on_stack_param_indices.insert(argument_tys.len());
                     arg.memory_ty(cx)
                 },
-                PassMode::Indirect { meta_attrs: None, on_stack: false, .. } => cx.type_ptr_to(arg.memory_ty(cx)),
+                PassMode::Direct(attrs) => apply_attrs(arg.layout.immediate_gcc_type(cx), &attrs, argument_tys.len()),
+                PassMode::Indirect { attrs, meta_attrs: None, on_stack: false } => {
+                    apply_attrs(cx.type_ptr_to(arg.memory_ty(cx)), &attrs, argument_tys.len())
+                }
+                PassMode::Indirect { attrs, meta_attrs: Some(meta_attrs), on_stack } => {
+                    assert!(!on_stack);
+                    let ty = apply_attrs(cx.type_ptr_to(arg.memory_ty(cx)), &attrs, argument_tys.len());
+                    apply_attrs(ty, &meta_attrs, argument_tys.len())
+                }
             };
             argument_tys.push(arg_ty);
         }
 
-        (return_ty, argument_tys, self.c_variadic, on_stack_param_indices)
+        #[cfg(feature = "master")]
+        let fn_attrs = if non_null_args.is_empty() {
+            Vec::new()
+        } else {
+            vec![FnAttribute::NonNull(non_null_args)]
+        };
+
+        FnAbiGcc {
+            return_type,
+            arguments_type: argument_tys,
+            is_c_variadic: self.c_variadic,
+            on_stack_param_indices,
+            #[cfg(feature = "master")]
+            fn_attributes: fn_attrs,
+        }
     }
 
     fn ptr_to_gcc_type(&self, cx: &CodegenCx<'gcc, 'tcx>) -> Type<'gcc> {
-        let (return_type, params, variadic, on_stack_param_indices) = self.gcc_type(cx);
-        let pointer_type = cx.context.new_function_pointer_type(None, return_type, &params, variadic);
+        // FIXME(antoyo): Should we do something with `FnAbiGcc::fn_attributes`?
+        let FnAbiGcc {
+            return_type,
+            arguments_type,
+            is_c_variadic,
+            on_stack_param_indices,
+            ..
+        } = self.gcc_type(cx);
+        let pointer_type = cx.context.new_function_pointer_type(None, return_type, &arguments_type, is_c_variadic);
         cx.on_stack_params.borrow_mut().insert(pointer_type.dyncast_function_ptr_type().expect("function ptr type"), on_stack_param_indices);
         pointer_type
     }
diff --git a/compiler/rustc_codegen_gcc/src/allocator.rs b/compiler/rustc_codegen_gcc/src/allocator.rs
index edd7ab722f6..c8c098e2973 100644
--- a/compiler/rustc_codegen_gcc/src/allocator.rs
+++ b/compiler/rustc_codegen_gcc/src/allocator.rs
@@ -1,6 +1,6 @@
 #[cfg(feature="master")]
 use gccjit::FnAttribute;
-use gccjit::{FunctionType, GlobalKind, ToRValue};
+use gccjit::{Context, FunctionType, GlobalKind, ToRValue, Type};
 use rustc_ast::expand::allocator::{
     alloc_error_handler_name, default_fn_name, global_fn_name, AllocatorKind, AllocatorTy,
     ALLOCATOR_METHODS, NO_ALLOC_SHIM_IS_UNSTABLE,
@@ -22,7 +22,6 @@ pub(crate) unsafe fn codegen(tcx: TyCtxt<'_>, mods: &mut GccContext, _module_nam
         };
     let i8 = context.new_type::<i8>();
     let i8p = i8.make_pointer();
-    let void = context.new_type::<()>();
 
     if kind == AllocatorKind::Default {
         for method in ALLOCATOR_METHODS {
@@ -47,67 +46,62 @@ pub(crate) unsafe fn codegen(tcx: TyCtxt<'_>, mods: &mut GccContext, _module_nam
                     panic!("invalid allocator output")
                 }
             };
-            let name = global_fn_name(method.name);
+            let from_name = global_fn_name(method.name);
+            let to_name = default_fn_name(method.name);
 
-            let args: Vec<_> = types.iter().enumerate()
-                .map(|(index, typ)| context.new_parameter(None, *typ, &format!("param{}", index)))
-                .collect();
-            let func = context.new_function(None, FunctionType::Exported, output.unwrap_or(void), &args, name, false);
+            create_wrapper_function(tcx, context, &from_name, &to_name, &types, output);
+        }
+    }
 
-            if tcx.sess.target.options.default_hidden_visibility {
-                #[cfg(feature="master")]
-                func.add_attribute(FnAttribute::Visibility(gccjit::Visibility::Hidden));
-            }
-            if tcx.sess.must_emit_unwind_tables() {
-                // TODO(antoyo): emit unwind tables.
-            }
+    // FIXME(bjorn3): Add noreturn attribute
+    create_wrapper_function(
+        tcx,
+        context,
+        "__rust_alloc_error_handler",
+        &alloc_error_handler_name(alloc_error_handler_kind),
+        &[usize, usize],
+        None,
+    );
 
-            let callee = default_fn_name(method.name);
-            let args: Vec<_> = types.iter().enumerate()
-                .map(|(index, typ)| context.new_parameter(None, *typ, &format!("param{}", index)))
-                .collect();
-            let callee = context.new_function(None, FunctionType::Extern, output.unwrap_or(void), &args, callee, false);
-            #[cfg(feature="master")]
-            callee.add_attribute(FnAttribute::Visibility(gccjit::Visibility::Hidden));
-
-            let block = func.new_block("entry");
-
-            let args = args
-                .iter()
-                .enumerate()
-                .map(|(i, _)| func.get_param(i as i32).to_rvalue())
-                .collect::<Vec<_>>();
-            let ret = context.new_call(None, callee, &args);
-            //llvm::LLVMSetTailCall(ret, True);
-            if output.is_some() {
-                block.end_with_return(None, ret);
-            }
-            else {
-                block.end_with_void_return(None);
-            }
+    let name = OomStrategy::SYMBOL.to_string();
+    let global = context.new_global(None, GlobalKind::Exported, i8, name);
+    let value = tcx.sess.opts.unstable_opts.oom.should_panic();
+    let value = context.new_rvalue_from_int(i8, value as i32);
+    global.global_set_initializer_rvalue(value);
 
-            // TODO(@Commeownist): Check if we need to emit some extra debugging info in certain circumstances
-            // as described in https://github.com/rust-lang/rust/commit/77a96ed5646f7c3ee8897693decc4626fe380643
-        }
-    }
+    let name = NO_ALLOC_SHIM_IS_UNSTABLE.to_string();
+    let global = context.new_global(None, GlobalKind::Exported, i8, name);
+    let value = context.new_rvalue_from_int(i8, 0);
+    global.global_set_initializer_rvalue(value);
+}
+
+fn create_wrapper_function(
+    tcx: TyCtxt<'_>,
+    context: &Context<'_>,
+    from_name: &str,
+    to_name: &str,
+    types: &[Type<'_>],
+    output: Option<Type<'_>>,
+) {
+    let void = context.new_type::<()>();
 
-    let types = [usize, usize];
-    let name = "__rust_alloc_error_handler".to_string();
     let args: Vec<_> = types.iter().enumerate()
         .map(|(index, typ)| context.new_parameter(None, *typ, &format!("param{}", index)))
         .collect();
-    let func = context.new_function(None, FunctionType::Exported, void, &args, name, false);
+    let func = context.new_function(None, FunctionType::Exported, output.unwrap_or(void), &args, from_name, false);
 
-    if tcx.sess.target.default_hidden_visibility {
+    if tcx.sess.target.options.default_hidden_visibility {
         #[cfg(feature="master")]
         func.add_attribute(FnAttribute::Visibility(gccjit::Visibility::Hidden));
     }
+    if tcx.sess.must_emit_unwind_tables() {
+        // TODO(antoyo): emit unwind tables.
+    }
 
-    let callee = alloc_error_handler_name(alloc_error_handler_kind);
     let args: Vec<_> = types.iter().enumerate()
         .map(|(index, typ)| context.new_parameter(None, *typ, &format!("param{}", index)))
         .collect();
-    let callee = context.new_function(None, FunctionType::Extern, void, &args, callee, false);
+    let callee = context.new_function(None, FunctionType::Extern, output.unwrap_or(void), &args, to_name, false);
     #[cfg(feature="master")]
     callee.add_attribute(FnAttribute::Visibility(gccjit::Visibility::Hidden));
 
@@ -118,18 +112,15 @@ pub(crate) unsafe fn codegen(tcx: TyCtxt<'_>, mods: &mut GccContext, _module_nam
         .enumerate()
         .map(|(i, _)| func.get_param(i as i32).to_rvalue())
         .collect::<Vec<_>>();
-    let _ret = context.new_call(None, callee, &args);
+    let ret = context.new_call(None, callee, &args);
     //llvm::LLVMSetTailCall(ret, True);
-    block.end_with_void_return(None);
-
-    let name = OomStrategy::SYMBOL.to_string();
-    let global = context.new_global(None, GlobalKind::Exported, i8, name);
-    let value = tcx.sess.opts.unstable_opts.oom.should_panic();
-    let value = context.new_rvalue_from_int(i8, value as i32);
-    global.global_set_initializer_rvalue(value);
+    if output.is_some() {
+        block.end_with_return(None, ret);
+    }
+    else {
+        block.end_with_void_return(None);
+    }
 
-    let name = NO_ALLOC_SHIM_IS_UNSTABLE.to_string();
-    let global = context.new_global(None, GlobalKind::Exported, i8, name);
-    let value = context.new_rvalue_from_int(i8, 0);
-    global.global_set_initializer_rvalue(value);
+    // TODO(@Commeownist): Check if we need to emit some extra debugging info in certain circumstances
+    // as described in https://github.com/rust-lang/rust/commit/77a96ed5646f7c3ee8897693decc4626fe380643
 }
diff --git a/compiler/rustc_codegen_gcc/src/asm.rs b/compiler/rustc_codegen_gcc/src/asm.rs
index 905fdac92e9..f3a9ca77a67 100644
--- a/compiler/rustc_codegen_gcc/src/asm.rs
+++ b/compiler/rustc_codegen_gcc/src/asm.rs
@@ -452,10 +452,6 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
                         }
 
                         InlineAsmOperandRef::Const { ref string } => {
-                            // Const operands get injected directly into the template
-                            if att_dialect {
-                                template_str.push('$');
-                            }
                             template_str.push_str(string);
                         }
                     }
diff --git a/compiler/rustc_codegen_gcc/src/attributes.rs b/compiler/rustc_codegen_gcc/src/attributes.rs
index eb0cce19b85..6159971cfaa 100644
--- a/compiler/rustc_codegen_gcc/src/attributes.rs
+++ b/compiler/rustc_codegen_gcc/src/attributes.rs
@@ -4,72 +4,13 @@ use gccjit::Function;
 use rustc_attr::InstructionSetAttr;
 #[cfg(feature="master")]
 use rustc_attr::InlineAttr;
-use rustc_codegen_ssa::target_features::tied_target_features;
-use rustc_data_structures::fx::FxHashMap;
 use rustc_middle::ty;
 #[cfg(feature="master")]
 use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
-use rustc_session::Session;
 use rustc_span::symbol::sym;
-use smallvec::{smallvec, SmallVec};
 
 use crate::{context::CodegenCx, errors::TiedTargetFeatures};
-
-// Given a map from target_features to whether they are enabled or disabled,
-// ensure only valid combinations are allowed.
-pub fn check_tied_features(sess: &Session, features: &FxHashMap<&str, bool>) -> Option<&'static [&'static str]> {
-    for tied in tied_target_features(sess) {
-        // Tied features must be set to the same value, or not set at all
-        let mut tied_iter = tied.iter();
-        let enabled = features.get(tied_iter.next().unwrap());
-        if tied_iter.any(|feature| enabled != features.get(feature)) {
-            return Some(tied);
-        }
-    }
-    None
-}
-
-// TODO(antoyo): maybe move to a new module gcc_util.
-// To find a list of GCC's names, check https://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html
-fn to_gcc_features<'a>(sess: &Session, s: &'a str) -> SmallVec<[&'a str; 2]> {
-    let arch = if sess.target.arch == "x86_64" { "x86" } else { &*sess.target.arch };
-    match (arch, s) {
-        ("x86", "sse4.2") => smallvec!["sse4.2", "crc32"],
-        ("x86", "pclmulqdq") => smallvec!["pclmul"],
-        ("x86", "rdrand") => smallvec!["rdrnd"],
-        ("x86", "bmi1") => smallvec!["bmi"],
-        ("x86", "cmpxchg16b") => smallvec!["cx16"],
-        ("x86", "avx512vaes") => smallvec!["vaes"],
-        ("x86", "avx512gfni") => smallvec!["gfni"],
-        ("x86", "avx512vpclmulqdq") => smallvec!["vpclmulqdq"],
-        // NOTE: seems like GCC requires 'avx512bw' for 'avx512vbmi2'.
-        ("x86", "avx512vbmi2") => smallvec!["avx512vbmi2", "avx512bw"],
-        // NOTE: seems like GCC requires 'avx512bw' for 'avx512bitalg'.
-        ("x86", "avx512bitalg") => smallvec!["avx512bitalg", "avx512bw"],
-        ("aarch64", "rcpc2") => smallvec!["rcpc-immo"],
-        ("aarch64", "dpb") => smallvec!["ccpp"],
-        ("aarch64", "dpb2") => smallvec!["ccdp"],
-        ("aarch64", "frintts") => smallvec!["fptoint"],
-        ("aarch64", "fcma") => smallvec!["complxnum"],
-        ("aarch64", "pmuv3") => smallvec!["perfmon"],
-        ("aarch64", "paca") => smallvec!["pauth"],
-        ("aarch64", "pacg") => smallvec!["pauth"],
-        // Rust ties fp and neon together. In LLVM neon implicitly enables fp,
-        // but we manually enable neon when a feature only implicitly enables fp
-        ("aarch64", "f32mm") => smallvec!["f32mm", "neon"],
-        ("aarch64", "f64mm") => smallvec!["f64mm", "neon"],
-        ("aarch64", "fhm") => smallvec!["fp16fml", "neon"],
-        ("aarch64", "fp16") => smallvec!["fullfp16", "neon"],
-        ("aarch64", "jsconv") => smallvec!["jsconv", "neon"],
-        ("aarch64", "sve") => smallvec!["sve", "neon"],
-        ("aarch64", "sve2") => smallvec!["sve2", "neon"],
-        ("aarch64", "sve2-aes") => smallvec!["sve2-aes", "neon"],
-        ("aarch64", "sve2-sm4") => smallvec!["sve2-sm4", "neon"],
-        ("aarch64", "sve2-sha3") => smallvec!["sve2-sha3", "neon"],
-        ("aarch64", "sve2-bitperm") => smallvec!["sve2-bitperm", "neon"],
-        (_, s) => smallvec![s],
-    }
-}
+use crate::gcc_util::{check_tied_features, to_gcc_features};
 
 /// Get GCC attribute for the provided inline heuristic.
 #[cfg(feature="master")]
@@ -112,8 +53,24 @@ pub fn from_fn_attrs<'gcc, 'tcx>(
                 codegen_fn_attrs.inline
             };
         if let Some(attr) = inline_attr(cx, inline) {
+            if let FnAttribute::AlwaysInline = attr {
+                func.add_attribute(FnAttribute::Inline);
+            }
             func.add_attribute(attr);
         }
+
+        if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::COLD) {
+            func.add_attribute(FnAttribute::Cold);
+        }
+        if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::FFI_RETURNS_TWICE) {
+            func.add_attribute(FnAttribute::ReturnsTwice);
+        }
+        if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::FFI_PURE) {
+            func.add_attribute(FnAttribute::Pure);
+        }
+        if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::FFI_CONST) {
+            func.add_attribute(FnAttribute::Const);
+        }
     }
 
     let function_features =
@@ -140,11 +97,33 @@ pub fn from_fn_attrs<'gcc, 'tcx>(
         }))
         .collect::<Vec<_>>();
 
-    // TODO(antoyo): check if we really need global backend features. (Maybe they could be applied
-    // globally?)
+    // TODO(antoyo): cg_llvm adds global features to each function so that LTO keep them.
+    // Check if GCC requires the same.
     let mut global_features = cx.tcx.global_backend_features(()).iter().map(|s| s.as_str());
     function_features.extend(&mut global_features);
-    let target_features = function_features.join(",");
+    let target_features = function_features
+        .iter()
+        .filter_map(|feature| {
+            // FIXME(antoyo): for some reasons, disabling SSE results in the following error when
+            // compiling Rust for Linux:
+            // SSE register return with SSE disabled
+            // TODO(antoyo): support soft-float and retpoline-external-thunk.
+            if feature.contains("soft-float") || feature.contains("retpoline-external-thunk") || *feature == "-sse" {
+                return None;
+            }
+
+            if feature.starts_with('-') {
+                Some(format!("no{}", feature))
+            }
+            else if feature.starts_with('+') {
+                Some(feature[1..].to_string())
+            }
+            else {
+                Some(feature.to_string())
+            }
+        })
+        .collect::<Vec<_>>()
+        .join(",");
     if !target_features.is_empty() {
         #[cfg(feature="master")]
         func.add_attribute(FnAttribute::Target(&target_features));
diff --git a/compiler/rustc_codegen_gcc/src/back/lto.rs b/compiler/rustc_codegen_gcc/src/back/lto.rs
new file mode 100644
index 00000000000..529454b119e
--- /dev/null
+++ b/compiler/rustc_codegen_gcc/src/back/lto.rs
@@ -0,0 +1,341 @@
+/// GCC requires to use the same toolchain for the whole compilation when doing LTO.
+/// So, we need the same version/commit of the linker (gcc) and lto front-end binaries (lto1,
+/// lto-wrapper, liblto_plugin.so).
+
+// FIXME(antoyo): the executables compiled with LTO are bigger than those compiled without LTO.
+// Since it is the opposite for cg_llvm, check if this is normal.
+//
+// Maybe we embed the bitcode in the final binary?
+// It doesn't look like we try to generate fat objects for the final binary.
+// Check if the way we combine the object files make it keep the LTO sections on the final link.
+// Maybe that's because the combined object files contain the IR (true) and the final link
+// does not remove it?
+//
+// TODO(antoyo): for performance, check which optimizations the C++ frontend enables.
+//
+// Fix these warnings:
+// /usr/bin/ld: warning: type of symbol `_RNvNvNvNtCs5JWOrf9uCus_5rayon11thread_pool19WORKER_THREAD_STATE7___getit5___KEY' changed from 1 to 6 in /tmp/ccKeUSiR.ltrans0.ltrans.o
+// /usr/bin/ld: warning: type of symbol `_RNvNvNvNvNtNtNtCsAj5i4SGTR7_3std4sync4mpmc5waker17current_thread_id5DUMMY7___getit5___KEY' changed from 1 to 6 in /tmp/ccKeUSiR.ltrans0.ltrans.o
+// /usr/bin/ld: warning: incremental linking of LTO and non-LTO objects; using -flinker-output=nolto-rel which will bypass whole program optimization
+
+use std::ffi::CString;
+use std::fs::{self, File};
+use std::path::{Path, PathBuf};
+
+use gccjit::OutputKind;
+use object::read::archive::ArchiveFile;
+use rustc_codegen_ssa::back::lto::{LtoModuleCodegen, SerializedModule};
+use rustc_codegen_ssa::back::symbol_export;
+use rustc_codegen_ssa::back::write::{CodegenContext, FatLtoInput};
+use rustc_codegen_ssa::traits::*;
+use rustc_codegen_ssa::{looks_like_rust_object_file, ModuleCodegen, ModuleKind};
+use rustc_data_structures::memmap::Mmap;
+use rustc_errors::{FatalError, Handler};
+use rustc_hir::def_id::LOCAL_CRATE;
+use rustc_middle::dep_graph::WorkProduct;
+use rustc_middle::middle::exported_symbols::{SymbolExportInfo, SymbolExportLevel};
+use rustc_session::config::{CrateType, Lto};
+use tempfile::{TempDir, tempdir};
+
+use crate::back::write::save_temp_bitcode;
+use crate::errors::{
+    DynamicLinkingWithLTO, LtoBitcodeFromRlib, LtoDisallowed, LtoDylib,
+};
+use crate::{GccCodegenBackend, GccContext, to_gcc_opt_level};
+
+/// We keep track of the computed LTO cache keys from the previous
+/// session to determine which CGUs we can reuse.
+//pub const THIN_LTO_KEYS_INCR_COMP_FILE_NAME: &str = "thin-lto-past-keys.bin";
+
+pub fn crate_type_allows_lto(crate_type: CrateType) -> bool {
+    match crate_type {
+        CrateType::Executable | CrateType::Dylib | CrateType::Staticlib | CrateType::Cdylib => true,
+        CrateType::Rlib | CrateType::ProcMacro => false,
+    }
+}
+
+struct LtoData {
+    // TODO(antoyo): use symbols_below_threshold.
+    //symbols_below_threshold: Vec<CString>,
+    upstream_modules: Vec<(SerializedModule<ModuleBuffer>, CString)>,
+    tmp_path: TempDir,
+}
+
+fn prepare_lto(cgcx: &CodegenContext<GccCodegenBackend>, diag_handler: &Handler) -> Result<LtoData, FatalError> {
+    let export_threshold = match cgcx.lto {
+        // We're just doing LTO for our one crate
+        Lto::ThinLocal => SymbolExportLevel::Rust,
+
+        // We're doing LTO for the entire crate graph
+        Lto::Fat | Lto::Thin => symbol_export::crates_export_threshold(&cgcx.crate_types),
+
+        Lto::No => panic!("didn't request LTO but we're doing LTO"),
+    };
+
+    let tmp_path =
+        match tempdir() {
+            Ok(tmp_path) => tmp_path,
+            Err(error) => {
+                eprintln!("Cannot create temporary directory: {}", error);
+                return Err(FatalError);
+            },
+        };
+
+    let symbol_filter = &|&(ref name, info): &(String, SymbolExportInfo)| {
+        if info.level.is_below_threshold(export_threshold) || info.used {
+            Some(CString::new(name.as_str()).unwrap())
+        } else {
+            None
+        }
+    };
+    let exported_symbols = cgcx.exported_symbols.as_ref().expect("needs exported symbols for LTO");
+    let mut symbols_below_threshold = {
+        let _timer = cgcx.prof.generic_activity("GCC_lto_generate_symbols_below_threshold");
+        exported_symbols[&LOCAL_CRATE].iter().filter_map(symbol_filter).collect::<Vec<CString>>()
+    };
+    info!("{} symbols to preserve in this crate", symbols_below_threshold.len());
+
+    // If we're performing LTO for the entire crate graph, then for each of our
+    // upstream dependencies, find the corresponding rlib and load the bitcode
+    // from the archive.
+    //
+    // We save off all the bytecode and GCC module file path for later processing
+    // with either fat or thin LTO
+    let mut upstream_modules = Vec::new();
+    if cgcx.lto != Lto::ThinLocal {
+        // Make sure we actually can run LTO
+        for crate_type in cgcx.crate_types.iter() {
+            if !crate_type_allows_lto(*crate_type) {
+                diag_handler.emit_err(LtoDisallowed);
+                return Err(FatalError);
+            } else if *crate_type == CrateType::Dylib {
+                if !cgcx.opts.unstable_opts.dylib_lto {
+                    diag_handler.emit_err(LtoDylib);
+                    return Err(FatalError);
+                }
+            }
+        }
+
+        if cgcx.opts.cg.prefer_dynamic && !cgcx.opts.unstable_opts.dylib_lto {
+            diag_handler.emit_err(DynamicLinkingWithLTO);
+            return Err(FatalError);
+        }
+
+        for &(cnum, ref path) in cgcx.each_linked_rlib_for_lto.iter() {
+            let exported_symbols =
+                cgcx.exported_symbols.as_ref().expect("needs exported symbols for LTO");
+            {
+                let _timer =
+                    cgcx.prof.generic_activity("GCC_lto_generate_symbols_below_threshold");
+                symbols_below_threshold
+                    .extend(exported_symbols[&cnum].iter().filter_map(symbol_filter));
+            }
+
+            let archive_data = unsafe {
+                Mmap::map(File::open(&path).expect("couldn't open rlib"))
+                    .expect("couldn't map rlib")
+            };
+            let archive = ArchiveFile::parse(&*archive_data).expect("wanted an rlib");
+            let obj_files = archive
+                .members()
+                .filter_map(|child| {
+                    child.ok().and_then(|c| {
+                        std::str::from_utf8(c.name()).ok().map(|name| (name.trim(), c))
+                    })
+                })
+                .filter(|&(name, _)| looks_like_rust_object_file(name));
+            for (name, child) in obj_files {
+                info!("adding bitcode from {}", name);
+                let path = tmp_path.path().join(name);
+                match save_as_file(child.data(&*archive_data).expect("corrupt rlib"), &path) {
+                    Ok(()) => {
+                        let buffer = ModuleBuffer::new(path);
+                        let module = SerializedModule::Local(buffer);
+                        upstream_modules.push((module, CString::new(name).unwrap()));
+                    }
+                    Err(e) => {
+                        diag_handler.emit_err(e);
+                        return Err(FatalError);
+                    }
+                }
+            }
+        }
+    }
+
+    Ok(LtoData {
+        //symbols_below_threshold,
+        upstream_modules,
+        tmp_path,
+    })
+}
+
+fn save_as_file(obj: &[u8], path: &Path) -> Result<(), LtoBitcodeFromRlib> {
+    fs::write(path, obj)
+        .map_err(|error| LtoBitcodeFromRlib {
+            gcc_err: format!("write object file to temp dir: {}", error)
+        })
+}
+
+/// Performs fat LTO by merging all modules into a single one and returning it
+/// for further optimization.
+pub(crate) fn run_fat(
+    cgcx: &CodegenContext<GccCodegenBackend>,
+    modules: Vec<FatLtoInput<GccCodegenBackend>>,
+    cached_modules: Vec<(SerializedModule<ModuleBuffer>, WorkProduct)>,
+) -> Result<LtoModuleCodegen<GccCodegenBackend>, FatalError> {
+    let diag_handler = cgcx.create_diag_handler();
+    let lto_data = prepare_lto(cgcx, &diag_handler)?;
+    /*let symbols_below_threshold =
+        lto_data.symbols_below_threshold.iter().map(|c| c.as_ptr()).collect::<Vec<_>>();*/
+    fat_lto(cgcx, &diag_handler, modules, cached_modules, lto_data.upstream_modules, lto_data.tmp_path,
+        //&symbols_below_threshold,
+    )
+}
+
+fn fat_lto(cgcx: &CodegenContext<GccCodegenBackend>, _diag_handler: &Handler, modules: Vec<FatLtoInput<GccCodegenBackend>>, cached_modules: Vec<(SerializedModule<ModuleBuffer>, WorkProduct)>, mut serialized_modules: Vec<(SerializedModule<ModuleBuffer>, CString)>, tmp_path: TempDir,
+    //symbols_below_threshold: &[*const libc::c_char],
+) -> Result<LtoModuleCodegen<GccCodegenBackend>, FatalError> {
+    let _timer = cgcx.prof.generic_activity("GCC_fat_lto_build_monolithic_module");
+    info!("going for a fat lto");
+
+    // Sort out all our lists of incoming modules into two lists.
+    //
+    // * `serialized_modules` (also and argument to this function) contains all
+    //   modules that are serialized in-memory.
+    // * `in_memory` contains modules which are already parsed and in-memory,
+    //   such as from multi-CGU builds.
+    //
+    // All of `cached_modules` (cached from previous incremental builds) can
+    // immediately go onto the `serialized_modules` modules list and then we can
+    // split the `modules` array into these two lists.
+    let mut in_memory = Vec::new();
+    serialized_modules.extend(cached_modules.into_iter().map(|(buffer, wp)| {
+        info!("pushing cached module {:?}", wp.cgu_name);
+        (buffer, CString::new(wp.cgu_name).unwrap())
+    }));
+    for module in modules {
+        match module {
+            FatLtoInput::InMemory(m) => in_memory.push(m),
+            FatLtoInput::Serialized { name, buffer } => {
+                info!("pushing serialized module {:?}", name);
+                let buffer = SerializedModule::Local(buffer);
+                serialized_modules.push((buffer, CString::new(name).unwrap()));
+            }
+        }
+    }
+
+    // Find the "costliest" module and merge everything into that codegen unit.
+    // All the other modules will be serialized and reparsed into the new
+    // context, so this hopefully avoids serializing and parsing the largest
+    // codegen unit.
+    //
+    // Additionally use a regular module as the base here to ensure that various
+    // file copy operations in the backend work correctly. The only other kind
+    // of module here should be an allocator one, and if your crate is smaller
+    // than the allocator module then the size doesn't really matter anyway.
+    let costliest_module = in_memory
+        .iter()
+        .enumerate()
+        .filter(|&(_, module)| module.kind == ModuleKind::Regular)
+        .map(|(i, _module)| {
+            //let cost = unsafe { llvm::LLVMRustModuleCost(module.module_llvm.llmod()) };
+            // TODO(antoyo): compute the cost of a module if GCC allows this.
+            (0, i)
+        })
+        .max();
+
+    // If we found a costliest module, we're good to go. Otherwise all our
+    // inputs were serialized which could happen in the case, for example, that
+    // all our inputs were incrementally reread from the cache and we're just
+    // re-executing the LTO passes. If that's the case deserialize the first
+    // module and create a linker with it.
+    let mut module: ModuleCodegen<GccContext> = match costliest_module {
+        Some((_cost, i)) => in_memory.remove(i),
+        None => {
+            unimplemented!("Incremental");
+            /*assert!(!serialized_modules.is_empty(), "must have at least one serialized module");
+            let (buffer, name) = serialized_modules.remove(0);
+            info!("no in-memory regular modules to choose from, parsing {:?}", name);
+            ModuleCodegen {
+                module_llvm: GccContext::parse(cgcx, &name, buffer.data(), diag_handler)?,
+                name: name.into_string().unwrap(),
+                kind: ModuleKind::Regular,
+            }*/
+        }
+    };
+    let mut serialized_bitcode = Vec::new();
+    {
+        info!("using {:?} as a base module", module.name);
+
+        // We cannot load and merge GCC contexts in memory like cg_llvm is doing.
+        // Instead, we combine the object files into a single object file.
+        for module in in_memory {
+            let path = tmp_path.path().to_path_buf().join(&module.name);
+            let path = path.to_str().expect("path");
+            let context = &module.module_llvm.context;
+            let config = cgcx.config(module.kind);
+            // NOTE: we need to set the optimization level here in order for LTO to do its job.
+            context.set_optimization_level(to_gcc_opt_level(config.opt_level));
+            context.add_command_line_option("-flto=auto");
+            context.add_command_line_option("-flto-partition=one");
+            context.compile_to_file(OutputKind::ObjectFile, path);
+            let buffer = ModuleBuffer::new(PathBuf::from(path));
+            let llmod_id = CString::new(&module.name[..]).unwrap();
+            serialized_modules.push((SerializedModule::Local(buffer), llmod_id));
+        }
+        // Sort the modules to ensure we produce deterministic results.
+        serialized_modules.sort_by(|module1, module2| module1.1.cmp(&module2.1));
+
+        // We add the object files and save in should_combine_object_files that we should combine
+        // them into a single object file when compiling later.
+        for (bc_decoded, name) in serialized_modules {
+            let _timer = cgcx
+                .prof
+                .generic_activity_with_arg_recorder("GCC_fat_lto_link_module", |recorder| {
+                    recorder.record_arg(format!("{:?}", name))
+                });
+            info!("linking {:?}", name);
+            match bc_decoded {
+                SerializedModule::Local(ref module_buffer) => {
+                    module.module_llvm.should_combine_object_files = true;
+                    module.module_llvm.context.add_driver_option(module_buffer.0.to_str().expect("path"));
+                },
+                SerializedModule::FromRlib(_) => unimplemented!("from rlib"),
+                SerializedModule::FromUncompressedFile(_) => unimplemented!("from uncompressed file"),
+            }
+            serialized_bitcode.push(bc_decoded);
+        }
+        save_temp_bitcode(cgcx, &module, "lto.input");
+
+        // Internalize everything below threshold to help strip out more modules and such.
+        /*unsafe {
+            let ptr = symbols_below_threshold.as_ptr();
+            llvm::LLVMRustRunRestrictionPass(
+                llmod,
+                ptr as *const *const libc::c_char,
+                symbols_below_threshold.len() as libc::size_t,
+            );*/
+            save_temp_bitcode(cgcx, &module, "lto.after-restriction");
+        //}
+    }
+
+    // NOTE: save the temporary directory used by LTO so that it gets deleted after linking instead
+    // of now.
+    module.module_llvm.temp_dir = Some(tmp_path);
+
+    Ok(LtoModuleCodegen::Fat { module, _serialized_bitcode: serialized_bitcode })
+}
+
+pub struct ModuleBuffer(PathBuf);
+
+impl ModuleBuffer {
+    pub fn new(path: PathBuf) -> ModuleBuffer {
+        ModuleBuffer(path)
+    }
+}
+
+impl ModuleBufferMethods for ModuleBuffer {
+    fn data(&self) -> &[u8] {
+        unimplemented!("data not needed for GCC codegen");
+    }
+}
diff --git a/compiler/rustc_codegen_gcc/src/back/mod.rs b/compiler/rustc_codegen_gcc/src/back/mod.rs
index d692799d764..10187eab0d7 100644
--- a/compiler/rustc_codegen_gcc/src/back/mod.rs
+++ b/compiler/rustc_codegen_gcc/src/back/mod.rs
@@ -1 +1,2 @@
+pub mod lto;
 pub mod write;
diff --git a/compiler/rustc_codegen_gcc/src/back/write.rs b/compiler/rustc_codegen_gcc/src/back/write.rs
index 5f54ac4ebc6..04772d7707a 100644
--- a/compiler/rustc_codegen_gcc/src/back/write.rs
+++ b/compiler/rustc_codegen_gcc/src/back/write.rs
@@ -2,27 +2,71 @@ use std::{env, fs};
 
 use gccjit::OutputKind;
 use rustc_codegen_ssa::{CompiledModule, ModuleCodegen};
-use rustc_codegen_ssa::back::write::{CodegenContext, EmitObj, ModuleConfig};
+use rustc_codegen_ssa::back::link::ensure_removed;
+use rustc_codegen_ssa::back::write::{BitcodeSection, CodegenContext, EmitObj, ModuleConfig};
 use rustc_errors::Handler;
+use rustc_fs_util::link_or_copy;
 use rustc_session::config::OutputType;
 use rustc_span::fatal_error::FatalError;
 use rustc_target::spec::SplitDebuginfo;
 
 use crate::{GccCodegenBackend, GccContext};
+use crate::errors::CopyBitcode;
 
-pub(crate) unsafe fn codegen(cgcx: &CodegenContext<GccCodegenBackend>, _diag_handler: &Handler, module: ModuleCodegen<GccContext>, config: &ModuleConfig) -> Result<CompiledModule, FatalError> {
-    let _timer = cgcx.prof.generic_activity_with_arg("LLVM_module_codegen", &*module.name);
+pub(crate) unsafe fn codegen(cgcx: &CodegenContext<GccCodegenBackend>, diag_handler: &Handler, module: ModuleCodegen<GccContext>, config: &ModuleConfig) -> Result<CompiledModule, FatalError> {
+    let _timer = cgcx.prof.generic_activity_with_arg("GCC_module_codegen", &*module.name);
     {
         let context = &module.module_llvm.context;
 
         let module_name = module.name.clone();
+
+        let should_combine_object_files = module.module_llvm.should_combine_object_files;
+
         let module_name = Some(&module_name[..]);
 
-        let _bc_out = cgcx.output_filenames.temp_path(OutputType::Bitcode, module_name);
+        // NOTE: Only generate object files with GIMPLE when this environment variable is set for
+        // now because this requires a particular setup (same gcc/lto1/lto-wrapper commit as libgccjit).
+        let fat_lto = env::var("EMBED_LTO_BITCODE").as_deref() == Ok("1");
+
+        let bc_out = cgcx.output_filenames.temp_path(OutputType::Bitcode, module_name);
         let obj_out = cgcx.output_filenames.temp_path(OutputType::Object, module_name);
 
-        if config.bitcode_needed() {
+        if config.bitcode_needed() && fat_lto {
+            let _timer = cgcx
+                .prof
+                .generic_activity_with_arg("GCC_module_codegen_make_bitcode", &*module.name);
+
             // TODO(antoyo)
+            /*if let Some(bitcode_filename) = bc_out.file_name() {
+                cgcx.prof.artifact_size(
+                    "llvm_bitcode",
+                    bitcode_filename.to_string_lossy(),
+                    data.len() as u64,
+                );
+            }*/
+
+            if config.emit_bc || config.emit_obj == EmitObj::Bitcode {
+                let _timer = cgcx
+                    .prof
+                    .generic_activity_with_arg("GCC_module_codegen_emit_bitcode", &*module.name);
+                context.add_command_line_option("-flto=auto");
+                context.add_command_line_option("-flto-partition=one");
+                context.compile_to_file(OutputKind::ObjectFile, bc_out.to_str().expect("path to str"));
+            }
+
+            if config.emit_obj == EmitObj::ObjectCode(BitcodeSection::Full) {
+                let _timer = cgcx
+                    .prof
+                    .generic_activity_with_arg("GCC_module_codegen_embed_bitcode", &*module.name);
+                // TODO(antoyo): maybe we should call embed_bitcode to have the proper iOS fixes?
+                //embed_bitcode(cgcx, llcx, llmod, &config.bc_cmdline, data);
+
+                context.add_command_line_option("-flto=auto");
+                context.add_command_line_option("-flto-partition=one");
+                context.add_command_line_option("-ffat-lto-objects");
+                // TODO(antoyo): Send -plugin/usr/lib/gcc/x86_64-pc-linux-gnu/11.1.0/liblto_plugin.so to linker (this should be done when specifying the appropriate rustc cli argument).
+                context.compile_to_file(OutputKind::ObjectFile, bc_out.to_str().expect("path to str"));
+            }
         }
 
         if config.emit_ir {
@@ -32,7 +76,7 @@ pub(crate) unsafe fn codegen(cgcx: &CodegenContext<GccCodegenBackend>, _diag_han
         if config.emit_asm {
             let _timer = cgcx
                 .prof
-                .generic_activity_with_arg("LLVM_module_codegen_emit_asm", &*module.name);
+                .generic_activity_with_arg("GCC_module_codegen_emit_asm", &*module.name);
             let path = cgcx.output_filenames.temp_path(OutputType::Assembly, module_name);
             context.compile_to_file(OutputKind::Assembler, path.to_str().expect("path to str"));
         }
@@ -41,7 +85,7 @@ pub(crate) unsafe fn codegen(cgcx: &CodegenContext<GccCodegenBackend>, _diag_han
             EmitObj::ObjectCode(_) => {
                 let _timer = cgcx
                     .prof
-                    .generic_activity_with_arg("LLVM_module_codegen_emit_obj", &*module.name);
+                    .generic_activity_with_arg("GCC_module_codegen_emit_obj", &*module.name);
                 if env::var("CG_GCCJIT_DUMP_MODULE_NAMES").as_deref() == Ok("1") {
                     println!("Module {}", module.name);
                 }
@@ -60,11 +104,36 @@ pub(crate) unsafe fn codegen(cgcx: &CodegenContext<GccCodegenBackend>, _diag_han
                     context.set_debug_info(true);
                     context.dump_to_file(path, true);
                 }
-                context.compile_to_file(OutputKind::ObjectFile, obj_out.to_str().expect("path to str"));
+                if should_combine_object_files && fat_lto {
+                    context.add_command_line_option("-flto=auto");
+                    context.add_command_line_option("-flto-partition=one");
+
+                    context.add_driver_option("-Wl,-r");
+                    // NOTE: we need -nostdlib, otherwise, we get the following error:
+                    // /usr/bin/ld: cannot find -lgcc_s: No such file or directory
+                    context.add_driver_option("-nostdlib");
+                    // NOTE: without -fuse-linker-plugin, we get the following error:
+                    // lto1: internal compiler error: decompressed stream: Destination buffer is too small
+                    context.add_driver_option("-fuse-linker-plugin");
+
+                    // NOTE: this doesn't actually generate an executable. With the above flags, it combines the .o files together in another .o.
+                    context.compile_to_file(OutputKind::Executable, obj_out.to_str().expect("path to str"));
+                }
+                else {
+                    context.compile_to_file(OutputKind::ObjectFile, obj_out.to_str().expect("path to str"));
+                }
             }
 
             EmitObj::Bitcode => {
-                // TODO(antoyo)
+                debug!("copying bitcode {:?} to obj {:?}", bc_out, obj_out);
+                if let Err(err) = link_or_copy(&bc_out, &obj_out) {
+                    diag_handler.emit_err(CopyBitcode { err });
+                }
+
+                if !config.emit_bc {
+                    debug!("removing_bitcode {:?}", bc_out);
+                    ensure_removed(diag_handler, &bc_out);
+                }
             }
 
             EmitObj::None => {}
@@ -82,3 +151,18 @@ pub(crate) unsafe fn codegen(cgcx: &CodegenContext<GccCodegenBackend>, _diag_han
 pub(crate) fn link(_cgcx: &CodegenContext<GccCodegenBackend>, _diag_handler: &Handler, mut _modules: Vec<ModuleCodegen<GccContext>>) -> Result<ModuleCodegen<GccContext>, FatalError> {
     unimplemented!();
 }
+
+pub(crate) fn save_temp_bitcode(cgcx: &CodegenContext<GccCodegenBackend>, _module: &ModuleCodegen<GccContext>, _name: &str) {
+    if !cgcx.save_temps {
+        return;
+    }
+    unimplemented!();
+    /*unsafe {
+        let ext = format!("{}.bc", name);
+        let cgu = Some(&module.name[..]);
+        let path = cgcx.output_filenames.temp_path_ext(&ext, cgu);
+        let cstr = path_to_c_string(&path);
+        let llmod = module.module_llvm.llmod();
+        llvm::LLVMWriteBitcodeToFile(llmod, cstr.as_ptr());
+    }*/
+}
diff --git a/compiler/rustc_codegen_gcc/src/base.rs b/compiler/rustc_codegen_gcc/src/base.rs
index 9e614ca4ace..5073066c138 100644
--- a/compiler/rustc_codegen_gcc/src/base.rs
+++ b/compiler/rustc_codegen_gcc/src/base.rs
@@ -1,3 +1,4 @@
+use std::collections::HashSet;
 use std::env;
 use std::time::Instant;
 
@@ -18,6 +19,7 @@ use rustc_codegen_ssa::traits::DebugInfoMethods;
 use rustc_session::config::DebugInfo;
 use rustc_span::Symbol;
 
+use crate::{LockedTargetInfo, gcc_util};
 use crate::GccContext;
 use crate::builder::Builder;
 use crate::context::CodegenCx;
@@ -50,6 +52,7 @@ pub fn global_linkage_to_gcc(linkage: Linkage) -> GlobalKind {
 pub fn linkage_to_gcc(linkage: Linkage) -> FunctionType {
     match linkage {
         Linkage::External => FunctionType::Exported,
+        // TODO(antoyo): set the attribute externally_visible.
         Linkage::AvailableExternally => FunctionType::Extern,
         Linkage::LinkOnceAny => unimplemented!(),
         Linkage::LinkOnceODR => unimplemented!(),
@@ -63,7 +66,7 @@ pub fn linkage_to_gcc(linkage: Linkage) -> FunctionType {
     }
 }
 
-pub fn compile_codegen_unit(tcx: TyCtxt<'_>, cgu_name: Symbol, supports_128bit_integers: bool) -> (ModuleCodegen<GccContext>, u64) {
+pub fn compile_codegen_unit(tcx: TyCtxt<'_>, cgu_name: Symbol, target_info: LockedTargetInfo) -> (ModuleCodegen<GccContext>, u64) {
     let prof_timer = tcx.prof.generic_activity("codegen_module");
     let start_time = Instant::now();
 
@@ -71,7 +74,7 @@ pub fn compile_codegen_unit(tcx: TyCtxt<'_>, cgu_name: Symbol, supports_128bit_i
     let (module, _) = tcx.dep_graph.with_task(
         dep_node,
         tcx,
-        (cgu_name, supports_128bit_integers),
+        (cgu_name, target_info),
         module_codegen,
         Some(dep_graph::hash_result),
     );
@@ -82,38 +85,29 @@ pub fn compile_codegen_unit(tcx: TyCtxt<'_>, cgu_name: Symbol, supports_128bit_i
     // the time we needed for codegenning it.
     let cost = time_to_codegen.as_secs() * 1_000_000_000 + time_to_codegen.subsec_nanos() as u64;
 
-    fn module_codegen(tcx: TyCtxt<'_>, (cgu_name, supports_128bit_integers): (Symbol, bool)) -> ModuleCodegen<GccContext> {
+    fn module_codegen(tcx: TyCtxt<'_>, (cgu_name, target_info): (Symbol, LockedTargetInfo)) -> ModuleCodegen<GccContext> {
         let cgu = tcx.codegen_unit(cgu_name);
         // Instantiate monomorphizations without filling out definitions yet...
-        //let llvm_module = ModuleLlvm::new(tcx, &cgu_name.as_str());
         let context = Context::default();
 
         context.add_command_line_option("-fexceptions");
         context.add_driver_option("-fexceptions");
 
-        // TODO(antoyo): only set on x86 platforms.
-        context.add_command_line_option("-masm=intel");
-        // TODO(antoyo): only add the following cli argument if the feature is supported.
-        context.add_command_line_option("-msse2");
-        context.add_command_line_option("-mavx2");
-        // FIXME(antoyo): the following causes an illegal instruction on vmovdqu64 in std_example on my CPU.
-        // Only add if the CPU supports it.
-        context.add_command_line_option("-msha");
-        context.add_command_line_option("-mpclmul");
-        context.add_command_line_option("-mfma");
-        context.add_command_line_option("-mfma4");
-        context.add_command_line_option("-m64");
-        context.add_command_line_option("-mbmi");
-        context.add_command_line_option("-mgfni");
-        //context.add_command_line_option("-mavxvnni"); // The CI doesn't support this option.
-        context.add_command_line_option("-mf16c");
-        context.add_command_line_option("-maes");
-        context.add_command_line_option("-mxsavec");
-        context.add_command_line_option("-mbmi2");
-        context.add_command_line_option("-mrtm");
-        context.add_command_line_option("-mvaes");
-        context.add_command_line_option("-mvpclmulqdq");
-        context.add_command_line_option("-mavx");
+        let disabled_features: HashSet<_> = tcx.sess.opts.cg.target_feature.split(',')
+            .filter(|feature| feature.starts_with('-'))
+            .map(|string| &string[1..])
+            .collect();
+
+        if tcx.sess.target.arch == "x86" || tcx.sess.target.arch == "x86_64" {
+            context.add_command_line_option("-masm=intel");
+        }
+
+        if !disabled_features.contains("avx") && tcx.sess.target.arch == "x86_64" {
+            // NOTE: we always enable AVX because the equivalent of llvm.x86.sse2.cmp.pd in GCC for
+            // SSE2 is multiple builtins, so we use the AVX __builtin_ia32_cmppd instead.
+            // FIXME(antoyo): use the proper builtins for llvm.x86.sse2.cmp.pd and similar.
+            context.add_command_line_option("-mavx");
+        }
 
         for arg in &tcx.sess.opts.cg.llvm_args {
             context.add_command_line_option(arg);
@@ -127,6 +121,16 @@ pub fn compile_codegen_unit(tcx: TyCtxt<'_>, cgu_name: Symbol, supports_128bit_i
         // NOTE: Rust relies on LLVM doing wrapping on overflow.
         context.add_command_line_option("-fwrapv");
 
+        if tcx.sess.relocation_model() == rustc_target::spec::RelocModel::Static {
+            context.add_command_line_option("-mcmodel=kernel");
+            context.add_command_line_option("-fno-pie");
+        }
+
+        let target_cpu = gcc_util::target_cpu(tcx.sess);
+        if target_cpu != "generic" {
+            context.add_command_line_option(&format!("-march={}", target_cpu));
+        }
+
         if tcx.sess.opts.unstable_opts.function_sections.unwrap_or(tcx.sess.target.function_sections) {
             context.add_command_line_option("-ffunction-sections");
             context.add_command_line_option("-fdata-sections");
@@ -135,8 +139,14 @@ pub fn compile_codegen_unit(tcx: TyCtxt<'_>, cgu_name: Symbol, supports_128bit_i
         if env::var("CG_GCCJIT_DUMP_RTL").as_deref() == Ok("1") {
             context.add_command_line_option("-fdump-rtl-vregs");
         }
+        if env::var("CG_GCCJIT_DUMP_RTL_ALL").as_deref() == Ok("1") {
+            context.add_command_line_option("-fdump-rtl-all");
+        }
         if env::var("CG_GCCJIT_DUMP_TREE_ALL").as_deref() == Ok("1") {
-            context.add_command_line_option("-fdump-tree-all");
+            context.add_command_line_option("-fdump-tree-all-eh");
+        }
+        if env::var("CG_GCCJIT_DUMP_IPA_ALL").as_deref() == Ok("1") {
+            context.add_command_line_option("-fdump-ipa-all-eh");
         }
         if env::var("CG_GCCJIT_DUMP_CODE").as_deref() == Ok("1") {
             context.set_dump_code_on_compile(true);
@@ -152,11 +162,15 @@ pub fn compile_codegen_unit(tcx: TyCtxt<'_>, cgu_name: Symbol, supports_128bit_i
             context.set_keep_intermediates(true);
         }
 
+        if env::var("CG_GCCJIT_VERBOSE").as_deref() == Ok("1") {
+            context.add_driver_option("-v");
+        }
+
         // NOTE: The codegen generates unrechable blocks.
         context.set_allow_unreachable_blocks(true);
 
         {
-            let cx = CodegenCx::new(&context, cgu, tcx, supports_128bit_integers);
+            let cx = CodegenCx::new(&context, cgu, tcx, target_info.supports_128bit_int());
 
             let mono_items = cgu.items_in_deterministic_order(tcx);
             for &(mono_item, data) in &mono_items {
@@ -181,7 +195,9 @@ pub fn compile_codegen_unit(tcx: TyCtxt<'_>, cgu_name: Symbol, supports_128bit_i
         ModuleCodegen {
             name: cgu_name.to_string(),
             module_llvm: GccContext {
-                context
+                context,
+                should_combine_object_files: false,
+                temp_dir: None,
             },
             kind: ModuleKind::Regular,
         }
diff --git a/compiler/rustc_codegen_gcc/src/builder.rs b/compiler/rustc_codegen_gcc/src/builder.rs
index ecc293aee23..b8a8c144dc9 100644
--- a/compiler/rustc_codegen_gcc/src/builder.rs
+++ b/compiler/rustc_codegen_gcc/src/builder.rs
@@ -247,16 +247,9 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
     }
 
     fn check_store(&mut self, val: RValue<'gcc>, ptr: RValue<'gcc>) -> RValue<'gcc> {
-        let dest_ptr_ty = self.cx.val_ty(ptr).make_pointer(); // TODO(antoyo): make sure make_pointer() is okay here.
         let stored_ty = self.cx.val_ty(val);
         let stored_ptr_ty = self.cx.type_ptr_to(stored_ty);
-
-        if dest_ptr_ty == stored_ptr_ty {
-            ptr
-        }
-        else {
-            self.bitcast(ptr, stored_ptr_ty)
-        }
+        self.bitcast(ptr, stored_ptr_ty)
     }
 
     pub fn current_func(&self) -> Function<'gcc> {
@@ -500,7 +493,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
     }
 
     #[cfg(not(feature="master"))]
-    fn invoke(&mut self, typ: Type<'gcc>, fn_attrs: &CodegenFnAttrs, fn_abi: Option<&FnAbi<'tcx, Ty<'tcx>>>, func: RValue<'gcc>, args: &[RValue<'gcc>], then: Block<'gcc>, catch: Block<'gcc>, _funclet: Option<&Funclet>) -> RValue<'gcc> {
+    fn invoke(&mut self, typ: Type<'gcc>, fn_attrs: Option<&CodegenFnAttrs>, fn_abi: Option<&FnAbi<'tcx, Ty<'tcx>>>, func: RValue<'gcc>, args: &[RValue<'gcc>], then: Block<'gcc>, catch: Block<'gcc>, _funclet: Option<&Funclet>) -> RValue<'gcc> {
         let call_site = self.call(typ, fn_attrs, None, func, args, None);
         let condition = self.context.new_rvalue_from_int(self.bool_type, 1);
         self.llbb().end_with_conditional(None, condition, then, catch);
@@ -663,7 +656,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
     }
 
     fn unchecked_sadd(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
-        a + b
+        self.gcc_add(a, b)
     }
 
     fn unchecked_uadd(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
@@ -671,7 +664,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
     }
 
     fn unchecked_ssub(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
-        a - b
+        self.gcc_sub(a, b)
     }
 
     fn unchecked_usub(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
@@ -680,11 +673,11 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
     }
 
     fn unchecked_smul(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
-        a * b
+        self.gcc_mul(a, b)
     }
 
     fn unchecked_umul(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
-        a * b
+        self.gcc_mul(a, b)
     }
 
     fn fadd_fast(&mut self, lhs: RValue<'gcc>, rhs: RValue<'gcc>) -> RValue<'gcc> {
@@ -758,9 +751,8 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
         loaded_value.to_rvalue()
     }
 
-    fn volatile_load(&mut self, _ty: Type<'gcc>, ptr: RValue<'gcc>) -> RValue<'gcc> {
-        // TODO(antoyo): use ty.
-        let ptr = self.context.new_cast(None, ptr, ptr.get_type().make_volatile());
+    fn volatile_load(&mut self, ty: Type<'gcc>, ptr: RValue<'gcc>) -> RValue<'gcc> {
+        let ptr = self.context.new_cast(None, ptr, ty.make_volatile().make_pointer());
         ptr.dereference(None).to_rvalue()
     }
 
@@ -916,7 +908,9 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
             .add_eval(None, self.context.new_call(None, atomic_store, &[ptr, value, ordering]));
     }
 
-    fn gep(&mut self, _typ: Type<'gcc>, ptr: RValue<'gcc>, indices: &[RValue<'gcc>]) -> RValue<'gcc> {
+    fn gep(&mut self, typ: Type<'gcc>, ptr: RValue<'gcc>, indices: &[RValue<'gcc>]) -> RValue<'gcc> {
+        // NOTE: due to opaque pointers now being used, we need to cast here.
+        let ptr = self.context.new_cast(None, ptr, typ.make_pointer());
         let ptr_type = ptr.get_type();
         let mut pointee_type = ptr.get_type();
         // NOTE: we cannot use array indexing here like in inbounds_gep because array indexing is
@@ -927,6 +921,12 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
         // require dereferencing the pointer.
         for index in indices {
             pointee_type = pointee_type.get_pointee().expect("pointee type");
+            #[cfg(feature="master")]
+            let pointee_size = {
+                let size = self.cx.context.new_sizeof(pointee_type);
+                self.context.new_cast(None, size, index.get_type())
+            };
+            #[cfg(not(feature="master"))]
             let pointee_size = self.context.new_rvalue_from_int(index.get_type(), pointee_type.get_size() as i32);
             result = result + self.gcc_int_cast(*index * pointee_size, self.sizet_type);
         }
diff --git a/compiler/rustc_codegen_gcc/src/common.rs b/compiler/rustc_codegen_gcc/src/common.rs
index 5f54cb16d8e..93fe27e547a 100644
--- a/compiler/rustc_codegen_gcc/src/common.rs
+++ b/compiler/rustc_codegen_gcc/src/common.rs
@@ -424,35 +424,35 @@ impl<'gcc, 'tcx> TypeReflection<'gcc, 'tcx> for Type<'gcc> {
     }
 
     fn is_i8(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool {
-        self.unqualified() == cx.i8_type
+        self.is_compatible_with(cx.i8_type)
     }
 
     fn is_u8(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool {
-        self.unqualified() == cx.u8_type
+        self.is_compatible_with(cx.u8_type)
     }
 
     fn is_i16(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool {
-        self.unqualified() == cx.i16_type
+        self.is_compatible_with(cx.i16_type)
     }
 
     fn is_u16(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool {
-        self.unqualified() == cx.u16_type
+        self.is_compatible_with(cx.u16_type)
     }
 
     fn is_i32(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool {
-        self.unqualified() == cx.i32_type
+        self.is_compatible_with(cx.i32_type)
     }
 
     fn is_u32(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool {
-        self.unqualified() == cx.u32_type
+        self.is_compatible_with(cx.u32_type)
     }
 
     fn is_i64(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool {
-        self.unqualified() == cx.i64_type
+        self.is_compatible_with(cx.i64_type)
     }
 
     fn is_u64(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool {
-        self.unqualified() == cx.u64_type
+        self.is_compatible_with(cx.u64_type)
     }
 
     fn is_i128(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool {
diff --git a/compiler/rustc_codegen_gcc/src/context.rs b/compiler/rustc_codegen_gcc/src/context.rs
index dcebd92a61c..a043660ea63 100644
--- a/compiler/rustc_codegen_gcc/src/context.rs
+++ b/compiler/rustc_codegen_gcc/src/context.rs
@@ -20,6 +20,7 @@ use rustc_target::abi::{call::FnAbi, HasDataLayout, PointeeInfo, Size, TargetDat
 use rustc_target::spec::{HasTargetSpec, Target, TlsModel};
 
 use crate::callee::get_fn;
+use crate::common::SignType;
 
 #[derive(Clone)]
 pub struct FuncSig<'gcc> {
@@ -129,29 +130,57 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
     pub fn new(context: &'gcc Context<'gcc>, codegen_unit: &'tcx CodegenUnit<'tcx>, tcx: TyCtxt<'tcx>, supports_128bit_integers: bool) -> Self {
         let check_overflow = tcx.sess.overflow_checks();
 
-        let i8_type = context.new_c_type(CType::Int8t);
-        let i16_type = context.new_c_type(CType::Int16t);
-        let i32_type = context.new_c_type(CType::Int32t);
-        let i64_type = context.new_c_type(CType::Int64t);
-        let u8_type = context.new_c_type(CType::UInt8t);
-        let u16_type = context.new_c_type(CType::UInt16t);
-        let u32_type = context.new_c_type(CType::UInt32t);
-        let u64_type = context.new_c_type(CType::UInt64t);
+        let create_type = |ctype, rust_type| {
+            let layout = tcx.layout_of(ParamEnv::reveal_all().and(rust_type)).unwrap();
+            let align = layout.align.abi.bytes();
+            #[cfg(feature="master")]
+            {
+                context.new_c_type(ctype).get_aligned(align)
+            }
+            #[cfg(not(feature="master"))]
+            {
+                // Since libgccjit 12 doesn't contain the fix to compare aligned integer types,
+                // only align u128 and i128.
+                if layout.ty.int_size_and_signed(tcx).0.bytes() == 16 {
+                    context.new_c_type(ctype).get_aligned(align)
+                }
+                else {
+                    context.new_c_type(ctype)
+                }
+            }
+        };
+
+        let i8_type = create_type(CType::Int8t, tcx.types.i8);
+        let i16_type = create_type(CType::Int16t, tcx.types.i16);
+        let i32_type = create_type(CType::Int32t, tcx.types.i32);
+        let i64_type = create_type(CType::Int64t, tcx.types.i64);
+        let u8_type = create_type(CType::UInt8t, tcx.types.u8);
+        let u16_type = create_type(CType::UInt16t, tcx.types.u16);
+        let u32_type = create_type(CType::UInt32t, tcx.types.u32);
+        let u64_type = create_type(CType::UInt64t, tcx.types.u64);
 
         let (i128_type, u128_type) =
             if supports_128bit_integers {
-                let i128_type = context.new_c_type(CType::Int128t).get_aligned(8); // TODO(antoyo): should the alignment be hard-coded?;
-                let u128_type = context.new_c_type(CType::UInt128t).get_aligned(8); // TODO(antoyo): should the alignment be hard-coded?;
+                let i128_type = create_type(CType::Int128t, tcx.types.i128);
+                let u128_type = create_type(CType::UInt128t, tcx.types.u128);
                 (i128_type, u128_type)
             }
             else {
-                let i128_type = context.new_array_type(None, i64_type, 2);
-                let u128_type = context.new_array_type(None, u64_type, 2);
+                /*let layout = tcx.layout_of(ParamEnv::reveal_all().and(tcx.types.i128)).unwrap();
+                let i128_align = layout.align.abi.bytes();
+                let layout = tcx.layout_of(ParamEnv::reveal_all().and(tcx.types.u128)).unwrap();
+                let u128_align = layout.align.abi.bytes();*/
+
+                // TODO(antoyo): re-enable the alignment when libgccjit fixed the issue in
+                // gcc_jit_context_new_array_constructor (it should not use reinterpret_cast).
+                let i128_type = context.new_array_type(None, i64_type, 2)/*.get_aligned(i128_align)*/;
+                let u128_type = context.new_array_type(None, u64_type, 2)/*.get_aligned(u128_align)*/;
                 (i128_type, u128_type)
             };
 
         let tls_model = to_gcc_tls_mode(tcx.sess.tls_model());
 
+        // TODO(antoyo): set alignment on those types as well.
         let float_type = context.new_type::<f32>();
         let double_type = context.new_type::<f64>();
 
@@ -167,14 +196,10 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
         let ulonglong_type = context.new_c_type(CType::ULongLong);
         let sizet_type = context.new_c_type(CType::SizeT);
 
-        let isize_type = context.new_c_type(CType::LongLong);
-        let usize_type = context.new_c_type(CType::ULongLong);
+        let usize_type = sizet_type;
+        let isize_type = usize_type;
         let bool_type = context.new_type::<bool>();
 
-        // TODO(antoyo): only have those assertions on x86_64.
-        assert_eq!(isize_type.get_size(), i64_type.get_size());
-        assert_eq!(usize_type.get_size(), u64_type.get_size());
-
         let mut functions = FxHashMap::default();
         let builtins = [
             "__builtin_unreachable", "abort", "__builtin_expect", "__builtin_add_overflow", "__builtin_mul_overflow",
@@ -192,7 +217,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
             functions.insert(builtin.to_string(), context.get_builtin_function(builtin));
         }
 
-        Self {
+        let mut cx = Self {
             check_overflow,
             codegen_unit,
             context,
@@ -254,7 +279,10 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
             pointee_infos: Default::default(),
             structs_as_pointer: Default::default(),
             cleanup_blocks: Default::default(),
-        }
+        };
+        // TODO(antoyo): instead of doing this, add SsizeT to libgccjit.
+        cx.isize_type = usize_type.to_signed(&cx);
+        cx
     }
 
     pub fn rvalue_as_function(&self, value: RValue<'gcc>) -> Function<'gcc> {
diff --git a/compiler/rustc_codegen_gcc/src/declare.rs b/compiler/rustc_codegen_gcc/src/declare.rs
index 493626c3cf5..247454fa58e 100644
--- a/compiler/rustc_codegen_gcc/src/declare.rs
+++ b/compiler/rustc_codegen_gcc/src/declare.rs
@@ -1,10 +1,12 @@
 use gccjit::{Function, FunctionType, GlobalKind, LValue, RValue, Type};
+#[cfg(feature="master")]
+use gccjit::{FnAttribute, ToRValue};
 use rustc_codegen_ssa::traits::BaseTypeMethods;
 use rustc_middle::ty::Ty;
 use rustc_span::Symbol;
 use rustc_target::abi::call::FnAbi;
 
-use crate::abi::FnAbiGccExt;
+use crate::abi::{FnAbiGcc, FnAbiGccExt};
 use crate::context::CodegenCx;
 use crate::intrinsic::llvm;
 
@@ -78,9 +80,20 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
     }
 
     pub fn declare_fn(&self, name: &str, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> Function<'gcc> {
-        let (return_type, params, variadic, on_stack_param_indices) = fn_abi.gcc_type(self);
-        let func = declare_raw_fn(self, name, () /*fn_abi.llvm_cconv()*/, return_type, &params, variadic);
+        let FnAbiGcc {
+            return_type,
+            arguments_type,
+            is_c_variadic,
+            on_stack_param_indices,
+            #[cfg(feature="master")]
+            fn_attributes,
+        } = fn_abi.gcc_type(self);
+        let func = declare_raw_fn(self, name, () /*fn_abi.llvm_cconv()*/, return_type, &arguments_type, is_c_variadic);
         self.on_stack_function_params.borrow_mut().insert(func, on_stack_param_indices);
+        #[cfg(feature="master")]
+        for fn_attr in fn_attributes {
+            func.add_attribute(fn_attr);
+        }
         func
     }
 
@@ -114,6 +127,44 @@ fn declare_raw_fn<'gcc>(cx: &CodegenCx<'gcc, '_>, name: &str, _callconv: () /*ll
                 .collect();
             let func = cx.context.new_function(None, cx.linkage.get(), return_type, &params, mangle_name(name), variadic);
             cx.functions.borrow_mut().insert(name.to_string(), func);
+
+            #[cfg(feature="master")]
+            if name == "rust_eh_personality" {
+                // NOTE: GCC will sometimes change the personality function set on a function from
+                // rust_eh_personality to __gcc_personality_v0 as an optimization.
+                // As such, we need to create a weak alias from __gcc_personality_v0 to
+                // rust_eh_personality in order to avoid a linker error.
+                // This needs to be weak in order to still allow using the standard
+                // __gcc_personality_v0 when the linking to it.
+                // Since aliases don't work (maybe because of a bug in LTO partitioning?), we
+                // create a wrapper function that calls rust_eh_personality.
+
+                let params: Vec<_> = param_types.into_iter().enumerate()
+                    .map(|(index, param)| cx.context.new_parameter(None, *param, &format!("param{}", index))) // TODO(antoyo): set name.
+                    .collect();
+                let gcc_func = cx.context.new_function(None, FunctionType::Exported, return_type, &params, "__gcc_personality_v0", variadic);
+
+                // We need a normal extern function for the crates that access rust_eh_personality
+                // without defining it, otherwise we'll get a compiler error.
+                //
+                // For the crate defining it, that needs to be a weak alias instead.
+                gcc_func.add_attribute(FnAttribute::Weak);
+
+                let block = gcc_func.new_block("start");
+                let mut args = vec![];
+                for param in &params {
+                    args.push(param.to_rvalue());
+                }
+                let call = cx.context.new_call(None, func, &args);
+                if return_type == cx.type_void() {
+                    block.add_eval(None, call);
+                    block.end_with_void_return(None);
+                }
+                else {
+                    block.end_with_return(None, call);
+                }
+            }
+
             func
         };
 
diff --git a/compiler/rustc_codegen_gcc/src/errors.rs b/compiler/rustc_codegen_gcc/src/errors.rs
index 693367192b1..4bf3b71f503 100644
--- a/compiler/rustc_codegen_gcc/src/errors.rs
+++ b/compiler/rustc_codegen_gcc/src/errors.rs
@@ -1,8 +1,36 @@
-use rustc_errors::{DiagnosticArgValue, IntoDiagnosticArg};
-use rustc_macros::Diagnostic;
+use rustc_errors::{
+    DiagnosticArgValue, DiagnosticBuilder, ErrorGuaranteed, Handler, IntoDiagnostic, IntoDiagnosticArg,
+};
+use rustc_macros::{Diagnostic, Subdiagnostic};
 use rustc_span::Span;
 use std::borrow::Cow;
 
+use crate::fluent_generated as fluent;
+
+#[derive(Diagnostic)]
+#[diag(codegen_gcc_unknown_ctarget_feature_prefix)]
+#[note]
+pub(crate) struct UnknownCTargetFeaturePrefix<'a> {
+    pub feature: &'a str,
+}
+
+#[derive(Diagnostic)]
+#[diag(codegen_gcc_unknown_ctarget_feature)]
+#[note]
+pub(crate) struct UnknownCTargetFeature<'a> {
+    pub feature: &'a str,
+    #[subdiagnostic]
+    pub rust_feature: PossibleFeature<'a>,
+}
+
+#[derive(Subdiagnostic)]
+pub(crate) enum PossibleFeature<'a> {
+    #[help(codegen_gcc_possible_feature)]
+    Some { rust_feature: &'a str },
+    #[help(codegen_gcc_consider_filing_feature_request)]
+    None,
+}
+
 struct ExitCode(Option<i32>);
 
 impl IntoDiagnosticArg for ExitCode {
@@ -40,3 +68,58 @@ pub(crate) struct TiedTargetFeatures {
     pub span: Span,
     pub features: String,
 }
+
+#[derive(Diagnostic)]
+#[diag(codegen_gcc_copy_bitcode)]
+pub(crate) struct CopyBitcode {
+    pub err: std::io::Error,
+}
+
+#[derive(Diagnostic)]
+#[diag(codegen_gcc_dynamic_linking_with_lto)]
+#[note]
+pub(crate) struct DynamicLinkingWithLTO;
+
+#[derive(Diagnostic)]
+#[diag(codegen_gcc_load_bitcode)]
+pub(crate) struct LoadBitcode {
+    name: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(codegen_gcc_lto_disallowed)]
+pub(crate) struct LtoDisallowed;
+
+#[derive(Diagnostic)]
+#[diag(codegen_gcc_lto_dylib)]
+pub(crate) struct LtoDylib;
+
+#[derive(Diagnostic)]
+#[diag(codegen_gcc_lto_bitcode_from_rlib)]
+pub(crate) struct LtoBitcodeFromRlib {
+    pub gcc_err: String,
+}
+
+pub(crate) struct TargetFeatureDisableOrEnable<'a> {
+    pub features: &'a [&'a str],
+    pub span: Option<Span>,
+    pub missing_features: Option<MissingFeatures>,
+}
+
+#[derive(Subdiagnostic)]
+#[help(codegen_gcc_missing_features)]
+pub(crate) struct MissingFeatures;
+
+impl IntoDiagnostic<'_, ErrorGuaranteed> for TargetFeatureDisableOrEnable<'_> {
+    fn into_diagnostic(self, sess: &'_ Handler) -> DiagnosticBuilder<'_, ErrorGuaranteed> {
+        let mut diag = sess.struct_err(fluent::codegen_gcc_target_feature_disable_or_enable);
+        if let Some(span) = self.span {
+            diag.set_span(span);
+        };
+        if let Some(missing_features) = self.missing_features {
+            diag.subdiagnostic(missing_features);
+        }
+        diag.set_arg("features", self.features.join(", "));
+        diag
+    }
+}
diff --git a/compiler/rustc_codegen_gcc/src/gcc_util.rs b/compiler/rustc_codegen_gcc/src/gcc_util.rs
new file mode 100644
index 00000000000..1248fdcd259
--- /dev/null
+++ b/compiler/rustc_codegen_gcc/src/gcc_util.rs
@@ -0,0 +1,230 @@
+#[cfg(feature="master")]
+use gccjit::Context;
+use smallvec::{smallvec, SmallVec};
+
+use rustc_codegen_ssa::target_features::{
+    supported_target_features, tied_target_features, RUSTC_SPECIFIC_FEATURES,
+};
+use rustc_data_structures::fx::FxHashMap;
+use rustc_middle::bug;
+use rustc_session::Session;
+
+use crate::errors::{PossibleFeature, TargetFeatureDisableOrEnable, UnknownCTargetFeature, UnknownCTargetFeaturePrefix};
+
+/// The list of GCC features computed from CLI flags (`-Ctarget-cpu`, `-Ctarget-feature`,
+/// `--target` and similar).
+pub(crate) fn global_gcc_features(sess: &Session, diagnostics: bool) -> Vec<String> {
+    // Features that come earlier are overridden by conflicting features later in the string.
+    // Typically we'll want more explicit settings to override the implicit ones, so:
+    //
+    // * Features from -Ctarget-cpu=*; are overridden by [^1]
+    // * Features implied by --target; are overridden by
+    // * Features from -Ctarget-feature; are overridden by
+    // * function specific features.
+    //
+    // [^1]: target-cpu=native is handled here, other target-cpu values are handled implicitly
+    // through GCC march implementation.
+    //
+    // FIXME(nagisa): it isn't clear what's the best interaction between features implied by
+    // `-Ctarget-cpu` and `--target` are. On one hand, you'd expect CLI arguments to always
+    // override anything that's implicit, so e.g. when there's no `--target` flag, features implied
+    // the host target are overridden by `-Ctarget-cpu=*`. On the other hand, what about when both
+    // `--target` and `-Ctarget-cpu=*` are specified? Both then imply some target features and both
+    // flags are specified by the user on the CLI. It isn't as clear-cut which order of precedence
+    // should be taken in cases like these.
+    let mut features = vec![];
+
+    // Features implied by an implicit or explicit `--target`.
+    features.extend(
+        sess.target
+            .features
+            .split(',')
+            .filter(|v| !v.is_empty() && backend_feature_name(v).is_some())
+            .map(String::from),
+    );
+
+    // -Ctarget-features
+    let supported_features = supported_target_features(sess);
+    let mut featsmap = FxHashMap::default();
+    let feats = sess.opts.cg.target_feature
+        .split(',')
+        .filter_map(|s| {
+            let enable_disable = match s.chars().next() {
+                None => return None,
+                Some(c @ ('+' | '-')) => c,
+                Some(_) => {
+                    if diagnostics {
+                        sess.emit_warning(UnknownCTargetFeaturePrefix { feature: s });
+                    }
+                    return None;
+                }
+            };
+
+            let feature = backend_feature_name(s)?;
+            // Warn against use of GCC specific feature names on the CLI.
+            if diagnostics && !supported_features.iter().any(|&(v, _)| v == feature) {
+                let rust_feature = supported_features.iter().find_map(|&(rust_feature, _)| {
+                    let gcc_features = to_gcc_features(sess, rust_feature);
+                    if gcc_features.contains(&feature) && !gcc_features.contains(&rust_feature) {
+                        Some(rust_feature)
+                    } else {
+                        None
+                    }
+                });
+                let unknown_feature =
+                    if let Some(rust_feature) = rust_feature {
+                        UnknownCTargetFeature {
+                            feature,
+                            rust_feature: PossibleFeature::Some { rust_feature },
+                        }
+                    }
+                    else {
+                        UnknownCTargetFeature { feature, rust_feature: PossibleFeature::None }
+                    };
+                sess.emit_warning(unknown_feature);
+            }
+
+            if diagnostics {
+                // FIXME(nagisa): figure out how to not allocate a full hashset here.
+                featsmap.insert(feature, enable_disable == '+');
+            }
+
+            // rustc-specific features do not get passed down to GCC…
+            if RUSTC_SPECIFIC_FEATURES.contains(&feature) {
+                return None;
+            }
+            // ... otherwise though we run through `to_gcc_features` when
+            // passing requests down to GCC. This means that all in-language
+            // features also work on the command line instead of having two
+            // different names when the GCC name and the Rust name differ.
+            Some(to_gcc_features(sess, feature)
+                .iter()
+                .flat_map(|feat| to_gcc_features(sess, feat).into_iter())
+                .map(|feature| {
+                    if enable_disable == '-' {
+                        format!("-{}", feature)
+                    }
+                    else {
+                        feature.to_string()
+                    }
+                })
+                .collect::<Vec<_>>(),
+            )
+        })
+        .flatten();
+    features.extend(feats);
+
+    if diagnostics {
+        if let Some(f) = check_tied_features(sess, &featsmap) {
+            sess.emit_err(TargetFeatureDisableOrEnable {
+                features: f,
+                span: None,
+                missing_features: None,
+            });
+        }
+    }
+
+    features
+}
+
+/// Returns a feature name for the given `+feature` or `-feature` string.
+///
+/// Only allows features that are backend specific (i.e. not [`RUSTC_SPECIFIC_FEATURES`].)
+fn backend_feature_name(s: &str) -> Option<&str> {
+    // features must start with a `+` or `-`.
+    let feature = s.strip_prefix(&['+', '-'][..]).unwrap_or_else(|| {
+        bug!("target feature `{}` must begin with a `+` or `-`", s);
+    });
+    // Rustc-specific feature requests like `+crt-static` or `-crt-static`
+    // are not passed down to GCC.
+    if RUSTC_SPECIFIC_FEATURES.contains(&feature) {
+        return None;
+    }
+    Some(feature)
+}
+
+// To find a list of GCC's names, check https://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html
+pub fn to_gcc_features<'a>(sess: &Session, s: &'a str) -> SmallVec<[&'a str; 2]> {
+    let arch = if sess.target.arch == "x86_64" { "x86" } else { &*sess.target.arch };
+    match (arch, s) {
+        ("x86", "sse4.2") => smallvec!["sse4.2", "crc32"],
+        ("x86", "pclmulqdq") => smallvec!["pclmul"],
+        ("x86", "rdrand") => smallvec!["rdrnd"],
+        ("x86", "bmi1") => smallvec!["bmi"],
+        ("x86", "cmpxchg16b") => smallvec!["cx16"],
+        ("x86", "avx512vaes") => smallvec!["vaes"],
+        ("x86", "avx512gfni") => smallvec!["gfni"],
+        ("x86", "avx512vpclmulqdq") => smallvec!["vpclmulqdq"],
+        // NOTE: seems like GCC requires 'avx512bw' for 'avx512vbmi2'.
+        ("x86", "avx512vbmi2") => smallvec!["avx512vbmi2", "avx512bw"],
+        // NOTE: seems like GCC requires 'avx512bw' for 'avx512bitalg'.
+        ("x86", "avx512bitalg") => smallvec!["avx512bitalg", "avx512bw"],
+        ("aarch64", "rcpc2") => smallvec!["rcpc-immo"],
+        ("aarch64", "dpb") => smallvec!["ccpp"],
+        ("aarch64", "dpb2") => smallvec!["ccdp"],
+        ("aarch64", "frintts") => smallvec!["fptoint"],
+        ("aarch64", "fcma") => smallvec!["complxnum"],
+        ("aarch64", "pmuv3") => smallvec!["perfmon"],
+        ("aarch64", "paca") => smallvec!["pauth"],
+        ("aarch64", "pacg") => smallvec!["pauth"],
+        // Rust ties fp and neon together. In GCC neon implicitly enables fp,
+        // but we manually enable neon when a feature only implicitly enables fp
+        ("aarch64", "f32mm") => smallvec!["f32mm", "neon"],
+        ("aarch64", "f64mm") => smallvec!["f64mm", "neon"],
+        ("aarch64", "fhm") => smallvec!["fp16fml", "neon"],
+        ("aarch64", "fp16") => smallvec!["fullfp16", "neon"],
+        ("aarch64", "jsconv") => smallvec!["jsconv", "neon"],
+        ("aarch64", "sve") => smallvec!["sve", "neon"],
+        ("aarch64", "sve2") => smallvec!["sve2", "neon"],
+        ("aarch64", "sve2-aes") => smallvec!["sve2-aes", "neon"],
+        ("aarch64", "sve2-sm4") => smallvec!["sve2-sm4", "neon"],
+        ("aarch64", "sve2-sha3") => smallvec!["sve2-sha3", "neon"],
+        ("aarch64", "sve2-bitperm") => smallvec!["sve2-bitperm", "neon"],
+        (_, s) => smallvec![s],
+    }
+}
+
+// Given a map from target_features to whether they are enabled or disabled,
+// ensure only valid combinations are allowed.
+pub fn check_tied_features(sess: &Session, features: &FxHashMap<&str, bool>) -> Option<&'static [&'static str]> {
+    for tied in tied_target_features(sess) {
+        // Tied features must be set to the same value, or not set at all
+        let mut tied_iter = tied.iter();
+        let enabled = features.get(tied_iter.next().unwrap());
+        if tied_iter.any(|feature| enabled != features.get(feature)) {
+            return Some(tied);
+        }
+    }
+    None
+}
+
+fn arch_to_gcc(name: &str) -> &str {
+    match name {
+        "M68020" => "68020",
+         _ => name,
+    }
+}
+
+fn handle_native(name: &str) -> &str {
+    if name != "native" {
+        return arch_to_gcc(name);
+    }
+
+    #[cfg(feature="master")]
+    {
+        // Get the native arch.
+        let context = Context::default();
+        context.get_target_info().arch().unwrap()
+            .to_str()
+            .unwrap()
+    }
+    #[cfg(not(feature="master"))]
+    unimplemented!();
+}
+
+pub fn target_cpu(sess: &Session) -> &str {
+    match sess.opts.cg.target_cpu {
+        Some(ref name) => handle_native(name),
+        None => handle_native(sess.target.cpu.as_ref()),
+    }
+}
diff --git a/compiler/rustc_codegen_gcc/src/int.rs b/compiler/rustc_codegen_gcc/src/int.rs
index 0cf1204791d..ea8550d20f3 100644
--- a/compiler/rustc_codegen_gcc/src/int.rs
+++ b/compiler/rustc_codegen_gcc/src/int.rs
@@ -7,7 +7,9 @@ use std::convert::TryFrom;
 use gccjit::{ComparisonOp, FunctionType, RValue, ToRValue, Type, UnaryOp, BinaryOp};
 use rustc_codegen_ssa::common::{IntPredicate, TypeKind};
 use rustc_codegen_ssa::traits::{BackendTypes, BaseTypeMethods, BuilderMethods, OverflowOp};
-use rustc_middle::ty::Ty;
+use rustc_middle::ty::{ParamEnv, Ty};
+use rustc_target::abi::{Endian, call::{ArgAbi, ArgAttributes, Conv, FnAbi, PassMode}};
+use rustc_target::spec;
 
 use crate::builder::ToGccComp;
 use crate::{builder::Builder, common::{SignType, TypeReflection}, context::CodegenCx};
@@ -36,13 +38,11 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
             self.cx.context.new_unary_op(None, operation, typ, a)
         }
         else {
-            // TODO(antoyo): use __negdi2 and __negti2 instead?
             let element_type = typ.dyncast_array().expect("element type");
-            let values = [
+            self.from_low_high_rvalues(typ,
                 self.cx.context.new_unary_op(None, UnaryOp::BitwiseNegate, element_type, self.low(a)),
                 self.cx.context.new_unary_op(None, UnaryOp::BitwiseNegate, element_type, self.high(a)),
-            ];
-            self.cx.context.new_array_constructor(None, typ, &values)
+            )
         }
     }
 
@@ -52,9 +52,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
             self.cx.context.new_unary_op(None, UnaryOp::Minus, a.get_type(), a)
         }
         else {
-            let param_a = self.context.new_parameter(None, a_type, "a");
-            let func = self.context.new_function(None, FunctionType::Extern, a_type, &[param_a], "__negti2", false);
-            self.context.new_call(None, func, &[a])
+            self.gcc_add(self.gcc_not(a), self.gcc_int(a_type, 1))
         }
     }
 
@@ -103,7 +101,6 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
             let condition = self.gcc_icmp(IntPredicate::IntNE, self.gcc_and(b, sixty_four), zero);
             self.llbb().end_with_conditional(None, condition, then_block, else_block);
 
-            // TODO(antoyo): take endianness into account.
             let shift_value = self.gcc_sub(b, sixty_four);
             let high = self.high(a);
             let sign =
@@ -113,11 +110,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
                 else {
                     zero
                 };
-            let values = [
-                high >> shift_value,
-                sign,
-            ];
-            let array_value = self.context.new_array_constructor(None, a_type, &values);
+            let array_value = self.from_low_high_rvalues(a_type, high >> shift_value, sign);
             then_block.add_assignment(None, result, array_value);
             then_block.end_with_jump(None, after_block);
 
@@ -133,11 +126,10 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
             let casted_low = self.context.new_cast(None, self.low(a), unsigned_type);
             let shifted_low = casted_low >> self.context.new_cast(None, b, unsigned_type);
             let shifted_low = self.context.new_cast(None, shifted_low, native_int_type);
-            let values = [
+            let array_value = self.from_low_high_rvalues(a_type,
                 (high << shift_value) | shifted_low,
                 high >> b,
-            ];
-            let array_value = self.context.new_array_constructor(None, a_type, &values);
+            );
             actual_else_block.add_assignment(None, result, array_value);
             actual_else_block.end_with_jump(None, after_block);
 
@@ -317,18 +309,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
                                         _ => unreachable!(),
                                     },
                             };
-                        let a_type = lhs.get_type();
-                        let b_type = rhs.get_type();
-                        let param_a = self.context.new_parameter(None, a_type, "a");
-                        let param_b = self.context.new_parameter(None, b_type, "b");
-                        let result_field = self.context.new_field(None, a_type, "result");
-                        let overflow_field = self.context.new_field(None, self.bool_type, "overflow");
-                        let return_type = self.context.new_struct_type(None, "result_overflow", &[result_field, overflow_field]);
-                        let func = self.context.new_function(None, FunctionType::Extern, return_type.as_type(), &[param_a, param_b], func_name, false);
-                        let result = self.context.new_call(None, func, &[lhs, rhs]);
-                        let overflow = result.access_field(None, overflow_field);
-                        let int_result = result.access_field(None, result_field);
-                        return (int_result, overflow);
+                        return self.operation_with_overflow(func_name, lhs, rhs);
                     },
                     _ => {
                         match oop {
@@ -353,23 +334,111 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
         (res.dereference(None).to_rvalue(), overflow)
     }
 
-    pub fn gcc_icmp(&self, op: IntPredicate, mut lhs: RValue<'gcc>, mut rhs: RValue<'gcc>) -> RValue<'gcc> {
+    pub fn operation_with_overflow(&self, func_name: &str, lhs: RValue<'gcc>, rhs: RValue<'gcc>) -> (RValue<'gcc>, RValue<'gcc>) {
+        let a_type = lhs.get_type();
+        let b_type = rhs.get_type();
+        let param_a = self.context.new_parameter(None, a_type, "a");
+        let param_b = self.context.new_parameter(None, b_type, "b");
+        let result_field = self.context.new_field(None, a_type, "result");
+        let overflow_field = self.context.new_field(None, self.bool_type, "overflow");
+
+        let ret_ty = Ty::new_tup(self.tcx, &[self.tcx.types.i128, self.tcx.types.bool]);
+        let layout = self.tcx.layout_of(ParamEnv::reveal_all().and(ret_ty)).unwrap();
+
+        let arg_abi = ArgAbi {
+            layout,
+            mode: PassMode::Direct(ArgAttributes::new()),
+        };
+        let mut fn_abi = FnAbi {
+            args: vec![arg_abi.clone(), arg_abi.clone()].into_boxed_slice(),
+            ret: arg_abi,
+            c_variadic: false,
+            fixed_count: 2,
+            conv: Conv::C,
+            can_unwind: false,
+        };
+        fn_abi.adjust_for_foreign_abi(self.cx, spec::abi::Abi::C {
+            unwind: false,
+        }).unwrap();
+
+        let indirect = matches!(fn_abi.ret.mode, PassMode::Indirect { .. });
+
+        let return_type = self.context.new_struct_type(None, "result_overflow", &[result_field, overflow_field]);
+        let result =
+            if indirect {
+                let return_value = self.current_func().new_local(None, return_type.as_type(), "return_value");
+                let return_param_type = return_type.as_type().make_pointer();
+                let return_param = self.context.new_parameter(None, return_param_type, "return_value");
+                let func = self.context.new_function(None, FunctionType::Extern, self.type_void(), &[return_param, param_a, param_b], func_name, false);
+                self.llbb().add_eval(None, self.context.new_call(None, func, &[return_value.get_address(None), lhs, rhs]));
+                return_value.to_rvalue()
+            }
+            else {
+                let func = self.context.new_function(None, FunctionType::Extern, return_type.as_type(), &[param_a, param_b], func_name, false);
+                self.context.new_call(None, func, &[lhs, rhs])
+            };
+        let overflow = result.access_field(None, overflow_field);
+        let int_result = result.access_field(None, result_field);
+        return (int_result, overflow);
+    }
+
+    pub fn gcc_icmp(&mut self, op: IntPredicate, mut lhs: RValue<'gcc>, mut rhs: RValue<'gcc>) -> RValue<'gcc> {
         let a_type = lhs.get_type();
         let b_type = rhs.get_type();
         if self.is_non_native_int_type(a_type) || self.is_non_native_int_type(b_type) {
-            let signed = a_type.is_compatible_with(self.i128_type);
-            let sign =
-                if signed {
-                    ""
-                }
-                else {
-                    "u"
-                };
-            let func_name = format!("__{}cmpti2", sign);
-            let param_a = self.context.new_parameter(None, a_type, "a");
-            let param_b = self.context.new_parameter(None, b_type, "b");
-            let func = self.context.new_function(None, FunctionType::Extern, self.int_type, &[param_a, param_b], func_name, false);
-            let cmp = self.context.new_call(None, func, &[lhs, rhs]);
+            // This algorithm is based on compiler-rt's __cmpti2:
+            // https://github.com/llvm-mirror/compiler-rt/blob/f0745e8476f069296a7c71accedd061dce4cdf79/lib/builtins/cmpti2.c#L21
+            let result = self.current_func().new_local(None, self.int_type, "icmp_result");
+            let block1 = self.current_func().new_block("block1");
+            let block2 = self.current_func().new_block("block2");
+            let block3 = self.current_func().new_block("block3");
+            let block4 = self.current_func().new_block("block4");
+            let block5 = self.current_func().new_block("block5");
+            let block6 = self.current_func().new_block("block6");
+            let block7 = self.current_func().new_block("block7");
+            let block8 = self.current_func().new_block("block8");
+            let after = self.current_func().new_block("after");
+
+            let native_int_type = a_type.dyncast_array().expect("get element type");
+            // NOTE: cast low to its unsigned type in order to perform a comparison correctly (e.g.
+            // the sign is only on high).
+            let unsigned_type = native_int_type.to_unsigned(&self.cx);
+
+            let lhs_low = self.context.new_cast(None, self.low(lhs), unsigned_type);
+            let rhs_low = self.context.new_cast(None, self.low(rhs), unsigned_type);
+
+            let condition = self.context.new_comparison(None, ComparisonOp::LessThan, self.high(lhs), self.high(rhs));
+            self.llbb().end_with_conditional(None, condition, block1, block2);
+
+            block1.add_assignment(None, result, self.context.new_rvalue_zero(self.int_type));
+            block1.end_with_jump(None, after);
+
+            let condition = self.context.new_comparison(None, ComparisonOp::GreaterThan, self.high(lhs), self.high(rhs));
+            block2.end_with_conditional(None, condition, block3, block4);
+
+            block3.add_assignment(None, result, self.context.new_rvalue_from_int(self.int_type, 2));
+            block3.end_with_jump(None, after);
+
+            let condition = self.context.new_comparison(None, ComparisonOp::LessThan, lhs_low, rhs_low);
+            block4.end_with_conditional(None, condition, block5, block6);
+
+            block5.add_assignment(None, result, self.context.new_rvalue_zero(self.int_type));
+            block5.end_with_jump(None, after);
+
+            let condition = self.context.new_comparison(None, ComparisonOp::GreaterThan, lhs_low, rhs_low);
+            block6.end_with_conditional(None, condition, block7, block8);
+
+            block7.add_assignment(None, result, self.context.new_rvalue_from_int(self.int_type, 2));
+            block7.end_with_jump(None, after);
+
+            block8.add_assignment(None, result, self.context.new_rvalue_one(self.int_type));
+            block8.end_with_jump(None, after);
+
+            // NOTE: since jumps were added in a place rustc does not expect, the current block in the
+            // state need to be updated.
+            self.switch_to_block(after);
+
+            let cmp = result.to_rvalue();
             let (op, limit) =
                 match op {
                     IntPredicate::IntEQ => {
@@ -378,6 +447,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
                     IntPredicate::IntNE => {
                         return self.context.new_comparison(None, ComparisonOp::NotEquals, cmp, self.context.new_rvalue_one(self.int_type));
                     },
+                    // TODO(antoyo): cast to u128 for unsigned comparison. See below.
                     IntPredicate::IntUGT => (ComparisonOp::Equals, 2),
                     IntPredicate::IntUGE => (ComparisonOp::GreaterThanEquals, 1),
                     IntPredicate::IntULT => (ComparisonOp::Equals, 0),
@@ -407,6 +477,18 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
                     rhs = self.context.new_cast(None, rhs, a_type);
                 }
             }
+            match op {
+                IntPredicate::IntUGT | IntPredicate::IntUGE | IntPredicate::IntULT | IntPredicate::IntULE => {
+                    if !a_type.is_vector() {
+                        let unsigned_type = a_type.to_unsigned(&self.cx);
+                        lhs = self.context.new_cast(None, lhs, unsigned_type);
+                        rhs = self.context.new_cast(None, rhs, unsigned_type);
+                    }
+                },
+                // TODO(antoyo): we probably need to handle signed comparison for unsigned
+                // integers.
+                _ => (),
+            }
             self.context.new_comparison(None, op.to_gcc_comparison(), lhs, rhs)
         }
     }
@@ -418,11 +500,10 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
             a ^ b
         }
         else {
-            let values = [
+            self.from_low_high_rvalues(a_type,
                 self.low(a) ^ self.low(b),
                 self.high(a) ^ self.high(b),
-            ];
-            self.context.new_array_constructor(None, a_type, &values)
+            )
         }
     }
 
@@ -468,12 +549,10 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
             let condition = self.gcc_icmp(IntPredicate::IntNE, self.gcc_and(b, sixty_four), zero);
             self.llbb().end_with_conditional(None, condition, then_block, else_block);
 
-            // TODO(antoyo): take endianness into account.
-            let values = [
+            let array_value = self.from_low_high_rvalues(a_type,
                 zero,
                 self.low(a) << (b - sixty_four),
-            ];
-            let array_value = self.context.new_array_constructor(None, a_type, &values);
+            );
             then_block.add_assignment(None, result, array_value);
             then_block.end_with_jump(None, after_block);
 
@@ -484,16 +563,16 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
             b0_block.end_with_jump(None, after_block);
 
             // NOTE: cast low to its unsigned type in order to perform a logical right shift.
+            // TODO(antoyo): adjust this ^ comment.
             let unsigned_type = native_int_type.to_unsigned(&self.cx);
             let casted_low = self.context.new_cast(None, self.low(a), unsigned_type);
             let shift_value = self.context.new_cast(None, sixty_four - b, unsigned_type);
             let high_low = self.context.new_cast(None, casted_low >> shift_value, native_int_type);
-            let values = [
+
+            let array_value = self.from_low_high_rvalues(a_type,
                 self.low(a) << b,
                 (self.high(a) << b) | high_low,
-            ];
-
-            let array_value = self.context.new_array_constructor(None, a_type, &values);
+            );
             actual_else_block.add_assignment(None, result, array_value);
             actual_else_block.end_with_jump(None, after_block);
 
@@ -509,16 +588,16 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
         let arg_type = arg.get_type();
         if !self.is_native_int_type(arg_type) {
             let native_int_type = arg_type.dyncast_array().expect("get element type");
-            let lsb = self.context.new_array_access(None, arg, self.context.new_rvalue_from_int(self.int_type, 0)).to_rvalue();
+            let lsb = self.low(arg);
             let swapped_lsb = self.gcc_bswap(lsb, width / 2);
             let swapped_lsb = self.context.new_cast(None, swapped_lsb, native_int_type);
-            let msb = self.context.new_array_access(None, arg, self.context.new_rvalue_from_int(self.int_type, 1)).to_rvalue();
+            let msb = self.high(arg);
             let swapped_msb = self.gcc_bswap(msb, width / 2);
             let swapped_msb = self.context.new_cast(None, swapped_msb, native_int_type);
 
             // NOTE: we also need to swap the two elements here, in addition to swapping inside
             // the elements themselves like done above.
-            return self.context.new_array_constructor(None, arg_type, &[swapped_msb, swapped_lsb]);
+            return self.from_low_high_rvalues(arg_type, swapped_msb, swapped_lsb);
         }
 
         // TODO(antoyo): check if it's faster to use string literals and a
@@ -546,7 +625,12 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
     }
 
     pub fn gcc_uint(&self, typ: Type<'gcc>, int: u64) -> RValue<'gcc> {
-        if self.is_native_int_type_or_bool(typ) {
+        if typ.is_u128(self) {
+            // FIXME(antoyo): libgccjit cannot create 128-bit values yet.
+            let num = self.context.new_rvalue_from_long(self.u64_type, int as i64);
+            self.gcc_int_cast(num, typ)
+        }
+        else if self.is_native_int_type_or_bool(typ) {
             self.context.new_rvalue_from_long(typ, u64::try_from(int).expect("u64::try_from") as i64)
         }
         else {
@@ -572,6 +656,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
             }
         }
         else if typ.is_i128(self) {
+            // FIXME(antoyo): libgccjit cannot create 128-bit values yet.
             let num = self.context.new_rvalue_from_long(self.u64_type, num as u64 as i64);
             self.gcc_int_cast(num, typ)
         }
@@ -616,11 +701,10 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
         else {
             assert!(!a_native && !b_native, "both types should either be native or non-native for or operation");
             let native_int_type = a_type.dyncast_array().expect("get element type");
-            let values = [
+            self.from_low_high_rvalues(a_type,
                 self.context.new_binary_op(None, operation, native_int_type, self.low(a), self.low(b)),
                 self.context.new_binary_op(None, operation, native_int_type, self.high(a), self.high(b)),
-            ];
-            self.context.new_array_constructor(None, a_type, &values)
+            )
         }
     }
 
@@ -644,11 +728,10 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
             let zero = self.context.new_rvalue_zero(value_type);
             let is_negative = self.context.new_comparison(None, ComparisonOp::LessThan, value, zero);
             let is_negative = self.gcc_int_cast(is_negative, dest_element_type);
-            let values = [
+            self.from_low_high_rvalues(dest_typ,
                 self.context.new_cast(None, value, dest_element_type),
                 self.context.new_unary_op(None, UnaryOp::Minus, dest_element_type, is_negative),
-            ];
-            self.context.new_array_constructor(None, dest_typ, &values)
+            )
         }
         else {
             // Since u128 and i128 are the only types that can be unsupported, we know the type of
@@ -726,20 +809,47 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
     }
 
     fn high(&self, value: RValue<'gcc>) -> RValue<'gcc> {
-        self.context.new_array_access(None, value, self.context.new_rvalue_from_int(self.int_type, 1))
+        let index =
+            match self.sess().target.options.endian {
+                Endian::Little => 1,
+                Endian::Big => 0,
+            };
+        self.context.new_array_access(None, value, self.context.new_rvalue_from_int(self.int_type, index))
             .to_rvalue()
     }
 
     fn low(&self, value: RValue<'gcc>) -> RValue<'gcc> {
-        self.context.new_array_access(None, value, self.context.new_rvalue_from_int(self.int_type, 0))
+        let index =
+            match self.sess().target.options.endian {
+                Endian::Little => 0,
+                Endian::Big => 1,
+            };
+        self.context.new_array_access(None, value, self.context.new_rvalue_from_int(self.int_type, index))
             .to_rvalue()
     }
 
+    fn from_low_high_rvalues(&self, typ: Type<'gcc>, low: RValue<'gcc>, high: RValue<'gcc>) -> RValue<'gcc> {
+        let (first, last) =
+            match self.sess().target.options.endian {
+                Endian::Little => (low, high),
+                Endian::Big => (high, low),
+            };
+
+        let values = [first, last];
+        self.context.new_array_constructor(None, typ, &values)
+    }
+
     fn from_low_high(&self, typ: Type<'gcc>, low: i64, high: i64) -> RValue<'gcc> {
+        let (first, last) =
+            match self.sess().target.options.endian {
+                Endian::Little => (low, high),
+                Endian::Big => (high, low),
+            };
+
         let native_int_type = typ.dyncast_array().expect("get element type");
         let values = [
-            self.context.new_rvalue_from_long(native_int_type, low),
-            self.context.new_rvalue_from_long(native_int_type, high),
+            self.context.new_rvalue_from_long(native_int_type, first),
+            self.context.new_rvalue_from_long(native_int_type, last),
         ];
         self.context.new_array_constructor(None, typ, &values)
     }
diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/archs.rs b/compiler/rustc_codegen_gcc/src/intrinsic/archs.rs
index 438eab78943..15d67385c3e 100644
--- a/compiler/rustc_codegen_gcc/src/intrinsic/archs.rs
+++ b/compiler/rustc_codegen_gcc/src/intrinsic/archs.rs
@@ -2254,6 +2254,1494 @@ match name {
     "llvm.hexagon.prefetch" => "__builtin_HEXAGON_prefetch",
     "llvm.hexagon.vmemcpy" => "__builtin_hexagon_vmemcpy",
     "llvm.hexagon.vmemset" => "__builtin_hexagon_vmemset",
+    // loongarch
+    "llvm.loongarch.asrtgt.d" => "__builtin_loongarch_asrtgt_d",
+    "llvm.loongarch.asrtle.d" => "__builtin_loongarch_asrtle_d",
+    "llvm.loongarch.break" => "__builtin_loongarch_break",
+    "llvm.loongarch.cacop.d" => "__builtin_loongarch_cacop_d",
+    "llvm.loongarch.cacop.w" => "__builtin_loongarch_cacop_w",
+    "llvm.loongarch.cpucfg" => "__builtin_loongarch_cpucfg",
+    "llvm.loongarch.crc.w.b.w" => "__builtin_loongarch_crc_w_b_w",
+    "llvm.loongarch.crc.w.d.w" => "__builtin_loongarch_crc_w_d_w",
+    "llvm.loongarch.crc.w.h.w" => "__builtin_loongarch_crc_w_h_w",
+    "llvm.loongarch.crc.w.w.w" => "__builtin_loongarch_crc_w_w_w",
+    "llvm.loongarch.crcc.w.b.w" => "__builtin_loongarch_crcc_w_b_w",
+    "llvm.loongarch.crcc.w.d.w" => "__builtin_loongarch_crcc_w_d_w",
+    "llvm.loongarch.crcc.w.h.w" => "__builtin_loongarch_crcc_w_h_w",
+    "llvm.loongarch.crcc.w.w.w" => "__builtin_loongarch_crcc_w_w_w",
+    "llvm.loongarch.csrrd.d" => "__builtin_loongarch_csrrd_d",
+    "llvm.loongarch.csrrd.w" => "__builtin_loongarch_csrrd_w",
+    "llvm.loongarch.csrwr.d" => "__builtin_loongarch_csrwr_d",
+    "llvm.loongarch.csrwr.w" => "__builtin_loongarch_csrwr_w",
+    "llvm.loongarch.csrxchg.d" => "__builtin_loongarch_csrxchg_d",
+    "llvm.loongarch.csrxchg.w" => "__builtin_loongarch_csrxchg_w",
+    "llvm.loongarch.dbar" => "__builtin_loongarch_dbar",
+    "llvm.loongarch.ibar" => "__builtin_loongarch_ibar",
+    "llvm.loongarch.iocsrrd.b" => "__builtin_loongarch_iocsrrd_b",
+    "llvm.loongarch.iocsrrd.d" => "__builtin_loongarch_iocsrrd_d",
+    "llvm.loongarch.iocsrrd.h" => "__builtin_loongarch_iocsrrd_h",
+    "llvm.loongarch.iocsrrd.w" => "__builtin_loongarch_iocsrrd_w",
+    "llvm.loongarch.iocsrwr.b" => "__builtin_loongarch_iocsrwr_b",
+    "llvm.loongarch.iocsrwr.d" => "__builtin_loongarch_iocsrwr_d",
+    "llvm.loongarch.iocsrwr.h" => "__builtin_loongarch_iocsrwr_h",
+    "llvm.loongarch.iocsrwr.w" => "__builtin_loongarch_iocsrwr_w",
+    "llvm.loongarch.lasx.vext2xv.d.b" => "__builtin_lasx_vext2xv_d_b",
+    "llvm.loongarch.lasx.vext2xv.d.h" => "__builtin_lasx_vext2xv_d_h",
+    "llvm.loongarch.lasx.vext2xv.d.w" => "__builtin_lasx_vext2xv_d_w",
+    "llvm.loongarch.lasx.vext2xv.du.bu" => "__builtin_lasx_vext2xv_du_bu",
+    "llvm.loongarch.lasx.vext2xv.du.hu" => "__builtin_lasx_vext2xv_du_hu",
+    "llvm.loongarch.lasx.vext2xv.du.wu" => "__builtin_lasx_vext2xv_du_wu",
+    "llvm.loongarch.lasx.vext2xv.h.b" => "__builtin_lasx_vext2xv_h_b",
+    "llvm.loongarch.lasx.vext2xv.hu.bu" => "__builtin_lasx_vext2xv_hu_bu",
+    "llvm.loongarch.lasx.vext2xv.w.b" => "__builtin_lasx_vext2xv_w_b",
+    "llvm.loongarch.lasx.vext2xv.w.h" => "__builtin_lasx_vext2xv_w_h",
+    "llvm.loongarch.lasx.vext2xv.wu.bu" => "__builtin_lasx_vext2xv_wu_bu",
+    "llvm.loongarch.lasx.vext2xv.wu.hu" => "__builtin_lasx_vext2xv_wu_hu",
+    "llvm.loongarch.lasx.xbnz.b" => "__builtin_lasx_xbnz_b",
+    "llvm.loongarch.lasx.xbnz.d" => "__builtin_lasx_xbnz_d",
+    "llvm.loongarch.lasx.xbnz.h" => "__builtin_lasx_xbnz_h",
+    "llvm.loongarch.lasx.xbnz.v" => "__builtin_lasx_xbnz_v",
+    "llvm.loongarch.lasx.xbnz.w" => "__builtin_lasx_xbnz_w",
+    "llvm.loongarch.lasx.xbz.b" => "__builtin_lasx_xbz_b",
+    "llvm.loongarch.lasx.xbz.d" => "__builtin_lasx_xbz_d",
+    "llvm.loongarch.lasx.xbz.h" => "__builtin_lasx_xbz_h",
+    "llvm.loongarch.lasx.xbz.v" => "__builtin_lasx_xbz_v",
+    "llvm.loongarch.lasx.xbz.w" => "__builtin_lasx_xbz_w",
+    "llvm.loongarch.lasx.xvabsd.b" => "__builtin_lasx_xvabsd_b",
+    "llvm.loongarch.lasx.xvabsd.bu" => "__builtin_lasx_xvabsd_bu",
+    "llvm.loongarch.lasx.xvabsd.d" => "__builtin_lasx_xvabsd_d",
+    "llvm.loongarch.lasx.xvabsd.du" => "__builtin_lasx_xvabsd_du",
+    "llvm.loongarch.lasx.xvabsd.h" => "__builtin_lasx_xvabsd_h",
+    "llvm.loongarch.lasx.xvabsd.hu" => "__builtin_lasx_xvabsd_hu",
+    "llvm.loongarch.lasx.xvabsd.w" => "__builtin_lasx_xvabsd_w",
+    "llvm.loongarch.lasx.xvabsd.wu" => "__builtin_lasx_xvabsd_wu",
+    "llvm.loongarch.lasx.xvadd.b" => "__builtin_lasx_xvadd_b",
+    "llvm.loongarch.lasx.xvadd.d" => "__builtin_lasx_xvadd_d",
+    "llvm.loongarch.lasx.xvadd.h" => "__builtin_lasx_xvadd_h",
+    "llvm.loongarch.lasx.xvadd.q" => "__builtin_lasx_xvadd_q",
+    "llvm.loongarch.lasx.xvadd.w" => "__builtin_lasx_xvadd_w",
+    "llvm.loongarch.lasx.xvadda.b" => "__builtin_lasx_xvadda_b",
+    "llvm.loongarch.lasx.xvadda.d" => "__builtin_lasx_xvadda_d",
+    "llvm.loongarch.lasx.xvadda.h" => "__builtin_lasx_xvadda_h",
+    "llvm.loongarch.lasx.xvadda.w" => "__builtin_lasx_xvadda_w",
+    "llvm.loongarch.lasx.xvaddi.bu" => "__builtin_lasx_xvaddi_bu",
+    "llvm.loongarch.lasx.xvaddi.du" => "__builtin_lasx_xvaddi_du",
+    "llvm.loongarch.lasx.xvaddi.hu" => "__builtin_lasx_xvaddi_hu",
+    "llvm.loongarch.lasx.xvaddi.wu" => "__builtin_lasx_xvaddi_wu",
+    "llvm.loongarch.lasx.xvaddwev.d.w" => "__builtin_lasx_xvaddwev_d_w",
+    "llvm.loongarch.lasx.xvaddwev.d.wu" => "__builtin_lasx_xvaddwev_d_wu",
+    "llvm.loongarch.lasx.xvaddwev.d.wu.w" => "__builtin_lasx_xvaddwev_d_wu_w",
+    "llvm.loongarch.lasx.xvaddwev.h.b" => "__builtin_lasx_xvaddwev_h_b",
+    "llvm.loongarch.lasx.xvaddwev.h.bu" => "__builtin_lasx_xvaddwev_h_bu",
+    "llvm.loongarch.lasx.xvaddwev.h.bu.b" => "__builtin_lasx_xvaddwev_h_bu_b",
+    "llvm.loongarch.lasx.xvaddwev.q.d" => "__builtin_lasx_xvaddwev_q_d",
+    "llvm.loongarch.lasx.xvaddwev.q.du" => "__builtin_lasx_xvaddwev_q_du",
+    "llvm.loongarch.lasx.xvaddwev.q.du.d" => "__builtin_lasx_xvaddwev_q_du_d",
+    "llvm.loongarch.lasx.xvaddwev.w.h" => "__builtin_lasx_xvaddwev_w_h",
+    "llvm.loongarch.lasx.xvaddwev.w.hu" => "__builtin_lasx_xvaddwev_w_hu",
+    "llvm.loongarch.lasx.xvaddwev.w.hu.h" => "__builtin_lasx_xvaddwev_w_hu_h",
+    "llvm.loongarch.lasx.xvaddwod.d.w" => "__builtin_lasx_xvaddwod_d_w",
+    "llvm.loongarch.lasx.xvaddwod.d.wu" => "__builtin_lasx_xvaddwod_d_wu",
+    "llvm.loongarch.lasx.xvaddwod.d.wu.w" => "__builtin_lasx_xvaddwod_d_wu_w",
+    "llvm.loongarch.lasx.xvaddwod.h.b" => "__builtin_lasx_xvaddwod_h_b",
+    "llvm.loongarch.lasx.xvaddwod.h.bu" => "__builtin_lasx_xvaddwod_h_bu",
+    "llvm.loongarch.lasx.xvaddwod.h.bu.b" => "__builtin_lasx_xvaddwod_h_bu_b",
+    "llvm.loongarch.lasx.xvaddwod.q.d" => "__builtin_lasx_xvaddwod_q_d",
+    "llvm.loongarch.lasx.xvaddwod.q.du" => "__builtin_lasx_xvaddwod_q_du",
+    "llvm.loongarch.lasx.xvaddwod.q.du.d" => "__builtin_lasx_xvaddwod_q_du_d",
+    "llvm.loongarch.lasx.xvaddwod.w.h" => "__builtin_lasx_xvaddwod_w_h",
+    "llvm.loongarch.lasx.xvaddwod.w.hu" => "__builtin_lasx_xvaddwod_w_hu",
+    "llvm.loongarch.lasx.xvaddwod.w.hu.h" => "__builtin_lasx_xvaddwod_w_hu_h",
+    "llvm.loongarch.lasx.xvand.v" => "__builtin_lasx_xvand_v",
+    "llvm.loongarch.lasx.xvandi.b" => "__builtin_lasx_xvandi_b",
+    "llvm.loongarch.lasx.xvandn.v" => "__builtin_lasx_xvandn_v",
+    "llvm.loongarch.lasx.xvavg.b" => "__builtin_lasx_xvavg_b",
+    "llvm.loongarch.lasx.xvavg.bu" => "__builtin_lasx_xvavg_bu",
+    "llvm.loongarch.lasx.xvavg.d" => "__builtin_lasx_xvavg_d",
+    "llvm.loongarch.lasx.xvavg.du" => "__builtin_lasx_xvavg_du",
+    "llvm.loongarch.lasx.xvavg.h" => "__builtin_lasx_xvavg_h",
+    "llvm.loongarch.lasx.xvavg.hu" => "__builtin_lasx_xvavg_hu",
+    "llvm.loongarch.lasx.xvavg.w" => "__builtin_lasx_xvavg_w",
+    "llvm.loongarch.lasx.xvavg.wu" => "__builtin_lasx_xvavg_wu",
+    "llvm.loongarch.lasx.xvavgr.b" => "__builtin_lasx_xvavgr_b",
+    "llvm.loongarch.lasx.xvavgr.bu" => "__builtin_lasx_xvavgr_bu",
+    "llvm.loongarch.lasx.xvavgr.d" => "__builtin_lasx_xvavgr_d",
+    "llvm.loongarch.lasx.xvavgr.du" => "__builtin_lasx_xvavgr_du",
+    "llvm.loongarch.lasx.xvavgr.h" => "__builtin_lasx_xvavgr_h",
+    "llvm.loongarch.lasx.xvavgr.hu" => "__builtin_lasx_xvavgr_hu",
+    "llvm.loongarch.lasx.xvavgr.w" => "__builtin_lasx_xvavgr_w",
+    "llvm.loongarch.lasx.xvavgr.wu" => "__builtin_lasx_xvavgr_wu",
+    "llvm.loongarch.lasx.xvbitclr.b" => "__builtin_lasx_xvbitclr_b",
+    "llvm.loongarch.lasx.xvbitclr.d" => "__builtin_lasx_xvbitclr_d",
+    "llvm.loongarch.lasx.xvbitclr.h" => "__builtin_lasx_xvbitclr_h",
+    "llvm.loongarch.lasx.xvbitclr.w" => "__builtin_lasx_xvbitclr_w",
+    "llvm.loongarch.lasx.xvbitclri.b" => "__builtin_lasx_xvbitclri_b",
+    "llvm.loongarch.lasx.xvbitclri.d" => "__builtin_lasx_xvbitclri_d",
+    "llvm.loongarch.lasx.xvbitclri.h" => "__builtin_lasx_xvbitclri_h",
+    "llvm.loongarch.lasx.xvbitclri.w" => "__builtin_lasx_xvbitclri_w",
+    "llvm.loongarch.lasx.xvbitrev.b" => "__builtin_lasx_xvbitrev_b",
+    "llvm.loongarch.lasx.xvbitrev.d" => "__builtin_lasx_xvbitrev_d",
+    "llvm.loongarch.lasx.xvbitrev.h" => "__builtin_lasx_xvbitrev_h",
+    "llvm.loongarch.lasx.xvbitrev.w" => "__builtin_lasx_xvbitrev_w",
+    "llvm.loongarch.lasx.xvbitrevi.b" => "__builtin_lasx_xvbitrevi_b",
+    "llvm.loongarch.lasx.xvbitrevi.d" => "__builtin_lasx_xvbitrevi_d",
+    "llvm.loongarch.lasx.xvbitrevi.h" => "__builtin_lasx_xvbitrevi_h",
+    "llvm.loongarch.lasx.xvbitrevi.w" => "__builtin_lasx_xvbitrevi_w",
+    "llvm.loongarch.lasx.xvbitsel.v" => "__builtin_lasx_xvbitsel_v",
+    "llvm.loongarch.lasx.xvbitseli.b" => "__builtin_lasx_xvbitseli_b",
+    "llvm.loongarch.lasx.xvbitset.b" => "__builtin_lasx_xvbitset_b",
+    "llvm.loongarch.lasx.xvbitset.d" => "__builtin_lasx_xvbitset_d",
+    "llvm.loongarch.lasx.xvbitset.h" => "__builtin_lasx_xvbitset_h",
+    "llvm.loongarch.lasx.xvbitset.w" => "__builtin_lasx_xvbitset_w",
+    "llvm.loongarch.lasx.xvbitseti.b" => "__builtin_lasx_xvbitseti_b",
+    "llvm.loongarch.lasx.xvbitseti.d" => "__builtin_lasx_xvbitseti_d",
+    "llvm.loongarch.lasx.xvbitseti.h" => "__builtin_lasx_xvbitseti_h",
+    "llvm.loongarch.lasx.xvbitseti.w" => "__builtin_lasx_xvbitseti_w",
+    "llvm.loongarch.lasx.xvbsll.v" => "__builtin_lasx_xvbsll_v",
+    "llvm.loongarch.lasx.xvbsrl.v" => "__builtin_lasx_xvbsrl_v",
+    "llvm.loongarch.lasx.xvclo.b" => "__builtin_lasx_xvclo_b",
+    "llvm.loongarch.lasx.xvclo.d" => "__builtin_lasx_xvclo_d",
+    "llvm.loongarch.lasx.xvclo.h" => "__builtin_lasx_xvclo_h",
+    "llvm.loongarch.lasx.xvclo.w" => "__builtin_lasx_xvclo_w",
+    "llvm.loongarch.lasx.xvclz.b" => "__builtin_lasx_xvclz_b",
+    "llvm.loongarch.lasx.xvclz.d" => "__builtin_lasx_xvclz_d",
+    "llvm.loongarch.lasx.xvclz.h" => "__builtin_lasx_xvclz_h",
+    "llvm.loongarch.lasx.xvclz.w" => "__builtin_lasx_xvclz_w",
+    "llvm.loongarch.lasx.xvdiv.b" => "__builtin_lasx_xvdiv_b",
+    "llvm.loongarch.lasx.xvdiv.bu" => "__builtin_lasx_xvdiv_bu",
+    "llvm.loongarch.lasx.xvdiv.d" => "__builtin_lasx_xvdiv_d",
+    "llvm.loongarch.lasx.xvdiv.du" => "__builtin_lasx_xvdiv_du",
+    "llvm.loongarch.lasx.xvdiv.h" => "__builtin_lasx_xvdiv_h",
+    "llvm.loongarch.lasx.xvdiv.hu" => "__builtin_lasx_xvdiv_hu",
+    "llvm.loongarch.lasx.xvdiv.w" => "__builtin_lasx_xvdiv_w",
+    "llvm.loongarch.lasx.xvdiv.wu" => "__builtin_lasx_xvdiv_wu",
+    "llvm.loongarch.lasx.xvexth.d.w" => "__builtin_lasx_xvexth_d_w",
+    "llvm.loongarch.lasx.xvexth.du.wu" => "__builtin_lasx_xvexth_du_wu",
+    "llvm.loongarch.lasx.xvexth.h.b" => "__builtin_lasx_xvexth_h_b",
+    "llvm.loongarch.lasx.xvexth.hu.bu" => "__builtin_lasx_xvexth_hu_bu",
+    "llvm.loongarch.lasx.xvexth.q.d" => "__builtin_lasx_xvexth_q_d",
+    "llvm.loongarch.lasx.xvexth.qu.du" => "__builtin_lasx_xvexth_qu_du",
+    "llvm.loongarch.lasx.xvexth.w.h" => "__builtin_lasx_xvexth_w_h",
+    "llvm.loongarch.lasx.xvexth.wu.hu" => "__builtin_lasx_xvexth_wu_hu",
+    "llvm.loongarch.lasx.xvextl.q.d" => "__builtin_lasx_xvextl_q_d",
+    "llvm.loongarch.lasx.xvextl.qu.du" => "__builtin_lasx_xvextl_qu_du",
+    "llvm.loongarch.lasx.xvextrins.b" => "__builtin_lasx_xvextrins_b",
+    "llvm.loongarch.lasx.xvextrins.d" => "__builtin_lasx_xvextrins_d",
+    "llvm.loongarch.lasx.xvextrins.h" => "__builtin_lasx_xvextrins_h",
+    "llvm.loongarch.lasx.xvextrins.w" => "__builtin_lasx_xvextrins_w",
+    "llvm.loongarch.lasx.xvfadd.d" => "__builtin_lasx_xvfadd_d",
+    "llvm.loongarch.lasx.xvfadd.s" => "__builtin_lasx_xvfadd_s",
+    "llvm.loongarch.lasx.xvfclass.d" => "__builtin_lasx_xvfclass_d",
+    "llvm.loongarch.lasx.xvfclass.s" => "__builtin_lasx_xvfclass_s",
+    "llvm.loongarch.lasx.xvfcmp.caf.d" => "__builtin_lasx_xvfcmp_caf_d",
+    "llvm.loongarch.lasx.xvfcmp.caf.s" => "__builtin_lasx_xvfcmp_caf_s",
+    "llvm.loongarch.lasx.xvfcmp.ceq.d" => "__builtin_lasx_xvfcmp_ceq_d",
+    "llvm.loongarch.lasx.xvfcmp.ceq.s" => "__builtin_lasx_xvfcmp_ceq_s",
+    "llvm.loongarch.lasx.xvfcmp.cle.d" => "__builtin_lasx_xvfcmp_cle_d",
+    "llvm.loongarch.lasx.xvfcmp.cle.s" => "__builtin_lasx_xvfcmp_cle_s",
+    "llvm.loongarch.lasx.xvfcmp.clt.d" => "__builtin_lasx_xvfcmp_clt_d",
+    "llvm.loongarch.lasx.xvfcmp.clt.s" => "__builtin_lasx_xvfcmp_clt_s",
+    "llvm.loongarch.lasx.xvfcmp.cne.d" => "__builtin_lasx_xvfcmp_cne_d",
+    "llvm.loongarch.lasx.xvfcmp.cne.s" => "__builtin_lasx_xvfcmp_cne_s",
+    "llvm.loongarch.lasx.xvfcmp.cor.d" => "__builtin_lasx_xvfcmp_cor_d",
+    "llvm.loongarch.lasx.xvfcmp.cor.s" => "__builtin_lasx_xvfcmp_cor_s",
+    "llvm.loongarch.lasx.xvfcmp.cueq.d" => "__builtin_lasx_xvfcmp_cueq_d",
+    "llvm.loongarch.lasx.xvfcmp.cueq.s" => "__builtin_lasx_xvfcmp_cueq_s",
+    "llvm.loongarch.lasx.xvfcmp.cule.d" => "__builtin_lasx_xvfcmp_cule_d",
+    "llvm.loongarch.lasx.xvfcmp.cule.s" => "__builtin_lasx_xvfcmp_cule_s",
+    "llvm.loongarch.lasx.xvfcmp.cult.d" => "__builtin_lasx_xvfcmp_cult_d",
+    "llvm.loongarch.lasx.xvfcmp.cult.s" => "__builtin_lasx_xvfcmp_cult_s",
+    "llvm.loongarch.lasx.xvfcmp.cun.d" => "__builtin_lasx_xvfcmp_cun_d",
+    "llvm.loongarch.lasx.xvfcmp.cun.s" => "__builtin_lasx_xvfcmp_cun_s",
+    "llvm.loongarch.lasx.xvfcmp.cune.d" => "__builtin_lasx_xvfcmp_cune_d",
+    "llvm.loongarch.lasx.xvfcmp.cune.s" => "__builtin_lasx_xvfcmp_cune_s",
+    "llvm.loongarch.lasx.xvfcmp.saf.d" => "__builtin_lasx_xvfcmp_saf_d",
+    "llvm.loongarch.lasx.xvfcmp.saf.s" => "__builtin_lasx_xvfcmp_saf_s",
+    "llvm.loongarch.lasx.xvfcmp.seq.d" => "__builtin_lasx_xvfcmp_seq_d",
+    "llvm.loongarch.lasx.xvfcmp.seq.s" => "__builtin_lasx_xvfcmp_seq_s",
+    "llvm.loongarch.lasx.xvfcmp.sle.d" => "__builtin_lasx_xvfcmp_sle_d",
+    "llvm.loongarch.lasx.xvfcmp.sle.s" => "__builtin_lasx_xvfcmp_sle_s",
+    "llvm.loongarch.lasx.xvfcmp.slt.d" => "__builtin_lasx_xvfcmp_slt_d",
+    "llvm.loongarch.lasx.xvfcmp.slt.s" => "__builtin_lasx_xvfcmp_slt_s",
+    "llvm.loongarch.lasx.xvfcmp.sne.d" => "__builtin_lasx_xvfcmp_sne_d",
+    "llvm.loongarch.lasx.xvfcmp.sne.s" => "__builtin_lasx_xvfcmp_sne_s",
+    "llvm.loongarch.lasx.xvfcmp.sor.d" => "__builtin_lasx_xvfcmp_sor_d",
+    "llvm.loongarch.lasx.xvfcmp.sor.s" => "__builtin_lasx_xvfcmp_sor_s",
+    "llvm.loongarch.lasx.xvfcmp.sueq.d" => "__builtin_lasx_xvfcmp_sueq_d",
+    "llvm.loongarch.lasx.xvfcmp.sueq.s" => "__builtin_lasx_xvfcmp_sueq_s",
+    "llvm.loongarch.lasx.xvfcmp.sule.d" => "__builtin_lasx_xvfcmp_sule_d",
+    "llvm.loongarch.lasx.xvfcmp.sule.s" => "__builtin_lasx_xvfcmp_sule_s",
+    "llvm.loongarch.lasx.xvfcmp.sult.d" => "__builtin_lasx_xvfcmp_sult_d",
+    "llvm.loongarch.lasx.xvfcmp.sult.s" => "__builtin_lasx_xvfcmp_sult_s",
+    "llvm.loongarch.lasx.xvfcmp.sun.d" => "__builtin_lasx_xvfcmp_sun_d",
+    "llvm.loongarch.lasx.xvfcmp.sun.s" => "__builtin_lasx_xvfcmp_sun_s",
+    "llvm.loongarch.lasx.xvfcmp.sune.d" => "__builtin_lasx_xvfcmp_sune_d",
+    "llvm.loongarch.lasx.xvfcmp.sune.s" => "__builtin_lasx_xvfcmp_sune_s",
+    "llvm.loongarch.lasx.xvfcvt.h.s" => "__builtin_lasx_xvfcvt_h_s",
+    "llvm.loongarch.lasx.xvfcvt.s.d" => "__builtin_lasx_xvfcvt_s_d",
+    "llvm.loongarch.lasx.xvfcvth.d.s" => "__builtin_lasx_xvfcvth_d_s",
+    "llvm.loongarch.lasx.xvfcvth.s.h" => "__builtin_lasx_xvfcvth_s_h",
+    "llvm.loongarch.lasx.xvfcvtl.d.s" => "__builtin_lasx_xvfcvtl_d_s",
+    "llvm.loongarch.lasx.xvfcvtl.s.h" => "__builtin_lasx_xvfcvtl_s_h",
+    "llvm.loongarch.lasx.xvfdiv.d" => "__builtin_lasx_xvfdiv_d",
+    "llvm.loongarch.lasx.xvfdiv.s" => "__builtin_lasx_xvfdiv_s",
+    "llvm.loongarch.lasx.xvffint.d.l" => "__builtin_lasx_xvffint_d_l",
+    "llvm.loongarch.lasx.xvffint.d.lu" => "__builtin_lasx_xvffint_d_lu",
+    "llvm.loongarch.lasx.xvffint.s.l" => "__builtin_lasx_xvffint_s_l",
+    "llvm.loongarch.lasx.xvffint.s.w" => "__builtin_lasx_xvffint_s_w",
+    "llvm.loongarch.lasx.xvffint.s.wu" => "__builtin_lasx_xvffint_s_wu",
+    "llvm.loongarch.lasx.xvffinth.d.w" => "__builtin_lasx_xvffinth_d_w",
+    "llvm.loongarch.lasx.xvffintl.d.w" => "__builtin_lasx_xvffintl_d_w",
+    "llvm.loongarch.lasx.xvflogb.d" => "__builtin_lasx_xvflogb_d",
+    "llvm.loongarch.lasx.xvflogb.s" => "__builtin_lasx_xvflogb_s",
+    "llvm.loongarch.lasx.xvfmadd.d" => "__builtin_lasx_xvfmadd_d",
+    "llvm.loongarch.lasx.xvfmadd.s" => "__builtin_lasx_xvfmadd_s",
+    "llvm.loongarch.lasx.xvfmax.d" => "__builtin_lasx_xvfmax_d",
+    "llvm.loongarch.lasx.xvfmax.s" => "__builtin_lasx_xvfmax_s",
+    "llvm.loongarch.lasx.xvfmaxa.d" => "__builtin_lasx_xvfmaxa_d",
+    "llvm.loongarch.lasx.xvfmaxa.s" => "__builtin_lasx_xvfmaxa_s",
+    "llvm.loongarch.lasx.xvfmin.d" => "__builtin_lasx_xvfmin_d",
+    "llvm.loongarch.lasx.xvfmin.s" => "__builtin_lasx_xvfmin_s",
+    "llvm.loongarch.lasx.xvfmina.d" => "__builtin_lasx_xvfmina_d",
+    "llvm.loongarch.lasx.xvfmina.s" => "__builtin_lasx_xvfmina_s",
+    "llvm.loongarch.lasx.xvfmsub.d" => "__builtin_lasx_xvfmsub_d",
+    "llvm.loongarch.lasx.xvfmsub.s" => "__builtin_lasx_xvfmsub_s",
+    "llvm.loongarch.lasx.xvfmul.d" => "__builtin_lasx_xvfmul_d",
+    "llvm.loongarch.lasx.xvfmul.s" => "__builtin_lasx_xvfmul_s",
+    "llvm.loongarch.lasx.xvfnmadd.d" => "__builtin_lasx_xvfnmadd_d",
+    "llvm.loongarch.lasx.xvfnmadd.s" => "__builtin_lasx_xvfnmadd_s",
+    "llvm.loongarch.lasx.xvfnmsub.d" => "__builtin_lasx_xvfnmsub_d",
+    "llvm.loongarch.lasx.xvfnmsub.s" => "__builtin_lasx_xvfnmsub_s",
+    "llvm.loongarch.lasx.xvfrecip.d" => "__builtin_lasx_xvfrecip_d",
+    "llvm.loongarch.lasx.xvfrecip.s" => "__builtin_lasx_xvfrecip_s",
+    "llvm.loongarch.lasx.xvfrint.d" => "__builtin_lasx_xvfrint_d",
+    "llvm.loongarch.lasx.xvfrint.s" => "__builtin_lasx_xvfrint_s",
+    "llvm.loongarch.lasx.xvfrintrm.d" => "__builtin_lasx_xvfrintrm_d",
+    "llvm.loongarch.lasx.xvfrintrm.s" => "__builtin_lasx_xvfrintrm_s",
+    "llvm.loongarch.lasx.xvfrintrne.d" => "__builtin_lasx_xvfrintrne_d",
+    "llvm.loongarch.lasx.xvfrintrne.s" => "__builtin_lasx_xvfrintrne_s",
+    "llvm.loongarch.lasx.xvfrintrp.d" => "__builtin_lasx_xvfrintrp_d",
+    "llvm.loongarch.lasx.xvfrintrp.s" => "__builtin_lasx_xvfrintrp_s",
+    "llvm.loongarch.lasx.xvfrintrz.d" => "__builtin_lasx_xvfrintrz_d",
+    "llvm.loongarch.lasx.xvfrintrz.s" => "__builtin_lasx_xvfrintrz_s",
+    "llvm.loongarch.lasx.xvfrsqrt.d" => "__builtin_lasx_xvfrsqrt_d",
+    "llvm.loongarch.lasx.xvfrsqrt.s" => "__builtin_lasx_xvfrsqrt_s",
+    "llvm.loongarch.lasx.xvfrstp.b" => "__builtin_lasx_xvfrstp_b",
+    "llvm.loongarch.lasx.xvfrstp.h" => "__builtin_lasx_xvfrstp_h",
+    "llvm.loongarch.lasx.xvfrstpi.b" => "__builtin_lasx_xvfrstpi_b",
+    "llvm.loongarch.lasx.xvfrstpi.h" => "__builtin_lasx_xvfrstpi_h",
+    "llvm.loongarch.lasx.xvfsqrt.d" => "__builtin_lasx_xvfsqrt_d",
+    "llvm.loongarch.lasx.xvfsqrt.s" => "__builtin_lasx_xvfsqrt_s",
+    "llvm.loongarch.lasx.xvfsub.d" => "__builtin_lasx_xvfsub_d",
+    "llvm.loongarch.lasx.xvfsub.s" => "__builtin_lasx_xvfsub_s",
+    "llvm.loongarch.lasx.xvftint.l.d" => "__builtin_lasx_xvftint_l_d",
+    "llvm.loongarch.lasx.xvftint.lu.d" => "__builtin_lasx_xvftint_lu_d",
+    "llvm.loongarch.lasx.xvftint.w.d" => "__builtin_lasx_xvftint_w_d",
+    "llvm.loongarch.lasx.xvftint.w.s" => "__builtin_lasx_xvftint_w_s",
+    "llvm.loongarch.lasx.xvftint.wu.s" => "__builtin_lasx_xvftint_wu_s",
+    "llvm.loongarch.lasx.xvftinth.l.s" => "__builtin_lasx_xvftinth_l_s",
+    "llvm.loongarch.lasx.xvftintl.l.s" => "__builtin_lasx_xvftintl_l_s",
+    "llvm.loongarch.lasx.xvftintrm.l.d" => "__builtin_lasx_xvftintrm_l_d",
+    "llvm.loongarch.lasx.xvftintrm.w.d" => "__builtin_lasx_xvftintrm_w_d",
+    "llvm.loongarch.lasx.xvftintrm.w.s" => "__builtin_lasx_xvftintrm_w_s",
+    "llvm.loongarch.lasx.xvftintrmh.l.s" => "__builtin_lasx_xvftintrmh_l_s",
+    "llvm.loongarch.lasx.xvftintrml.l.s" => "__builtin_lasx_xvftintrml_l_s",
+    "llvm.loongarch.lasx.xvftintrne.l.d" => "__builtin_lasx_xvftintrne_l_d",
+    "llvm.loongarch.lasx.xvftintrne.w.d" => "__builtin_lasx_xvftintrne_w_d",
+    "llvm.loongarch.lasx.xvftintrne.w.s" => "__builtin_lasx_xvftintrne_w_s",
+    "llvm.loongarch.lasx.xvftintrneh.l.s" => "__builtin_lasx_xvftintrneh_l_s",
+    "llvm.loongarch.lasx.xvftintrnel.l.s" => "__builtin_lasx_xvftintrnel_l_s",
+    "llvm.loongarch.lasx.xvftintrp.l.d" => "__builtin_lasx_xvftintrp_l_d",
+    "llvm.loongarch.lasx.xvftintrp.w.d" => "__builtin_lasx_xvftintrp_w_d",
+    "llvm.loongarch.lasx.xvftintrp.w.s" => "__builtin_lasx_xvftintrp_w_s",
+    "llvm.loongarch.lasx.xvftintrph.l.s" => "__builtin_lasx_xvftintrph_l_s",
+    "llvm.loongarch.lasx.xvftintrpl.l.s" => "__builtin_lasx_xvftintrpl_l_s",
+    "llvm.loongarch.lasx.xvftintrz.l.d" => "__builtin_lasx_xvftintrz_l_d",
+    "llvm.loongarch.lasx.xvftintrz.lu.d" => "__builtin_lasx_xvftintrz_lu_d",
+    "llvm.loongarch.lasx.xvftintrz.w.d" => "__builtin_lasx_xvftintrz_w_d",
+    "llvm.loongarch.lasx.xvftintrz.w.s" => "__builtin_lasx_xvftintrz_w_s",
+    "llvm.loongarch.lasx.xvftintrz.wu.s" => "__builtin_lasx_xvftintrz_wu_s",
+    "llvm.loongarch.lasx.xvftintrzh.l.s" => "__builtin_lasx_xvftintrzh_l_s",
+    "llvm.loongarch.lasx.xvftintrzl.l.s" => "__builtin_lasx_xvftintrzl_l_s",
+    "llvm.loongarch.lasx.xvhaddw.d.w" => "__builtin_lasx_xvhaddw_d_w",
+    "llvm.loongarch.lasx.xvhaddw.du.wu" => "__builtin_lasx_xvhaddw_du_wu",
+    "llvm.loongarch.lasx.xvhaddw.h.b" => "__builtin_lasx_xvhaddw_h_b",
+    "llvm.loongarch.lasx.xvhaddw.hu.bu" => "__builtin_lasx_xvhaddw_hu_bu",
+    "llvm.loongarch.lasx.xvhaddw.q.d" => "__builtin_lasx_xvhaddw_q_d",
+    "llvm.loongarch.lasx.xvhaddw.qu.du" => "__builtin_lasx_xvhaddw_qu_du",
+    "llvm.loongarch.lasx.xvhaddw.w.h" => "__builtin_lasx_xvhaddw_w_h",
+    "llvm.loongarch.lasx.xvhaddw.wu.hu" => "__builtin_lasx_xvhaddw_wu_hu",
+    "llvm.loongarch.lasx.xvhsubw.d.w" => "__builtin_lasx_xvhsubw_d_w",
+    "llvm.loongarch.lasx.xvhsubw.du.wu" => "__builtin_lasx_xvhsubw_du_wu",
+    "llvm.loongarch.lasx.xvhsubw.h.b" => "__builtin_lasx_xvhsubw_h_b",
+    "llvm.loongarch.lasx.xvhsubw.hu.bu" => "__builtin_lasx_xvhsubw_hu_bu",
+    "llvm.loongarch.lasx.xvhsubw.q.d" => "__builtin_lasx_xvhsubw_q_d",
+    "llvm.loongarch.lasx.xvhsubw.qu.du" => "__builtin_lasx_xvhsubw_qu_du",
+    "llvm.loongarch.lasx.xvhsubw.w.h" => "__builtin_lasx_xvhsubw_w_h",
+    "llvm.loongarch.lasx.xvhsubw.wu.hu" => "__builtin_lasx_xvhsubw_wu_hu",
+    "llvm.loongarch.lasx.xvilvh.b" => "__builtin_lasx_xvilvh_b",
+    "llvm.loongarch.lasx.xvilvh.d" => "__builtin_lasx_xvilvh_d",
+    "llvm.loongarch.lasx.xvilvh.h" => "__builtin_lasx_xvilvh_h",
+    "llvm.loongarch.lasx.xvilvh.w" => "__builtin_lasx_xvilvh_w",
+    "llvm.loongarch.lasx.xvilvl.b" => "__builtin_lasx_xvilvl_b",
+    "llvm.loongarch.lasx.xvilvl.d" => "__builtin_lasx_xvilvl_d",
+    "llvm.loongarch.lasx.xvilvl.h" => "__builtin_lasx_xvilvl_h",
+    "llvm.loongarch.lasx.xvilvl.w" => "__builtin_lasx_xvilvl_w",
+    "llvm.loongarch.lasx.xvinsgr2vr.d" => "__builtin_lasx_xvinsgr2vr_d",
+    "llvm.loongarch.lasx.xvinsgr2vr.w" => "__builtin_lasx_xvinsgr2vr_w",
+    "llvm.loongarch.lasx.xvinsve0.d" => "__builtin_lasx_xvinsve0_d",
+    "llvm.loongarch.lasx.xvinsve0.w" => "__builtin_lasx_xvinsve0_w",
+    "llvm.loongarch.lasx.xvld" => "__builtin_lasx_xvld",
+    "llvm.loongarch.lasx.xvldi" => "__builtin_lasx_xvldi",
+    "llvm.loongarch.lasx.xvldrepl.b" => "__builtin_lasx_xvldrepl_b",
+    "llvm.loongarch.lasx.xvldrepl.d" => "__builtin_lasx_xvldrepl_d",
+    "llvm.loongarch.lasx.xvldrepl.h" => "__builtin_lasx_xvldrepl_h",
+    "llvm.loongarch.lasx.xvldrepl.w" => "__builtin_lasx_xvldrepl_w",
+    "llvm.loongarch.lasx.xvldx" => "__builtin_lasx_xvldx",
+    "llvm.loongarch.lasx.xvmadd.b" => "__builtin_lasx_xvmadd_b",
+    "llvm.loongarch.lasx.xvmadd.d" => "__builtin_lasx_xvmadd_d",
+    "llvm.loongarch.lasx.xvmadd.h" => "__builtin_lasx_xvmadd_h",
+    "llvm.loongarch.lasx.xvmadd.w" => "__builtin_lasx_xvmadd_w",
+    "llvm.loongarch.lasx.xvmaddwev.d.w" => "__builtin_lasx_xvmaddwev_d_w",
+    "llvm.loongarch.lasx.xvmaddwev.d.wu" => "__builtin_lasx_xvmaddwev_d_wu",
+    "llvm.loongarch.lasx.xvmaddwev.d.wu.w" => "__builtin_lasx_xvmaddwev_d_wu_w",
+    "llvm.loongarch.lasx.xvmaddwev.h.b" => "__builtin_lasx_xvmaddwev_h_b",
+    "llvm.loongarch.lasx.xvmaddwev.h.bu" => "__builtin_lasx_xvmaddwev_h_bu",
+    "llvm.loongarch.lasx.xvmaddwev.h.bu.b" => "__builtin_lasx_xvmaddwev_h_bu_b",
+    "llvm.loongarch.lasx.xvmaddwev.q.d" => "__builtin_lasx_xvmaddwev_q_d",
+    "llvm.loongarch.lasx.xvmaddwev.q.du" => "__builtin_lasx_xvmaddwev_q_du",
+    "llvm.loongarch.lasx.xvmaddwev.q.du.d" => "__builtin_lasx_xvmaddwev_q_du_d",
+    "llvm.loongarch.lasx.xvmaddwev.w.h" => "__builtin_lasx_xvmaddwev_w_h",
+    "llvm.loongarch.lasx.xvmaddwev.w.hu" => "__builtin_lasx_xvmaddwev_w_hu",
+    "llvm.loongarch.lasx.xvmaddwev.w.hu.h" => "__builtin_lasx_xvmaddwev_w_hu_h",
+    "llvm.loongarch.lasx.xvmaddwod.d.w" => "__builtin_lasx_xvmaddwod_d_w",
+    "llvm.loongarch.lasx.xvmaddwod.d.wu" => "__builtin_lasx_xvmaddwod_d_wu",
+    "llvm.loongarch.lasx.xvmaddwod.d.wu.w" => "__builtin_lasx_xvmaddwod_d_wu_w",
+    "llvm.loongarch.lasx.xvmaddwod.h.b" => "__builtin_lasx_xvmaddwod_h_b",
+    "llvm.loongarch.lasx.xvmaddwod.h.bu" => "__builtin_lasx_xvmaddwod_h_bu",
+    "llvm.loongarch.lasx.xvmaddwod.h.bu.b" => "__builtin_lasx_xvmaddwod_h_bu_b",
+    "llvm.loongarch.lasx.xvmaddwod.q.d" => "__builtin_lasx_xvmaddwod_q_d",
+    "llvm.loongarch.lasx.xvmaddwod.q.du" => "__builtin_lasx_xvmaddwod_q_du",
+    "llvm.loongarch.lasx.xvmaddwod.q.du.d" => "__builtin_lasx_xvmaddwod_q_du_d",
+    "llvm.loongarch.lasx.xvmaddwod.w.h" => "__builtin_lasx_xvmaddwod_w_h",
+    "llvm.loongarch.lasx.xvmaddwod.w.hu" => "__builtin_lasx_xvmaddwod_w_hu",
+    "llvm.loongarch.lasx.xvmaddwod.w.hu.h" => "__builtin_lasx_xvmaddwod_w_hu_h",
+    "llvm.loongarch.lasx.xvmax.b" => "__builtin_lasx_xvmax_b",
+    "llvm.loongarch.lasx.xvmax.bu" => "__builtin_lasx_xvmax_bu",
+    "llvm.loongarch.lasx.xvmax.d" => "__builtin_lasx_xvmax_d",
+    "llvm.loongarch.lasx.xvmax.du" => "__builtin_lasx_xvmax_du",
+    "llvm.loongarch.lasx.xvmax.h" => "__builtin_lasx_xvmax_h",
+    "llvm.loongarch.lasx.xvmax.hu" => "__builtin_lasx_xvmax_hu",
+    "llvm.loongarch.lasx.xvmax.w" => "__builtin_lasx_xvmax_w",
+    "llvm.loongarch.lasx.xvmax.wu" => "__builtin_lasx_xvmax_wu",
+    "llvm.loongarch.lasx.xvmaxi.b" => "__builtin_lasx_xvmaxi_b",
+    "llvm.loongarch.lasx.xvmaxi.bu" => "__builtin_lasx_xvmaxi_bu",
+    "llvm.loongarch.lasx.xvmaxi.d" => "__builtin_lasx_xvmaxi_d",
+    "llvm.loongarch.lasx.xvmaxi.du" => "__builtin_lasx_xvmaxi_du",
+    "llvm.loongarch.lasx.xvmaxi.h" => "__builtin_lasx_xvmaxi_h",
+    "llvm.loongarch.lasx.xvmaxi.hu" => "__builtin_lasx_xvmaxi_hu",
+    "llvm.loongarch.lasx.xvmaxi.w" => "__builtin_lasx_xvmaxi_w",
+    "llvm.loongarch.lasx.xvmaxi.wu" => "__builtin_lasx_xvmaxi_wu",
+    "llvm.loongarch.lasx.xvmin.b" => "__builtin_lasx_xvmin_b",
+    "llvm.loongarch.lasx.xvmin.bu" => "__builtin_lasx_xvmin_bu",
+    "llvm.loongarch.lasx.xvmin.d" => "__builtin_lasx_xvmin_d",
+    "llvm.loongarch.lasx.xvmin.du" => "__builtin_lasx_xvmin_du",
+    "llvm.loongarch.lasx.xvmin.h" => "__builtin_lasx_xvmin_h",
+    "llvm.loongarch.lasx.xvmin.hu" => "__builtin_lasx_xvmin_hu",
+    "llvm.loongarch.lasx.xvmin.w" => "__builtin_lasx_xvmin_w",
+    "llvm.loongarch.lasx.xvmin.wu" => "__builtin_lasx_xvmin_wu",
+    "llvm.loongarch.lasx.xvmini.b" => "__builtin_lasx_xvmini_b",
+    "llvm.loongarch.lasx.xvmini.bu" => "__builtin_lasx_xvmini_bu",
+    "llvm.loongarch.lasx.xvmini.d" => "__builtin_lasx_xvmini_d",
+    "llvm.loongarch.lasx.xvmini.du" => "__builtin_lasx_xvmini_du",
+    "llvm.loongarch.lasx.xvmini.h" => "__builtin_lasx_xvmini_h",
+    "llvm.loongarch.lasx.xvmini.hu" => "__builtin_lasx_xvmini_hu",
+    "llvm.loongarch.lasx.xvmini.w" => "__builtin_lasx_xvmini_w",
+    "llvm.loongarch.lasx.xvmini.wu" => "__builtin_lasx_xvmini_wu",
+    "llvm.loongarch.lasx.xvmod.b" => "__builtin_lasx_xvmod_b",
+    "llvm.loongarch.lasx.xvmod.bu" => "__builtin_lasx_xvmod_bu",
+    "llvm.loongarch.lasx.xvmod.d" => "__builtin_lasx_xvmod_d",
+    "llvm.loongarch.lasx.xvmod.du" => "__builtin_lasx_xvmod_du",
+    "llvm.loongarch.lasx.xvmod.h" => "__builtin_lasx_xvmod_h",
+    "llvm.loongarch.lasx.xvmod.hu" => "__builtin_lasx_xvmod_hu",
+    "llvm.loongarch.lasx.xvmod.w" => "__builtin_lasx_xvmod_w",
+    "llvm.loongarch.lasx.xvmod.wu" => "__builtin_lasx_xvmod_wu",
+    "llvm.loongarch.lasx.xvmskgez.b" => "__builtin_lasx_xvmskgez_b",
+    "llvm.loongarch.lasx.xvmskltz.b" => "__builtin_lasx_xvmskltz_b",
+    "llvm.loongarch.lasx.xvmskltz.d" => "__builtin_lasx_xvmskltz_d",
+    "llvm.loongarch.lasx.xvmskltz.h" => "__builtin_lasx_xvmskltz_h",
+    "llvm.loongarch.lasx.xvmskltz.w" => "__builtin_lasx_xvmskltz_w",
+    "llvm.loongarch.lasx.xvmsknz.b" => "__builtin_lasx_xvmsknz_b",
+    "llvm.loongarch.lasx.xvmsub.b" => "__builtin_lasx_xvmsub_b",
+    "llvm.loongarch.lasx.xvmsub.d" => "__builtin_lasx_xvmsub_d",
+    "llvm.loongarch.lasx.xvmsub.h" => "__builtin_lasx_xvmsub_h",
+    "llvm.loongarch.lasx.xvmsub.w" => "__builtin_lasx_xvmsub_w",
+    "llvm.loongarch.lasx.xvmuh.b" => "__builtin_lasx_xvmuh_b",
+    "llvm.loongarch.lasx.xvmuh.bu" => "__builtin_lasx_xvmuh_bu",
+    "llvm.loongarch.lasx.xvmuh.d" => "__builtin_lasx_xvmuh_d",
+    "llvm.loongarch.lasx.xvmuh.du" => "__builtin_lasx_xvmuh_du",
+    "llvm.loongarch.lasx.xvmuh.h" => "__builtin_lasx_xvmuh_h",
+    "llvm.loongarch.lasx.xvmuh.hu" => "__builtin_lasx_xvmuh_hu",
+    "llvm.loongarch.lasx.xvmuh.w" => "__builtin_lasx_xvmuh_w",
+    "llvm.loongarch.lasx.xvmuh.wu" => "__builtin_lasx_xvmuh_wu",
+    "llvm.loongarch.lasx.xvmul.b" => "__builtin_lasx_xvmul_b",
+    "llvm.loongarch.lasx.xvmul.d" => "__builtin_lasx_xvmul_d",
+    "llvm.loongarch.lasx.xvmul.h" => "__builtin_lasx_xvmul_h",
+    "llvm.loongarch.lasx.xvmul.w" => "__builtin_lasx_xvmul_w",
+    "llvm.loongarch.lasx.xvmulwev.d.w" => "__builtin_lasx_xvmulwev_d_w",
+    "llvm.loongarch.lasx.xvmulwev.d.wu" => "__builtin_lasx_xvmulwev_d_wu",
+    "llvm.loongarch.lasx.xvmulwev.d.wu.w" => "__builtin_lasx_xvmulwev_d_wu_w",
+    "llvm.loongarch.lasx.xvmulwev.h.b" => "__builtin_lasx_xvmulwev_h_b",
+    "llvm.loongarch.lasx.xvmulwev.h.bu" => "__builtin_lasx_xvmulwev_h_bu",
+    "llvm.loongarch.lasx.xvmulwev.h.bu.b" => "__builtin_lasx_xvmulwev_h_bu_b",
+    "llvm.loongarch.lasx.xvmulwev.q.d" => "__builtin_lasx_xvmulwev_q_d",
+    "llvm.loongarch.lasx.xvmulwev.q.du" => "__builtin_lasx_xvmulwev_q_du",
+    "llvm.loongarch.lasx.xvmulwev.q.du.d" => "__builtin_lasx_xvmulwev_q_du_d",
+    "llvm.loongarch.lasx.xvmulwev.w.h" => "__builtin_lasx_xvmulwev_w_h",
+    "llvm.loongarch.lasx.xvmulwev.w.hu" => "__builtin_lasx_xvmulwev_w_hu",
+    "llvm.loongarch.lasx.xvmulwev.w.hu.h" => "__builtin_lasx_xvmulwev_w_hu_h",
+    "llvm.loongarch.lasx.xvmulwod.d.w" => "__builtin_lasx_xvmulwod_d_w",
+    "llvm.loongarch.lasx.xvmulwod.d.wu" => "__builtin_lasx_xvmulwod_d_wu",
+    "llvm.loongarch.lasx.xvmulwod.d.wu.w" => "__builtin_lasx_xvmulwod_d_wu_w",
+    "llvm.loongarch.lasx.xvmulwod.h.b" => "__builtin_lasx_xvmulwod_h_b",
+    "llvm.loongarch.lasx.xvmulwod.h.bu" => "__builtin_lasx_xvmulwod_h_bu",
+    "llvm.loongarch.lasx.xvmulwod.h.bu.b" => "__builtin_lasx_xvmulwod_h_bu_b",
+    "llvm.loongarch.lasx.xvmulwod.q.d" => "__builtin_lasx_xvmulwod_q_d",
+    "llvm.loongarch.lasx.xvmulwod.q.du" => "__builtin_lasx_xvmulwod_q_du",
+    "llvm.loongarch.lasx.xvmulwod.q.du.d" => "__builtin_lasx_xvmulwod_q_du_d",
+    "llvm.loongarch.lasx.xvmulwod.w.h" => "__builtin_lasx_xvmulwod_w_h",
+    "llvm.loongarch.lasx.xvmulwod.w.hu" => "__builtin_lasx_xvmulwod_w_hu",
+    "llvm.loongarch.lasx.xvmulwod.w.hu.h" => "__builtin_lasx_xvmulwod_w_hu_h",
+    "llvm.loongarch.lasx.xvneg.b" => "__builtin_lasx_xvneg_b",
+    "llvm.loongarch.lasx.xvneg.d" => "__builtin_lasx_xvneg_d",
+    "llvm.loongarch.lasx.xvneg.h" => "__builtin_lasx_xvneg_h",
+    "llvm.loongarch.lasx.xvneg.w" => "__builtin_lasx_xvneg_w",
+    "llvm.loongarch.lasx.xvnor.v" => "__builtin_lasx_xvnor_v",
+    "llvm.loongarch.lasx.xvnori.b" => "__builtin_lasx_xvnori_b",
+    "llvm.loongarch.lasx.xvor.v" => "__builtin_lasx_xvor_v",
+    "llvm.loongarch.lasx.xvori.b" => "__builtin_lasx_xvori_b",
+    "llvm.loongarch.lasx.xvorn.v" => "__builtin_lasx_xvorn_v",
+    "llvm.loongarch.lasx.xvpackev.b" => "__builtin_lasx_xvpackev_b",
+    "llvm.loongarch.lasx.xvpackev.d" => "__builtin_lasx_xvpackev_d",
+    "llvm.loongarch.lasx.xvpackev.h" => "__builtin_lasx_xvpackev_h",
+    "llvm.loongarch.lasx.xvpackev.w" => "__builtin_lasx_xvpackev_w",
+    "llvm.loongarch.lasx.xvpackod.b" => "__builtin_lasx_xvpackod_b",
+    "llvm.loongarch.lasx.xvpackod.d" => "__builtin_lasx_xvpackod_d",
+    "llvm.loongarch.lasx.xvpackod.h" => "__builtin_lasx_xvpackod_h",
+    "llvm.loongarch.lasx.xvpackod.w" => "__builtin_lasx_xvpackod_w",
+    "llvm.loongarch.lasx.xvpcnt.b" => "__builtin_lasx_xvpcnt_b",
+    "llvm.loongarch.lasx.xvpcnt.d" => "__builtin_lasx_xvpcnt_d",
+    "llvm.loongarch.lasx.xvpcnt.h" => "__builtin_lasx_xvpcnt_h",
+    "llvm.loongarch.lasx.xvpcnt.w" => "__builtin_lasx_xvpcnt_w",
+    "llvm.loongarch.lasx.xvperm.w" => "__builtin_lasx_xvperm_w",
+    "llvm.loongarch.lasx.xvpermi.d" => "__builtin_lasx_xvpermi_d",
+    "llvm.loongarch.lasx.xvpermi.q" => "__builtin_lasx_xvpermi_q",
+    "llvm.loongarch.lasx.xvpermi.w" => "__builtin_lasx_xvpermi_w",
+    "llvm.loongarch.lasx.xvpickev.b" => "__builtin_lasx_xvpickev_b",
+    "llvm.loongarch.lasx.xvpickev.d" => "__builtin_lasx_xvpickev_d",
+    "llvm.loongarch.lasx.xvpickev.h" => "__builtin_lasx_xvpickev_h",
+    "llvm.loongarch.lasx.xvpickev.w" => "__builtin_lasx_xvpickev_w",
+    "llvm.loongarch.lasx.xvpickod.b" => "__builtin_lasx_xvpickod_b",
+    "llvm.loongarch.lasx.xvpickod.d" => "__builtin_lasx_xvpickod_d",
+    "llvm.loongarch.lasx.xvpickod.h" => "__builtin_lasx_xvpickod_h",
+    "llvm.loongarch.lasx.xvpickod.w" => "__builtin_lasx_xvpickod_w",
+    "llvm.loongarch.lasx.xvpickve.d" => "__builtin_lasx_xvpickve_d",
+    "llvm.loongarch.lasx.xvpickve.d.f" => "__builtin_lasx_xvpickve_d_f",
+    "llvm.loongarch.lasx.xvpickve.w" => "__builtin_lasx_xvpickve_w",
+    "llvm.loongarch.lasx.xvpickve.w.f" => "__builtin_lasx_xvpickve_w_f",
+    "llvm.loongarch.lasx.xvpickve2gr.d" => "__builtin_lasx_xvpickve2gr_d",
+    "llvm.loongarch.lasx.xvpickve2gr.du" => "__builtin_lasx_xvpickve2gr_du",
+    "llvm.loongarch.lasx.xvpickve2gr.w" => "__builtin_lasx_xvpickve2gr_w",
+    "llvm.loongarch.lasx.xvpickve2gr.wu" => "__builtin_lasx_xvpickve2gr_wu",
+    "llvm.loongarch.lasx.xvrepl128vei.b" => "__builtin_lasx_xvrepl128vei_b",
+    "llvm.loongarch.lasx.xvrepl128vei.d" => "__builtin_lasx_xvrepl128vei_d",
+    "llvm.loongarch.lasx.xvrepl128vei.h" => "__builtin_lasx_xvrepl128vei_h",
+    "llvm.loongarch.lasx.xvrepl128vei.w" => "__builtin_lasx_xvrepl128vei_w",
+    "llvm.loongarch.lasx.xvreplgr2vr.b" => "__builtin_lasx_xvreplgr2vr_b",
+    "llvm.loongarch.lasx.xvreplgr2vr.d" => "__builtin_lasx_xvreplgr2vr_d",
+    "llvm.loongarch.lasx.xvreplgr2vr.h" => "__builtin_lasx_xvreplgr2vr_h",
+    "llvm.loongarch.lasx.xvreplgr2vr.w" => "__builtin_lasx_xvreplgr2vr_w",
+    "llvm.loongarch.lasx.xvrepli.b" => "__builtin_lasx_xvrepli_b",
+    "llvm.loongarch.lasx.xvrepli.d" => "__builtin_lasx_xvrepli_d",
+    "llvm.loongarch.lasx.xvrepli.h" => "__builtin_lasx_xvrepli_h",
+    "llvm.loongarch.lasx.xvrepli.w" => "__builtin_lasx_xvrepli_w",
+    "llvm.loongarch.lasx.xvreplve.b" => "__builtin_lasx_xvreplve_b",
+    "llvm.loongarch.lasx.xvreplve.d" => "__builtin_lasx_xvreplve_d",
+    "llvm.loongarch.lasx.xvreplve.h" => "__builtin_lasx_xvreplve_h",
+    "llvm.loongarch.lasx.xvreplve.w" => "__builtin_lasx_xvreplve_w",
+    "llvm.loongarch.lasx.xvreplve0.b" => "__builtin_lasx_xvreplve0_b",
+    "llvm.loongarch.lasx.xvreplve0.d" => "__builtin_lasx_xvreplve0_d",
+    "llvm.loongarch.lasx.xvreplve0.h" => "__builtin_lasx_xvreplve0_h",
+    "llvm.loongarch.lasx.xvreplve0.q" => "__builtin_lasx_xvreplve0_q",
+    "llvm.loongarch.lasx.xvreplve0.w" => "__builtin_lasx_xvreplve0_w",
+    "llvm.loongarch.lasx.xvrotr.b" => "__builtin_lasx_xvrotr_b",
+    "llvm.loongarch.lasx.xvrotr.d" => "__builtin_lasx_xvrotr_d",
+    "llvm.loongarch.lasx.xvrotr.h" => "__builtin_lasx_xvrotr_h",
+    "llvm.loongarch.lasx.xvrotr.w" => "__builtin_lasx_xvrotr_w",
+    "llvm.loongarch.lasx.xvrotri.b" => "__builtin_lasx_xvrotri_b",
+    "llvm.loongarch.lasx.xvrotri.d" => "__builtin_lasx_xvrotri_d",
+    "llvm.loongarch.lasx.xvrotri.h" => "__builtin_lasx_xvrotri_h",
+    "llvm.loongarch.lasx.xvrotri.w" => "__builtin_lasx_xvrotri_w",
+    "llvm.loongarch.lasx.xvsadd.b" => "__builtin_lasx_xvsadd_b",
+    "llvm.loongarch.lasx.xvsadd.bu" => "__builtin_lasx_xvsadd_bu",
+    "llvm.loongarch.lasx.xvsadd.d" => "__builtin_lasx_xvsadd_d",
+    "llvm.loongarch.lasx.xvsadd.du" => "__builtin_lasx_xvsadd_du",
+    "llvm.loongarch.lasx.xvsadd.h" => "__builtin_lasx_xvsadd_h",
+    "llvm.loongarch.lasx.xvsadd.hu" => "__builtin_lasx_xvsadd_hu",
+    "llvm.loongarch.lasx.xvsadd.w" => "__builtin_lasx_xvsadd_w",
+    "llvm.loongarch.lasx.xvsadd.wu" => "__builtin_lasx_xvsadd_wu",
+    "llvm.loongarch.lasx.xvsat.b" => "__builtin_lasx_xvsat_b",
+    "llvm.loongarch.lasx.xvsat.bu" => "__builtin_lasx_xvsat_bu",
+    "llvm.loongarch.lasx.xvsat.d" => "__builtin_lasx_xvsat_d",
+    "llvm.loongarch.lasx.xvsat.du" => "__builtin_lasx_xvsat_du",
+    "llvm.loongarch.lasx.xvsat.h" => "__builtin_lasx_xvsat_h",
+    "llvm.loongarch.lasx.xvsat.hu" => "__builtin_lasx_xvsat_hu",
+    "llvm.loongarch.lasx.xvsat.w" => "__builtin_lasx_xvsat_w",
+    "llvm.loongarch.lasx.xvsat.wu" => "__builtin_lasx_xvsat_wu",
+    "llvm.loongarch.lasx.xvseq.b" => "__builtin_lasx_xvseq_b",
+    "llvm.loongarch.lasx.xvseq.d" => "__builtin_lasx_xvseq_d",
+    "llvm.loongarch.lasx.xvseq.h" => "__builtin_lasx_xvseq_h",
+    "llvm.loongarch.lasx.xvseq.w" => "__builtin_lasx_xvseq_w",
+    "llvm.loongarch.lasx.xvseqi.b" => "__builtin_lasx_xvseqi_b",
+    "llvm.loongarch.lasx.xvseqi.d" => "__builtin_lasx_xvseqi_d",
+    "llvm.loongarch.lasx.xvseqi.h" => "__builtin_lasx_xvseqi_h",
+    "llvm.loongarch.lasx.xvseqi.w" => "__builtin_lasx_xvseqi_w",
+    "llvm.loongarch.lasx.xvshuf.b" => "__builtin_lasx_xvshuf_b",
+    "llvm.loongarch.lasx.xvshuf.d" => "__builtin_lasx_xvshuf_d",
+    "llvm.loongarch.lasx.xvshuf.h" => "__builtin_lasx_xvshuf_h",
+    "llvm.loongarch.lasx.xvshuf.w" => "__builtin_lasx_xvshuf_w",
+    "llvm.loongarch.lasx.xvshuf4i.b" => "__builtin_lasx_xvshuf4i_b",
+    "llvm.loongarch.lasx.xvshuf4i.d" => "__builtin_lasx_xvshuf4i_d",
+    "llvm.loongarch.lasx.xvshuf4i.h" => "__builtin_lasx_xvshuf4i_h",
+    "llvm.loongarch.lasx.xvshuf4i.w" => "__builtin_lasx_xvshuf4i_w",
+    "llvm.loongarch.lasx.xvsigncov.b" => "__builtin_lasx_xvsigncov_b",
+    "llvm.loongarch.lasx.xvsigncov.d" => "__builtin_lasx_xvsigncov_d",
+    "llvm.loongarch.lasx.xvsigncov.h" => "__builtin_lasx_xvsigncov_h",
+    "llvm.loongarch.lasx.xvsigncov.w" => "__builtin_lasx_xvsigncov_w",
+    "llvm.loongarch.lasx.xvsle.b" => "__builtin_lasx_xvsle_b",
+    "llvm.loongarch.lasx.xvsle.bu" => "__builtin_lasx_xvsle_bu",
+    "llvm.loongarch.lasx.xvsle.d" => "__builtin_lasx_xvsle_d",
+    "llvm.loongarch.lasx.xvsle.du" => "__builtin_lasx_xvsle_du",
+    "llvm.loongarch.lasx.xvsle.h" => "__builtin_lasx_xvsle_h",
+    "llvm.loongarch.lasx.xvsle.hu" => "__builtin_lasx_xvsle_hu",
+    "llvm.loongarch.lasx.xvsle.w" => "__builtin_lasx_xvsle_w",
+    "llvm.loongarch.lasx.xvsle.wu" => "__builtin_lasx_xvsle_wu",
+    "llvm.loongarch.lasx.xvslei.b" => "__builtin_lasx_xvslei_b",
+    "llvm.loongarch.lasx.xvslei.bu" => "__builtin_lasx_xvslei_bu",
+    "llvm.loongarch.lasx.xvslei.d" => "__builtin_lasx_xvslei_d",
+    "llvm.loongarch.lasx.xvslei.du" => "__builtin_lasx_xvslei_du",
+    "llvm.loongarch.lasx.xvslei.h" => "__builtin_lasx_xvslei_h",
+    "llvm.loongarch.lasx.xvslei.hu" => "__builtin_lasx_xvslei_hu",
+    "llvm.loongarch.lasx.xvslei.w" => "__builtin_lasx_xvslei_w",
+    "llvm.loongarch.lasx.xvslei.wu" => "__builtin_lasx_xvslei_wu",
+    "llvm.loongarch.lasx.xvsll.b" => "__builtin_lasx_xvsll_b",
+    "llvm.loongarch.lasx.xvsll.d" => "__builtin_lasx_xvsll_d",
+    "llvm.loongarch.lasx.xvsll.h" => "__builtin_lasx_xvsll_h",
+    "llvm.loongarch.lasx.xvsll.w" => "__builtin_lasx_xvsll_w",
+    "llvm.loongarch.lasx.xvslli.b" => "__builtin_lasx_xvslli_b",
+    "llvm.loongarch.lasx.xvslli.d" => "__builtin_lasx_xvslli_d",
+    "llvm.loongarch.lasx.xvslli.h" => "__builtin_lasx_xvslli_h",
+    "llvm.loongarch.lasx.xvslli.w" => "__builtin_lasx_xvslli_w",
+    "llvm.loongarch.lasx.xvsllwil.d.w" => "__builtin_lasx_xvsllwil_d_w",
+    "llvm.loongarch.lasx.xvsllwil.du.wu" => "__builtin_lasx_xvsllwil_du_wu",
+    "llvm.loongarch.lasx.xvsllwil.h.b" => "__builtin_lasx_xvsllwil_h_b",
+    "llvm.loongarch.lasx.xvsllwil.hu.bu" => "__builtin_lasx_xvsllwil_hu_bu",
+    "llvm.loongarch.lasx.xvsllwil.w.h" => "__builtin_lasx_xvsllwil_w_h",
+    "llvm.loongarch.lasx.xvsllwil.wu.hu" => "__builtin_lasx_xvsllwil_wu_hu",
+    "llvm.loongarch.lasx.xvslt.b" => "__builtin_lasx_xvslt_b",
+    "llvm.loongarch.lasx.xvslt.bu" => "__builtin_lasx_xvslt_bu",
+    "llvm.loongarch.lasx.xvslt.d" => "__builtin_lasx_xvslt_d",
+    "llvm.loongarch.lasx.xvslt.du" => "__builtin_lasx_xvslt_du",
+    "llvm.loongarch.lasx.xvslt.h" => "__builtin_lasx_xvslt_h",
+    "llvm.loongarch.lasx.xvslt.hu" => "__builtin_lasx_xvslt_hu",
+    "llvm.loongarch.lasx.xvslt.w" => "__builtin_lasx_xvslt_w",
+    "llvm.loongarch.lasx.xvslt.wu" => "__builtin_lasx_xvslt_wu",
+    "llvm.loongarch.lasx.xvslti.b" => "__builtin_lasx_xvslti_b",
+    "llvm.loongarch.lasx.xvslti.bu" => "__builtin_lasx_xvslti_bu",
+    "llvm.loongarch.lasx.xvslti.d" => "__builtin_lasx_xvslti_d",
+    "llvm.loongarch.lasx.xvslti.du" => "__builtin_lasx_xvslti_du",
+    "llvm.loongarch.lasx.xvslti.h" => "__builtin_lasx_xvslti_h",
+    "llvm.loongarch.lasx.xvslti.hu" => "__builtin_lasx_xvslti_hu",
+    "llvm.loongarch.lasx.xvslti.w" => "__builtin_lasx_xvslti_w",
+    "llvm.loongarch.lasx.xvslti.wu" => "__builtin_lasx_xvslti_wu",
+    "llvm.loongarch.lasx.xvsra.b" => "__builtin_lasx_xvsra_b",
+    "llvm.loongarch.lasx.xvsra.d" => "__builtin_lasx_xvsra_d",
+    "llvm.loongarch.lasx.xvsra.h" => "__builtin_lasx_xvsra_h",
+    "llvm.loongarch.lasx.xvsra.w" => "__builtin_lasx_xvsra_w",
+    "llvm.loongarch.lasx.xvsrai.b" => "__builtin_lasx_xvsrai_b",
+    "llvm.loongarch.lasx.xvsrai.d" => "__builtin_lasx_xvsrai_d",
+    "llvm.loongarch.lasx.xvsrai.h" => "__builtin_lasx_xvsrai_h",
+    "llvm.loongarch.lasx.xvsrai.w" => "__builtin_lasx_xvsrai_w",
+    "llvm.loongarch.lasx.xvsran.b.h" => "__builtin_lasx_xvsran_b_h",
+    "llvm.loongarch.lasx.xvsran.h.w" => "__builtin_lasx_xvsran_h_w",
+    "llvm.loongarch.lasx.xvsran.w.d" => "__builtin_lasx_xvsran_w_d",
+    "llvm.loongarch.lasx.xvsrani.b.h" => "__builtin_lasx_xvsrani_b_h",
+    "llvm.loongarch.lasx.xvsrani.d.q" => "__builtin_lasx_xvsrani_d_q",
+    "llvm.loongarch.lasx.xvsrani.h.w" => "__builtin_lasx_xvsrani_h_w",
+    "llvm.loongarch.lasx.xvsrani.w.d" => "__builtin_lasx_xvsrani_w_d",
+    "llvm.loongarch.lasx.xvsrar.b" => "__builtin_lasx_xvsrar_b",
+    "llvm.loongarch.lasx.xvsrar.d" => "__builtin_lasx_xvsrar_d",
+    "llvm.loongarch.lasx.xvsrar.h" => "__builtin_lasx_xvsrar_h",
+    "llvm.loongarch.lasx.xvsrar.w" => "__builtin_lasx_xvsrar_w",
+    "llvm.loongarch.lasx.xvsrari.b" => "__builtin_lasx_xvsrari_b",
+    "llvm.loongarch.lasx.xvsrari.d" => "__builtin_lasx_xvsrari_d",
+    "llvm.loongarch.lasx.xvsrari.h" => "__builtin_lasx_xvsrari_h",
+    "llvm.loongarch.lasx.xvsrari.w" => "__builtin_lasx_xvsrari_w",
+    "llvm.loongarch.lasx.xvsrarn.b.h" => "__builtin_lasx_xvsrarn_b_h",
+    "llvm.loongarch.lasx.xvsrarn.h.w" => "__builtin_lasx_xvsrarn_h_w",
+    "llvm.loongarch.lasx.xvsrarn.w.d" => "__builtin_lasx_xvsrarn_w_d",
+    "llvm.loongarch.lasx.xvsrarni.b.h" => "__builtin_lasx_xvsrarni_b_h",
+    "llvm.loongarch.lasx.xvsrarni.d.q" => "__builtin_lasx_xvsrarni_d_q",
+    "llvm.loongarch.lasx.xvsrarni.h.w" => "__builtin_lasx_xvsrarni_h_w",
+    "llvm.loongarch.lasx.xvsrarni.w.d" => "__builtin_lasx_xvsrarni_w_d",
+    "llvm.loongarch.lasx.xvsrl.b" => "__builtin_lasx_xvsrl_b",
+    "llvm.loongarch.lasx.xvsrl.d" => "__builtin_lasx_xvsrl_d",
+    "llvm.loongarch.lasx.xvsrl.h" => "__builtin_lasx_xvsrl_h",
+    "llvm.loongarch.lasx.xvsrl.w" => "__builtin_lasx_xvsrl_w",
+    "llvm.loongarch.lasx.xvsrli.b" => "__builtin_lasx_xvsrli_b",
+    "llvm.loongarch.lasx.xvsrli.d" => "__builtin_lasx_xvsrli_d",
+    "llvm.loongarch.lasx.xvsrli.h" => "__builtin_lasx_xvsrli_h",
+    "llvm.loongarch.lasx.xvsrli.w" => "__builtin_lasx_xvsrli_w",
+    "llvm.loongarch.lasx.xvsrln.b.h" => "__builtin_lasx_xvsrln_b_h",
+    "llvm.loongarch.lasx.xvsrln.h.w" => "__builtin_lasx_xvsrln_h_w",
+    "llvm.loongarch.lasx.xvsrln.w.d" => "__builtin_lasx_xvsrln_w_d",
+    "llvm.loongarch.lasx.xvsrlni.b.h" => "__builtin_lasx_xvsrlni_b_h",
+    "llvm.loongarch.lasx.xvsrlni.d.q" => "__builtin_lasx_xvsrlni_d_q",
+    "llvm.loongarch.lasx.xvsrlni.h.w" => "__builtin_lasx_xvsrlni_h_w",
+    "llvm.loongarch.lasx.xvsrlni.w.d" => "__builtin_lasx_xvsrlni_w_d",
+    "llvm.loongarch.lasx.xvsrlr.b" => "__builtin_lasx_xvsrlr_b",
+    "llvm.loongarch.lasx.xvsrlr.d" => "__builtin_lasx_xvsrlr_d",
+    "llvm.loongarch.lasx.xvsrlr.h" => "__builtin_lasx_xvsrlr_h",
+    "llvm.loongarch.lasx.xvsrlr.w" => "__builtin_lasx_xvsrlr_w",
+    "llvm.loongarch.lasx.xvsrlri.b" => "__builtin_lasx_xvsrlri_b",
+    "llvm.loongarch.lasx.xvsrlri.d" => "__builtin_lasx_xvsrlri_d",
+    "llvm.loongarch.lasx.xvsrlri.h" => "__builtin_lasx_xvsrlri_h",
+    "llvm.loongarch.lasx.xvsrlri.w" => "__builtin_lasx_xvsrlri_w",
+    "llvm.loongarch.lasx.xvsrlrn.b.h" => "__builtin_lasx_xvsrlrn_b_h",
+    "llvm.loongarch.lasx.xvsrlrn.h.w" => "__builtin_lasx_xvsrlrn_h_w",
+    "llvm.loongarch.lasx.xvsrlrn.w.d" => "__builtin_lasx_xvsrlrn_w_d",
+    "llvm.loongarch.lasx.xvsrlrni.b.h" => "__builtin_lasx_xvsrlrni_b_h",
+    "llvm.loongarch.lasx.xvsrlrni.d.q" => "__builtin_lasx_xvsrlrni_d_q",
+    "llvm.loongarch.lasx.xvsrlrni.h.w" => "__builtin_lasx_xvsrlrni_h_w",
+    "llvm.loongarch.lasx.xvsrlrni.w.d" => "__builtin_lasx_xvsrlrni_w_d",
+    "llvm.loongarch.lasx.xvssran.b.h" => "__builtin_lasx_xvssran_b_h",
+    "llvm.loongarch.lasx.xvssran.bu.h" => "__builtin_lasx_xvssran_bu_h",
+    "llvm.loongarch.lasx.xvssran.h.w" => "__builtin_lasx_xvssran_h_w",
+    "llvm.loongarch.lasx.xvssran.hu.w" => "__builtin_lasx_xvssran_hu_w",
+    "llvm.loongarch.lasx.xvssran.w.d" => "__builtin_lasx_xvssran_w_d",
+    "llvm.loongarch.lasx.xvssran.wu.d" => "__builtin_lasx_xvssran_wu_d",
+    "llvm.loongarch.lasx.xvssrani.b.h" => "__builtin_lasx_xvssrani_b_h",
+    "llvm.loongarch.lasx.xvssrani.bu.h" => "__builtin_lasx_xvssrani_bu_h",
+    "llvm.loongarch.lasx.xvssrani.d.q" => "__builtin_lasx_xvssrani_d_q",
+    "llvm.loongarch.lasx.xvssrani.du.q" => "__builtin_lasx_xvssrani_du_q",
+    "llvm.loongarch.lasx.xvssrani.h.w" => "__builtin_lasx_xvssrani_h_w",
+    "llvm.loongarch.lasx.xvssrani.hu.w" => "__builtin_lasx_xvssrani_hu_w",
+    "llvm.loongarch.lasx.xvssrani.w.d" => "__builtin_lasx_xvssrani_w_d",
+    "llvm.loongarch.lasx.xvssrani.wu.d" => "__builtin_lasx_xvssrani_wu_d",
+    "llvm.loongarch.lasx.xvssrarn.b.h" => "__builtin_lasx_xvssrarn_b_h",
+    "llvm.loongarch.lasx.xvssrarn.bu.h" => "__builtin_lasx_xvssrarn_bu_h",
+    "llvm.loongarch.lasx.xvssrarn.h.w" => "__builtin_lasx_xvssrarn_h_w",
+    "llvm.loongarch.lasx.xvssrarn.hu.w" => "__builtin_lasx_xvssrarn_hu_w",
+    "llvm.loongarch.lasx.xvssrarn.w.d" => "__builtin_lasx_xvssrarn_w_d",
+    "llvm.loongarch.lasx.xvssrarn.wu.d" => "__builtin_lasx_xvssrarn_wu_d",
+    "llvm.loongarch.lasx.xvssrarni.b.h" => "__builtin_lasx_xvssrarni_b_h",
+    "llvm.loongarch.lasx.xvssrarni.bu.h" => "__builtin_lasx_xvssrarni_bu_h",
+    "llvm.loongarch.lasx.xvssrarni.d.q" => "__builtin_lasx_xvssrarni_d_q",
+    "llvm.loongarch.lasx.xvssrarni.du.q" => "__builtin_lasx_xvssrarni_du_q",
+    "llvm.loongarch.lasx.xvssrarni.h.w" => "__builtin_lasx_xvssrarni_h_w",
+    "llvm.loongarch.lasx.xvssrarni.hu.w" => "__builtin_lasx_xvssrarni_hu_w",
+    "llvm.loongarch.lasx.xvssrarni.w.d" => "__builtin_lasx_xvssrarni_w_d",
+    "llvm.loongarch.lasx.xvssrarni.wu.d" => "__builtin_lasx_xvssrarni_wu_d",
+    "llvm.loongarch.lasx.xvssrln.b.h" => "__builtin_lasx_xvssrln_b_h",
+    "llvm.loongarch.lasx.xvssrln.bu.h" => "__builtin_lasx_xvssrln_bu_h",
+    "llvm.loongarch.lasx.xvssrln.h.w" => "__builtin_lasx_xvssrln_h_w",
+    "llvm.loongarch.lasx.xvssrln.hu.w" => "__builtin_lasx_xvssrln_hu_w",
+    "llvm.loongarch.lasx.xvssrln.w.d" => "__builtin_lasx_xvssrln_w_d",
+    "llvm.loongarch.lasx.xvssrln.wu.d" => "__builtin_lasx_xvssrln_wu_d",
+    "llvm.loongarch.lasx.xvssrlni.b.h" => "__builtin_lasx_xvssrlni_b_h",
+    "llvm.loongarch.lasx.xvssrlni.bu.h" => "__builtin_lasx_xvssrlni_bu_h",
+    "llvm.loongarch.lasx.xvssrlni.d.q" => "__builtin_lasx_xvssrlni_d_q",
+    "llvm.loongarch.lasx.xvssrlni.du.q" => "__builtin_lasx_xvssrlni_du_q",
+    "llvm.loongarch.lasx.xvssrlni.h.w" => "__builtin_lasx_xvssrlni_h_w",
+    "llvm.loongarch.lasx.xvssrlni.hu.w" => "__builtin_lasx_xvssrlni_hu_w",
+    "llvm.loongarch.lasx.xvssrlni.w.d" => "__builtin_lasx_xvssrlni_w_d",
+    "llvm.loongarch.lasx.xvssrlni.wu.d" => "__builtin_lasx_xvssrlni_wu_d",
+    "llvm.loongarch.lasx.xvssrlrn.b.h" => "__builtin_lasx_xvssrlrn_b_h",
+    "llvm.loongarch.lasx.xvssrlrn.bu.h" => "__builtin_lasx_xvssrlrn_bu_h",
+    "llvm.loongarch.lasx.xvssrlrn.h.w" => "__builtin_lasx_xvssrlrn_h_w",
+    "llvm.loongarch.lasx.xvssrlrn.hu.w" => "__builtin_lasx_xvssrlrn_hu_w",
+    "llvm.loongarch.lasx.xvssrlrn.w.d" => "__builtin_lasx_xvssrlrn_w_d",
+    "llvm.loongarch.lasx.xvssrlrn.wu.d" => "__builtin_lasx_xvssrlrn_wu_d",
+    "llvm.loongarch.lasx.xvssrlrni.b.h" => "__builtin_lasx_xvssrlrni_b_h",
+    "llvm.loongarch.lasx.xvssrlrni.bu.h" => "__builtin_lasx_xvssrlrni_bu_h",
+    "llvm.loongarch.lasx.xvssrlrni.d.q" => "__builtin_lasx_xvssrlrni_d_q",
+    "llvm.loongarch.lasx.xvssrlrni.du.q" => "__builtin_lasx_xvssrlrni_du_q",
+    "llvm.loongarch.lasx.xvssrlrni.h.w" => "__builtin_lasx_xvssrlrni_h_w",
+    "llvm.loongarch.lasx.xvssrlrni.hu.w" => "__builtin_lasx_xvssrlrni_hu_w",
+    "llvm.loongarch.lasx.xvssrlrni.w.d" => "__builtin_lasx_xvssrlrni_w_d",
+    "llvm.loongarch.lasx.xvssrlrni.wu.d" => "__builtin_lasx_xvssrlrni_wu_d",
+    "llvm.loongarch.lasx.xvssub.b" => "__builtin_lasx_xvssub_b",
+    "llvm.loongarch.lasx.xvssub.bu" => "__builtin_lasx_xvssub_bu",
+    "llvm.loongarch.lasx.xvssub.d" => "__builtin_lasx_xvssub_d",
+    "llvm.loongarch.lasx.xvssub.du" => "__builtin_lasx_xvssub_du",
+    "llvm.loongarch.lasx.xvssub.h" => "__builtin_lasx_xvssub_h",
+    "llvm.loongarch.lasx.xvssub.hu" => "__builtin_lasx_xvssub_hu",
+    "llvm.loongarch.lasx.xvssub.w" => "__builtin_lasx_xvssub_w",
+    "llvm.loongarch.lasx.xvssub.wu" => "__builtin_lasx_xvssub_wu",
+    "llvm.loongarch.lasx.xvst" => "__builtin_lasx_xvst",
+    "llvm.loongarch.lasx.xvstelm.b" => "__builtin_lasx_xvstelm_b",
+    "llvm.loongarch.lasx.xvstelm.d" => "__builtin_lasx_xvstelm_d",
+    "llvm.loongarch.lasx.xvstelm.h" => "__builtin_lasx_xvstelm_h",
+    "llvm.loongarch.lasx.xvstelm.w" => "__builtin_lasx_xvstelm_w",
+    "llvm.loongarch.lasx.xvstx" => "__builtin_lasx_xvstx",
+    "llvm.loongarch.lasx.xvsub.b" => "__builtin_lasx_xvsub_b",
+    "llvm.loongarch.lasx.xvsub.d" => "__builtin_lasx_xvsub_d",
+    "llvm.loongarch.lasx.xvsub.h" => "__builtin_lasx_xvsub_h",
+    "llvm.loongarch.lasx.xvsub.q" => "__builtin_lasx_xvsub_q",
+    "llvm.loongarch.lasx.xvsub.w" => "__builtin_lasx_xvsub_w",
+    "llvm.loongarch.lasx.xvsubi.bu" => "__builtin_lasx_xvsubi_bu",
+    "llvm.loongarch.lasx.xvsubi.du" => "__builtin_lasx_xvsubi_du",
+    "llvm.loongarch.lasx.xvsubi.hu" => "__builtin_lasx_xvsubi_hu",
+    "llvm.loongarch.lasx.xvsubi.wu" => "__builtin_lasx_xvsubi_wu",
+    "llvm.loongarch.lasx.xvsubwev.d.w" => "__builtin_lasx_xvsubwev_d_w",
+    "llvm.loongarch.lasx.xvsubwev.d.wu" => "__builtin_lasx_xvsubwev_d_wu",
+    "llvm.loongarch.lasx.xvsubwev.h.b" => "__builtin_lasx_xvsubwev_h_b",
+    "llvm.loongarch.lasx.xvsubwev.h.bu" => "__builtin_lasx_xvsubwev_h_bu",
+    "llvm.loongarch.lasx.xvsubwev.q.d" => "__builtin_lasx_xvsubwev_q_d",
+    "llvm.loongarch.lasx.xvsubwev.q.du" => "__builtin_lasx_xvsubwev_q_du",
+    "llvm.loongarch.lasx.xvsubwev.w.h" => "__builtin_lasx_xvsubwev_w_h",
+    "llvm.loongarch.lasx.xvsubwev.w.hu" => "__builtin_lasx_xvsubwev_w_hu",
+    "llvm.loongarch.lasx.xvsubwod.d.w" => "__builtin_lasx_xvsubwod_d_w",
+    "llvm.loongarch.lasx.xvsubwod.d.wu" => "__builtin_lasx_xvsubwod_d_wu",
+    "llvm.loongarch.lasx.xvsubwod.h.b" => "__builtin_lasx_xvsubwod_h_b",
+    "llvm.loongarch.lasx.xvsubwod.h.bu" => "__builtin_lasx_xvsubwod_h_bu",
+    "llvm.loongarch.lasx.xvsubwod.q.d" => "__builtin_lasx_xvsubwod_q_d",
+    "llvm.loongarch.lasx.xvsubwod.q.du" => "__builtin_lasx_xvsubwod_q_du",
+    "llvm.loongarch.lasx.xvsubwod.w.h" => "__builtin_lasx_xvsubwod_w_h",
+    "llvm.loongarch.lasx.xvsubwod.w.hu" => "__builtin_lasx_xvsubwod_w_hu",
+    "llvm.loongarch.lasx.xvxor.v" => "__builtin_lasx_xvxor_v",
+    "llvm.loongarch.lasx.xvxori.b" => "__builtin_lasx_xvxori_b",
+    "llvm.loongarch.lddir.d" => "__builtin_loongarch_lddir_d",
+    "llvm.loongarch.ldpte.d" => "__builtin_loongarch_ldpte_d",
+    "llvm.loongarch.lsx.bnz.b" => "__builtin_lsx_bnz_b",
+    "llvm.loongarch.lsx.bnz.d" => "__builtin_lsx_bnz_d",
+    "llvm.loongarch.lsx.bnz.h" => "__builtin_lsx_bnz_h",
+    "llvm.loongarch.lsx.bnz.v" => "__builtin_lsx_bnz_v",
+    "llvm.loongarch.lsx.bnz.w" => "__builtin_lsx_bnz_w",
+    "llvm.loongarch.lsx.bz.b" => "__builtin_lsx_bz_b",
+    "llvm.loongarch.lsx.bz.d" => "__builtin_lsx_bz_d",
+    "llvm.loongarch.lsx.bz.h" => "__builtin_lsx_bz_h",
+    "llvm.loongarch.lsx.bz.v" => "__builtin_lsx_bz_v",
+    "llvm.loongarch.lsx.bz.w" => "__builtin_lsx_bz_w",
+    "llvm.loongarch.lsx.vabsd.b" => "__builtin_lsx_vabsd_b",
+    "llvm.loongarch.lsx.vabsd.bu" => "__builtin_lsx_vabsd_bu",
+    "llvm.loongarch.lsx.vabsd.d" => "__builtin_lsx_vabsd_d",
+    "llvm.loongarch.lsx.vabsd.du" => "__builtin_lsx_vabsd_du",
+    "llvm.loongarch.lsx.vabsd.h" => "__builtin_lsx_vabsd_h",
+    "llvm.loongarch.lsx.vabsd.hu" => "__builtin_lsx_vabsd_hu",
+    "llvm.loongarch.lsx.vabsd.w" => "__builtin_lsx_vabsd_w",
+    "llvm.loongarch.lsx.vabsd.wu" => "__builtin_lsx_vabsd_wu",
+    "llvm.loongarch.lsx.vadd.b" => "__builtin_lsx_vadd_b",
+    "llvm.loongarch.lsx.vadd.d" => "__builtin_lsx_vadd_d",
+    "llvm.loongarch.lsx.vadd.h" => "__builtin_lsx_vadd_h",
+    "llvm.loongarch.lsx.vadd.q" => "__builtin_lsx_vadd_q",
+    "llvm.loongarch.lsx.vadd.w" => "__builtin_lsx_vadd_w",
+    "llvm.loongarch.lsx.vadda.b" => "__builtin_lsx_vadda_b",
+    "llvm.loongarch.lsx.vadda.d" => "__builtin_lsx_vadda_d",
+    "llvm.loongarch.lsx.vadda.h" => "__builtin_lsx_vadda_h",
+    "llvm.loongarch.lsx.vadda.w" => "__builtin_lsx_vadda_w",
+    "llvm.loongarch.lsx.vaddi.bu" => "__builtin_lsx_vaddi_bu",
+    "llvm.loongarch.lsx.vaddi.du" => "__builtin_lsx_vaddi_du",
+    "llvm.loongarch.lsx.vaddi.hu" => "__builtin_lsx_vaddi_hu",
+    "llvm.loongarch.lsx.vaddi.wu" => "__builtin_lsx_vaddi_wu",
+    "llvm.loongarch.lsx.vaddwev.d.w" => "__builtin_lsx_vaddwev_d_w",
+    "llvm.loongarch.lsx.vaddwev.d.wu" => "__builtin_lsx_vaddwev_d_wu",
+    "llvm.loongarch.lsx.vaddwev.d.wu.w" => "__builtin_lsx_vaddwev_d_wu_w",
+    "llvm.loongarch.lsx.vaddwev.h.b" => "__builtin_lsx_vaddwev_h_b",
+    "llvm.loongarch.lsx.vaddwev.h.bu" => "__builtin_lsx_vaddwev_h_bu",
+    "llvm.loongarch.lsx.vaddwev.h.bu.b" => "__builtin_lsx_vaddwev_h_bu_b",
+    "llvm.loongarch.lsx.vaddwev.q.d" => "__builtin_lsx_vaddwev_q_d",
+    "llvm.loongarch.lsx.vaddwev.q.du" => "__builtin_lsx_vaddwev_q_du",
+    "llvm.loongarch.lsx.vaddwev.q.du.d" => "__builtin_lsx_vaddwev_q_du_d",
+    "llvm.loongarch.lsx.vaddwev.w.h" => "__builtin_lsx_vaddwev_w_h",
+    "llvm.loongarch.lsx.vaddwev.w.hu" => "__builtin_lsx_vaddwev_w_hu",
+    "llvm.loongarch.lsx.vaddwev.w.hu.h" => "__builtin_lsx_vaddwev_w_hu_h",
+    "llvm.loongarch.lsx.vaddwod.d.w" => "__builtin_lsx_vaddwod_d_w",
+    "llvm.loongarch.lsx.vaddwod.d.wu" => "__builtin_lsx_vaddwod_d_wu",
+    "llvm.loongarch.lsx.vaddwod.d.wu.w" => "__builtin_lsx_vaddwod_d_wu_w",
+    "llvm.loongarch.lsx.vaddwod.h.b" => "__builtin_lsx_vaddwod_h_b",
+    "llvm.loongarch.lsx.vaddwod.h.bu" => "__builtin_lsx_vaddwod_h_bu",
+    "llvm.loongarch.lsx.vaddwod.h.bu.b" => "__builtin_lsx_vaddwod_h_bu_b",
+    "llvm.loongarch.lsx.vaddwod.q.d" => "__builtin_lsx_vaddwod_q_d",
+    "llvm.loongarch.lsx.vaddwod.q.du" => "__builtin_lsx_vaddwod_q_du",
+    "llvm.loongarch.lsx.vaddwod.q.du.d" => "__builtin_lsx_vaddwod_q_du_d",
+    "llvm.loongarch.lsx.vaddwod.w.h" => "__builtin_lsx_vaddwod_w_h",
+    "llvm.loongarch.lsx.vaddwod.w.hu" => "__builtin_lsx_vaddwod_w_hu",
+    "llvm.loongarch.lsx.vaddwod.w.hu.h" => "__builtin_lsx_vaddwod_w_hu_h",
+    "llvm.loongarch.lsx.vand.v" => "__builtin_lsx_vand_v",
+    "llvm.loongarch.lsx.vandi.b" => "__builtin_lsx_vandi_b",
+    "llvm.loongarch.lsx.vandn.v" => "__builtin_lsx_vandn_v",
+    "llvm.loongarch.lsx.vavg.b" => "__builtin_lsx_vavg_b",
+    "llvm.loongarch.lsx.vavg.bu" => "__builtin_lsx_vavg_bu",
+    "llvm.loongarch.lsx.vavg.d" => "__builtin_lsx_vavg_d",
+    "llvm.loongarch.lsx.vavg.du" => "__builtin_lsx_vavg_du",
+    "llvm.loongarch.lsx.vavg.h" => "__builtin_lsx_vavg_h",
+    "llvm.loongarch.lsx.vavg.hu" => "__builtin_lsx_vavg_hu",
+    "llvm.loongarch.lsx.vavg.w" => "__builtin_lsx_vavg_w",
+    "llvm.loongarch.lsx.vavg.wu" => "__builtin_lsx_vavg_wu",
+    "llvm.loongarch.lsx.vavgr.b" => "__builtin_lsx_vavgr_b",
+    "llvm.loongarch.lsx.vavgr.bu" => "__builtin_lsx_vavgr_bu",
+    "llvm.loongarch.lsx.vavgr.d" => "__builtin_lsx_vavgr_d",
+    "llvm.loongarch.lsx.vavgr.du" => "__builtin_lsx_vavgr_du",
+    "llvm.loongarch.lsx.vavgr.h" => "__builtin_lsx_vavgr_h",
+    "llvm.loongarch.lsx.vavgr.hu" => "__builtin_lsx_vavgr_hu",
+    "llvm.loongarch.lsx.vavgr.w" => "__builtin_lsx_vavgr_w",
+    "llvm.loongarch.lsx.vavgr.wu" => "__builtin_lsx_vavgr_wu",
+    "llvm.loongarch.lsx.vbitclr.b" => "__builtin_lsx_vbitclr_b",
+    "llvm.loongarch.lsx.vbitclr.d" => "__builtin_lsx_vbitclr_d",
+    "llvm.loongarch.lsx.vbitclr.h" => "__builtin_lsx_vbitclr_h",
+    "llvm.loongarch.lsx.vbitclr.w" => "__builtin_lsx_vbitclr_w",
+    "llvm.loongarch.lsx.vbitclri.b" => "__builtin_lsx_vbitclri_b",
+    "llvm.loongarch.lsx.vbitclri.d" => "__builtin_lsx_vbitclri_d",
+    "llvm.loongarch.lsx.vbitclri.h" => "__builtin_lsx_vbitclri_h",
+    "llvm.loongarch.lsx.vbitclri.w" => "__builtin_lsx_vbitclri_w",
+    "llvm.loongarch.lsx.vbitrev.b" => "__builtin_lsx_vbitrev_b",
+    "llvm.loongarch.lsx.vbitrev.d" => "__builtin_lsx_vbitrev_d",
+    "llvm.loongarch.lsx.vbitrev.h" => "__builtin_lsx_vbitrev_h",
+    "llvm.loongarch.lsx.vbitrev.w" => "__builtin_lsx_vbitrev_w",
+    "llvm.loongarch.lsx.vbitrevi.b" => "__builtin_lsx_vbitrevi_b",
+    "llvm.loongarch.lsx.vbitrevi.d" => "__builtin_lsx_vbitrevi_d",
+    "llvm.loongarch.lsx.vbitrevi.h" => "__builtin_lsx_vbitrevi_h",
+    "llvm.loongarch.lsx.vbitrevi.w" => "__builtin_lsx_vbitrevi_w",
+    "llvm.loongarch.lsx.vbitsel.v" => "__builtin_lsx_vbitsel_v",
+    "llvm.loongarch.lsx.vbitseli.b" => "__builtin_lsx_vbitseli_b",
+    "llvm.loongarch.lsx.vbitset.b" => "__builtin_lsx_vbitset_b",
+    "llvm.loongarch.lsx.vbitset.d" => "__builtin_lsx_vbitset_d",
+    "llvm.loongarch.lsx.vbitset.h" => "__builtin_lsx_vbitset_h",
+    "llvm.loongarch.lsx.vbitset.w" => "__builtin_lsx_vbitset_w",
+    "llvm.loongarch.lsx.vbitseti.b" => "__builtin_lsx_vbitseti_b",
+    "llvm.loongarch.lsx.vbitseti.d" => "__builtin_lsx_vbitseti_d",
+    "llvm.loongarch.lsx.vbitseti.h" => "__builtin_lsx_vbitseti_h",
+    "llvm.loongarch.lsx.vbitseti.w" => "__builtin_lsx_vbitseti_w",
+    "llvm.loongarch.lsx.vbsll.v" => "__builtin_lsx_vbsll_v",
+    "llvm.loongarch.lsx.vbsrl.v" => "__builtin_lsx_vbsrl_v",
+    "llvm.loongarch.lsx.vclo.b" => "__builtin_lsx_vclo_b",
+    "llvm.loongarch.lsx.vclo.d" => "__builtin_lsx_vclo_d",
+    "llvm.loongarch.lsx.vclo.h" => "__builtin_lsx_vclo_h",
+    "llvm.loongarch.lsx.vclo.w" => "__builtin_lsx_vclo_w",
+    "llvm.loongarch.lsx.vclz.b" => "__builtin_lsx_vclz_b",
+    "llvm.loongarch.lsx.vclz.d" => "__builtin_lsx_vclz_d",
+    "llvm.loongarch.lsx.vclz.h" => "__builtin_lsx_vclz_h",
+    "llvm.loongarch.lsx.vclz.w" => "__builtin_lsx_vclz_w",
+    "llvm.loongarch.lsx.vdiv.b" => "__builtin_lsx_vdiv_b",
+    "llvm.loongarch.lsx.vdiv.bu" => "__builtin_lsx_vdiv_bu",
+    "llvm.loongarch.lsx.vdiv.d" => "__builtin_lsx_vdiv_d",
+    "llvm.loongarch.lsx.vdiv.du" => "__builtin_lsx_vdiv_du",
+    "llvm.loongarch.lsx.vdiv.h" => "__builtin_lsx_vdiv_h",
+    "llvm.loongarch.lsx.vdiv.hu" => "__builtin_lsx_vdiv_hu",
+    "llvm.loongarch.lsx.vdiv.w" => "__builtin_lsx_vdiv_w",
+    "llvm.loongarch.lsx.vdiv.wu" => "__builtin_lsx_vdiv_wu",
+    "llvm.loongarch.lsx.vexth.d.w" => "__builtin_lsx_vexth_d_w",
+    "llvm.loongarch.lsx.vexth.du.wu" => "__builtin_lsx_vexth_du_wu",
+    "llvm.loongarch.lsx.vexth.h.b" => "__builtin_lsx_vexth_h_b",
+    "llvm.loongarch.lsx.vexth.hu.bu" => "__builtin_lsx_vexth_hu_bu",
+    "llvm.loongarch.lsx.vexth.q.d" => "__builtin_lsx_vexth_q_d",
+    "llvm.loongarch.lsx.vexth.qu.du" => "__builtin_lsx_vexth_qu_du",
+    "llvm.loongarch.lsx.vexth.w.h" => "__builtin_lsx_vexth_w_h",
+    "llvm.loongarch.lsx.vexth.wu.hu" => "__builtin_lsx_vexth_wu_hu",
+    "llvm.loongarch.lsx.vextl.q.d" => "__builtin_lsx_vextl_q_d",
+    "llvm.loongarch.lsx.vextl.qu.du" => "__builtin_lsx_vextl_qu_du",
+    "llvm.loongarch.lsx.vextrins.b" => "__builtin_lsx_vextrins_b",
+    "llvm.loongarch.lsx.vextrins.d" => "__builtin_lsx_vextrins_d",
+    "llvm.loongarch.lsx.vextrins.h" => "__builtin_lsx_vextrins_h",
+    "llvm.loongarch.lsx.vextrins.w" => "__builtin_lsx_vextrins_w",
+    "llvm.loongarch.lsx.vfadd.d" => "__builtin_lsx_vfadd_d",
+    "llvm.loongarch.lsx.vfadd.s" => "__builtin_lsx_vfadd_s",
+    "llvm.loongarch.lsx.vfclass.d" => "__builtin_lsx_vfclass_d",
+    "llvm.loongarch.lsx.vfclass.s" => "__builtin_lsx_vfclass_s",
+    "llvm.loongarch.lsx.vfcmp.caf.d" => "__builtin_lsx_vfcmp_caf_d",
+    "llvm.loongarch.lsx.vfcmp.caf.s" => "__builtin_lsx_vfcmp_caf_s",
+    "llvm.loongarch.lsx.vfcmp.ceq.d" => "__builtin_lsx_vfcmp_ceq_d",
+    "llvm.loongarch.lsx.vfcmp.ceq.s" => "__builtin_lsx_vfcmp_ceq_s",
+    "llvm.loongarch.lsx.vfcmp.cle.d" => "__builtin_lsx_vfcmp_cle_d",
+    "llvm.loongarch.lsx.vfcmp.cle.s" => "__builtin_lsx_vfcmp_cle_s",
+    "llvm.loongarch.lsx.vfcmp.clt.d" => "__builtin_lsx_vfcmp_clt_d",
+    "llvm.loongarch.lsx.vfcmp.clt.s" => "__builtin_lsx_vfcmp_clt_s",
+    "llvm.loongarch.lsx.vfcmp.cne.d" => "__builtin_lsx_vfcmp_cne_d",
+    "llvm.loongarch.lsx.vfcmp.cne.s" => "__builtin_lsx_vfcmp_cne_s",
+    "llvm.loongarch.lsx.vfcmp.cor.d" => "__builtin_lsx_vfcmp_cor_d",
+    "llvm.loongarch.lsx.vfcmp.cor.s" => "__builtin_lsx_vfcmp_cor_s",
+    "llvm.loongarch.lsx.vfcmp.cueq.d" => "__builtin_lsx_vfcmp_cueq_d",
+    "llvm.loongarch.lsx.vfcmp.cueq.s" => "__builtin_lsx_vfcmp_cueq_s",
+    "llvm.loongarch.lsx.vfcmp.cule.d" => "__builtin_lsx_vfcmp_cule_d",
+    "llvm.loongarch.lsx.vfcmp.cule.s" => "__builtin_lsx_vfcmp_cule_s",
+    "llvm.loongarch.lsx.vfcmp.cult.d" => "__builtin_lsx_vfcmp_cult_d",
+    "llvm.loongarch.lsx.vfcmp.cult.s" => "__builtin_lsx_vfcmp_cult_s",
+    "llvm.loongarch.lsx.vfcmp.cun.d" => "__builtin_lsx_vfcmp_cun_d",
+    "llvm.loongarch.lsx.vfcmp.cun.s" => "__builtin_lsx_vfcmp_cun_s",
+    "llvm.loongarch.lsx.vfcmp.cune.d" => "__builtin_lsx_vfcmp_cune_d",
+    "llvm.loongarch.lsx.vfcmp.cune.s" => "__builtin_lsx_vfcmp_cune_s",
+    "llvm.loongarch.lsx.vfcmp.saf.d" => "__builtin_lsx_vfcmp_saf_d",
+    "llvm.loongarch.lsx.vfcmp.saf.s" => "__builtin_lsx_vfcmp_saf_s",
+    "llvm.loongarch.lsx.vfcmp.seq.d" => "__builtin_lsx_vfcmp_seq_d",
+    "llvm.loongarch.lsx.vfcmp.seq.s" => "__builtin_lsx_vfcmp_seq_s",
+    "llvm.loongarch.lsx.vfcmp.sle.d" => "__builtin_lsx_vfcmp_sle_d",
+    "llvm.loongarch.lsx.vfcmp.sle.s" => "__builtin_lsx_vfcmp_sle_s",
+    "llvm.loongarch.lsx.vfcmp.slt.d" => "__builtin_lsx_vfcmp_slt_d",
+    "llvm.loongarch.lsx.vfcmp.slt.s" => "__builtin_lsx_vfcmp_slt_s",
+    "llvm.loongarch.lsx.vfcmp.sne.d" => "__builtin_lsx_vfcmp_sne_d",
+    "llvm.loongarch.lsx.vfcmp.sne.s" => "__builtin_lsx_vfcmp_sne_s",
+    "llvm.loongarch.lsx.vfcmp.sor.d" => "__builtin_lsx_vfcmp_sor_d",
+    "llvm.loongarch.lsx.vfcmp.sor.s" => "__builtin_lsx_vfcmp_sor_s",
+    "llvm.loongarch.lsx.vfcmp.sueq.d" => "__builtin_lsx_vfcmp_sueq_d",
+    "llvm.loongarch.lsx.vfcmp.sueq.s" => "__builtin_lsx_vfcmp_sueq_s",
+    "llvm.loongarch.lsx.vfcmp.sule.d" => "__builtin_lsx_vfcmp_sule_d",
+    "llvm.loongarch.lsx.vfcmp.sule.s" => "__builtin_lsx_vfcmp_sule_s",
+    "llvm.loongarch.lsx.vfcmp.sult.d" => "__builtin_lsx_vfcmp_sult_d",
+    "llvm.loongarch.lsx.vfcmp.sult.s" => "__builtin_lsx_vfcmp_sult_s",
+    "llvm.loongarch.lsx.vfcmp.sun.d" => "__builtin_lsx_vfcmp_sun_d",
+    "llvm.loongarch.lsx.vfcmp.sun.s" => "__builtin_lsx_vfcmp_sun_s",
+    "llvm.loongarch.lsx.vfcmp.sune.d" => "__builtin_lsx_vfcmp_sune_d",
+    "llvm.loongarch.lsx.vfcmp.sune.s" => "__builtin_lsx_vfcmp_sune_s",
+    "llvm.loongarch.lsx.vfcvt.h.s" => "__builtin_lsx_vfcvt_h_s",
+    "llvm.loongarch.lsx.vfcvt.s.d" => "__builtin_lsx_vfcvt_s_d",
+    "llvm.loongarch.lsx.vfcvth.d.s" => "__builtin_lsx_vfcvth_d_s",
+    "llvm.loongarch.lsx.vfcvth.s.h" => "__builtin_lsx_vfcvth_s_h",
+    "llvm.loongarch.lsx.vfcvtl.d.s" => "__builtin_lsx_vfcvtl_d_s",
+    "llvm.loongarch.lsx.vfcvtl.s.h" => "__builtin_lsx_vfcvtl_s_h",
+    "llvm.loongarch.lsx.vfdiv.d" => "__builtin_lsx_vfdiv_d",
+    "llvm.loongarch.lsx.vfdiv.s" => "__builtin_lsx_vfdiv_s",
+    "llvm.loongarch.lsx.vffint.d.l" => "__builtin_lsx_vffint_d_l",
+    "llvm.loongarch.lsx.vffint.d.lu" => "__builtin_lsx_vffint_d_lu",
+    "llvm.loongarch.lsx.vffint.s.l" => "__builtin_lsx_vffint_s_l",
+    "llvm.loongarch.lsx.vffint.s.w" => "__builtin_lsx_vffint_s_w",
+    "llvm.loongarch.lsx.vffint.s.wu" => "__builtin_lsx_vffint_s_wu",
+    "llvm.loongarch.lsx.vffinth.d.w" => "__builtin_lsx_vffinth_d_w",
+    "llvm.loongarch.lsx.vffintl.d.w" => "__builtin_lsx_vffintl_d_w",
+    "llvm.loongarch.lsx.vflogb.d" => "__builtin_lsx_vflogb_d",
+    "llvm.loongarch.lsx.vflogb.s" => "__builtin_lsx_vflogb_s",
+    "llvm.loongarch.lsx.vfmadd.d" => "__builtin_lsx_vfmadd_d",
+    "llvm.loongarch.lsx.vfmadd.s" => "__builtin_lsx_vfmadd_s",
+    "llvm.loongarch.lsx.vfmax.d" => "__builtin_lsx_vfmax_d",
+    "llvm.loongarch.lsx.vfmax.s" => "__builtin_lsx_vfmax_s",
+    "llvm.loongarch.lsx.vfmaxa.d" => "__builtin_lsx_vfmaxa_d",
+    "llvm.loongarch.lsx.vfmaxa.s" => "__builtin_lsx_vfmaxa_s",
+    "llvm.loongarch.lsx.vfmin.d" => "__builtin_lsx_vfmin_d",
+    "llvm.loongarch.lsx.vfmin.s" => "__builtin_lsx_vfmin_s",
+    "llvm.loongarch.lsx.vfmina.d" => "__builtin_lsx_vfmina_d",
+    "llvm.loongarch.lsx.vfmina.s" => "__builtin_lsx_vfmina_s",
+    "llvm.loongarch.lsx.vfmsub.d" => "__builtin_lsx_vfmsub_d",
+    "llvm.loongarch.lsx.vfmsub.s" => "__builtin_lsx_vfmsub_s",
+    "llvm.loongarch.lsx.vfmul.d" => "__builtin_lsx_vfmul_d",
+    "llvm.loongarch.lsx.vfmul.s" => "__builtin_lsx_vfmul_s",
+    "llvm.loongarch.lsx.vfnmadd.d" => "__builtin_lsx_vfnmadd_d",
+    "llvm.loongarch.lsx.vfnmadd.s" => "__builtin_lsx_vfnmadd_s",
+    "llvm.loongarch.lsx.vfnmsub.d" => "__builtin_lsx_vfnmsub_d",
+    "llvm.loongarch.lsx.vfnmsub.s" => "__builtin_lsx_vfnmsub_s",
+    "llvm.loongarch.lsx.vfrecip.d" => "__builtin_lsx_vfrecip_d",
+    "llvm.loongarch.lsx.vfrecip.s" => "__builtin_lsx_vfrecip_s",
+    "llvm.loongarch.lsx.vfrint.d" => "__builtin_lsx_vfrint_d",
+    "llvm.loongarch.lsx.vfrint.s" => "__builtin_lsx_vfrint_s",
+    "llvm.loongarch.lsx.vfrintrm.d" => "__builtin_lsx_vfrintrm_d",
+    "llvm.loongarch.lsx.vfrintrm.s" => "__builtin_lsx_vfrintrm_s",
+    "llvm.loongarch.lsx.vfrintrne.d" => "__builtin_lsx_vfrintrne_d",
+    "llvm.loongarch.lsx.vfrintrne.s" => "__builtin_lsx_vfrintrne_s",
+    "llvm.loongarch.lsx.vfrintrp.d" => "__builtin_lsx_vfrintrp_d",
+    "llvm.loongarch.lsx.vfrintrp.s" => "__builtin_lsx_vfrintrp_s",
+    "llvm.loongarch.lsx.vfrintrz.d" => "__builtin_lsx_vfrintrz_d",
+    "llvm.loongarch.lsx.vfrintrz.s" => "__builtin_lsx_vfrintrz_s",
+    "llvm.loongarch.lsx.vfrsqrt.d" => "__builtin_lsx_vfrsqrt_d",
+    "llvm.loongarch.lsx.vfrsqrt.s" => "__builtin_lsx_vfrsqrt_s",
+    "llvm.loongarch.lsx.vfrstp.b" => "__builtin_lsx_vfrstp_b",
+    "llvm.loongarch.lsx.vfrstp.h" => "__builtin_lsx_vfrstp_h",
+    "llvm.loongarch.lsx.vfrstpi.b" => "__builtin_lsx_vfrstpi_b",
+    "llvm.loongarch.lsx.vfrstpi.h" => "__builtin_lsx_vfrstpi_h",
+    "llvm.loongarch.lsx.vfsqrt.d" => "__builtin_lsx_vfsqrt_d",
+    "llvm.loongarch.lsx.vfsqrt.s" => "__builtin_lsx_vfsqrt_s",
+    "llvm.loongarch.lsx.vfsub.d" => "__builtin_lsx_vfsub_d",
+    "llvm.loongarch.lsx.vfsub.s" => "__builtin_lsx_vfsub_s",
+    "llvm.loongarch.lsx.vftint.l.d" => "__builtin_lsx_vftint_l_d",
+    "llvm.loongarch.lsx.vftint.lu.d" => "__builtin_lsx_vftint_lu_d",
+    "llvm.loongarch.lsx.vftint.w.d" => "__builtin_lsx_vftint_w_d",
+    "llvm.loongarch.lsx.vftint.w.s" => "__builtin_lsx_vftint_w_s",
+    "llvm.loongarch.lsx.vftint.wu.s" => "__builtin_lsx_vftint_wu_s",
+    "llvm.loongarch.lsx.vftinth.l.s" => "__builtin_lsx_vftinth_l_s",
+    "llvm.loongarch.lsx.vftintl.l.s" => "__builtin_lsx_vftintl_l_s",
+    "llvm.loongarch.lsx.vftintrm.l.d" => "__builtin_lsx_vftintrm_l_d",
+    "llvm.loongarch.lsx.vftintrm.w.d" => "__builtin_lsx_vftintrm_w_d",
+    "llvm.loongarch.lsx.vftintrm.w.s" => "__builtin_lsx_vftintrm_w_s",
+    "llvm.loongarch.lsx.vftintrmh.l.s" => "__builtin_lsx_vftintrmh_l_s",
+    "llvm.loongarch.lsx.vftintrml.l.s" => "__builtin_lsx_vftintrml_l_s",
+    "llvm.loongarch.lsx.vftintrne.l.d" => "__builtin_lsx_vftintrne_l_d",
+    "llvm.loongarch.lsx.vftintrne.w.d" => "__builtin_lsx_vftintrne_w_d",
+    "llvm.loongarch.lsx.vftintrne.w.s" => "__builtin_lsx_vftintrne_w_s",
+    "llvm.loongarch.lsx.vftintrneh.l.s" => "__builtin_lsx_vftintrneh_l_s",
+    "llvm.loongarch.lsx.vftintrnel.l.s" => "__builtin_lsx_vftintrnel_l_s",
+    "llvm.loongarch.lsx.vftintrp.l.d" => "__builtin_lsx_vftintrp_l_d",
+    "llvm.loongarch.lsx.vftintrp.w.d" => "__builtin_lsx_vftintrp_w_d",
+    "llvm.loongarch.lsx.vftintrp.w.s" => "__builtin_lsx_vftintrp_w_s",
+    "llvm.loongarch.lsx.vftintrph.l.s" => "__builtin_lsx_vftintrph_l_s",
+    "llvm.loongarch.lsx.vftintrpl.l.s" => "__builtin_lsx_vftintrpl_l_s",
+    "llvm.loongarch.lsx.vftintrz.l.d" => "__builtin_lsx_vftintrz_l_d",
+    "llvm.loongarch.lsx.vftintrz.lu.d" => "__builtin_lsx_vftintrz_lu_d",
+    "llvm.loongarch.lsx.vftintrz.w.d" => "__builtin_lsx_vftintrz_w_d",
+    "llvm.loongarch.lsx.vftintrz.w.s" => "__builtin_lsx_vftintrz_w_s",
+    "llvm.loongarch.lsx.vftintrz.wu.s" => "__builtin_lsx_vftintrz_wu_s",
+    "llvm.loongarch.lsx.vftintrzh.l.s" => "__builtin_lsx_vftintrzh_l_s",
+    "llvm.loongarch.lsx.vftintrzl.l.s" => "__builtin_lsx_vftintrzl_l_s",
+    "llvm.loongarch.lsx.vhaddw.d.w" => "__builtin_lsx_vhaddw_d_w",
+    "llvm.loongarch.lsx.vhaddw.du.wu" => "__builtin_lsx_vhaddw_du_wu",
+    "llvm.loongarch.lsx.vhaddw.h.b" => "__builtin_lsx_vhaddw_h_b",
+    "llvm.loongarch.lsx.vhaddw.hu.bu" => "__builtin_lsx_vhaddw_hu_bu",
+    "llvm.loongarch.lsx.vhaddw.q.d" => "__builtin_lsx_vhaddw_q_d",
+    "llvm.loongarch.lsx.vhaddw.qu.du" => "__builtin_lsx_vhaddw_qu_du",
+    "llvm.loongarch.lsx.vhaddw.w.h" => "__builtin_lsx_vhaddw_w_h",
+    "llvm.loongarch.lsx.vhaddw.wu.hu" => "__builtin_lsx_vhaddw_wu_hu",
+    "llvm.loongarch.lsx.vhsubw.d.w" => "__builtin_lsx_vhsubw_d_w",
+    "llvm.loongarch.lsx.vhsubw.du.wu" => "__builtin_lsx_vhsubw_du_wu",
+    "llvm.loongarch.lsx.vhsubw.h.b" => "__builtin_lsx_vhsubw_h_b",
+    "llvm.loongarch.lsx.vhsubw.hu.bu" => "__builtin_lsx_vhsubw_hu_bu",
+    "llvm.loongarch.lsx.vhsubw.q.d" => "__builtin_lsx_vhsubw_q_d",
+    "llvm.loongarch.lsx.vhsubw.qu.du" => "__builtin_lsx_vhsubw_qu_du",
+    "llvm.loongarch.lsx.vhsubw.w.h" => "__builtin_lsx_vhsubw_w_h",
+    "llvm.loongarch.lsx.vhsubw.wu.hu" => "__builtin_lsx_vhsubw_wu_hu",
+    "llvm.loongarch.lsx.vilvh.b" => "__builtin_lsx_vilvh_b",
+    "llvm.loongarch.lsx.vilvh.d" => "__builtin_lsx_vilvh_d",
+    "llvm.loongarch.lsx.vilvh.h" => "__builtin_lsx_vilvh_h",
+    "llvm.loongarch.lsx.vilvh.w" => "__builtin_lsx_vilvh_w",
+    "llvm.loongarch.lsx.vilvl.b" => "__builtin_lsx_vilvl_b",
+    "llvm.loongarch.lsx.vilvl.d" => "__builtin_lsx_vilvl_d",
+    "llvm.loongarch.lsx.vilvl.h" => "__builtin_lsx_vilvl_h",
+    "llvm.loongarch.lsx.vilvl.w" => "__builtin_lsx_vilvl_w",
+    "llvm.loongarch.lsx.vinsgr2vr.b" => "__builtin_lsx_vinsgr2vr_b",
+    "llvm.loongarch.lsx.vinsgr2vr.d" => "__builtin_lsx_vinsgr2vr_d",
+    "llvm.loongarch.lsx.vinsgr2vr.h" => "__builtin_lsx_vinsgr2vr_h",
+    "llvm.loongarch.lsx.vinsgr2vr.w" => "__builtin_lsx_vinsgr2vr_w",
+    "llvm.loongarch.lsx.vld" => "__builtin_lsx_vld",
+    "llvm.loongarch.lsx.vldi" => "__builtin_lsx_vldi",
+    "llvm.loongarch.lsx.vldrepl.b" => "__builtin_lsx_vldrepl_b",
+    "llvm.loongarch.lsx.vldrepl.d" => "__builtin_lsx_vldrepl_d",
+    "llvm.loongarch.lsx.vldrepl.h" => "__builtin_lsx_vldrepl_h",
+    "llvm.loongarch.lsx.vldrepl.w" => "__builtin_lsx_vldrepl_w",
+    "llvm.loongarch.lsx.vldx" => "__builtin_lsx_vldx",
+    "llvm.loongarch.lsx.vmadd.b" => "__builtin_lsx_vmadd_b",
+    "llvm.loongarch.lsx.vmadd.d" => "__builtin_lsx_vmadd_d",
+    "llvm.loongarch.lsx.vmadd.h" => "__builtin_lsx_vmadd_h",
+    "llvm.loongarch.lsx.vmadd.w" => "__builtin_lsx_vmadd_w",
+    "llvm.loongarch.lsx.vmaddwev.d.w" => "__builtin_lsx_vmaddwev_d_w",
+    "llvm.loongarch.lsx.vmaddwev.d.wu" => "__builtin_lsx_vmaddwev_d_wu",
+    "llvm.loongarch.lsx.vmaddwev.d.wu.w" => "__builtin_lsx_vmaddwev_d_wu_w",
+    "llvm.loongarch.lsx.vmaddwev.h.b" => "__builtin_lsx_vmaddwev_h_b",
+    "llvm.loongarch.lsx.vmaddwev.h.bu" => "__builtin_lsx_vmaddwev_h_bu",
+    "llvm.loongarch.lsx.vmaddwev.h.bu.b" => "__builtin_lsx_vmaddwev_h_bu_b",
+    "llvm.loongarch.lsx.vmaddwev.q.d" => "__builtin_lsx_vmaddwev_q_d",
+    "llvm.loongarch.lsx.vmaddwev.q.du" => "__builtin_lsx_vmaddwev_q_du",
+    "llvm.loongarch.lsx.vmaddwev.q.du.d" => "__builtin_lsx_vmaddwev_q_du_d",
+    "llvm.loongarch.lsx.vmaddwev.w.h" => "__builtin_lsx_vmaddwev_w_h",
+    "llvm.loongarch.lsx.vmaddwev.w.hu" => "__builtin_lsx_vmaddwev_w_hu",
+    "llvm.loongarch.lsx.vmaddwev.w.hu.h" => "__builtin_lsx_vmaddwev_w_hu_h",
+    "llvm.loongarch.lsx.vmaddwod.d.w" => "__builtin_lsx_vmaddwod_d_w",
+    "llvm.loongarch.lsx.vmaddwod.d.wu" => "__builtin_lsx_vmaddwod_d_wu",
+    "llvm.loongarch.lsx.vmaddwod.d.wu.w" => "__builtin_lsx_vmaddwod_d_wu_w",
+    "llvm.loongarch.lsx.vmaddwod.h.b" => "__builtin_lsx_vmaddwod_h_b",
+    "llvm.loongarch.lsx.vmaddwod.h.bu" => "__builtin_lsx_vmaddwod_h_bu",
+    "llvm.loongarch.lsx.vmaddwod.h.bu.b" => "__builtin_lsx_vmaddwod_h_bu_b",
+    "llvm.loongarch.lsx.vmaddwod.q.d" => "__builtin_lsx_vmaddwod_q_d",
+    "llvm.loongarch.lsx.vmaddwod.q.du" => "__builtin_lsx_vmaddwod_q_du",
+    "llvm.loongarch.lsx.vmaddwod.q.du.d" => "__builtin_lsx_vmaddwod_q_du_d",
+    "llvm.loongarch.lsx.vmaddwod.w.h" => "__builtin_lsx_vmaddwod_w_h",
+    "llvm.loongarch.lsx.vmaddwod.w.hu" => "__builtin_lsx_vmaddwod_w_hu",
+    "llvm.loongarch.lsx.vmaddwod.w.hu.h" => "__builtin_lsx_vmaddwod_w_hu_h",
+    "llvm.loongarch.lsx.vmax.b" => "__builtin_lsx_vmax_b",
+    "llvm.loongarch.lsx.vmax.bu" => "__builtin_lsx_vmax_bu",
+    "llvm.loongarch.lsx.vmax.d" => "__builtin_lsx_vmax_d",
+    "llvm.loongarch.lsx.vmax.du" => "__builtin_lsx_vmax_du",
+    "llvm.loongarch.lsx.vmax.h" => "__builtin_lsx_vmax_h",
+    "llvm.loongarch.lsx.vmax.hu" => "__builtin_lsx_vmax_hu",
+    "llvm.loongarch.lsx.vmax.w" => "__builtin_lsx_vmax_w",
+    "llvm.loongarch.lsx.vmax.wu" => "__builtin_lsx_vmax_wu",
+    "llvm.loongarch.lsx.vmaxi.b" => "__builtin_lsx_vmaxi_b",
+    "llvm.loongarch.lsx.vmaxi.bu" => "__builtin_lsx_vmaxi_bu",
+    "llvm.loongarch.lsx.vmaxi.d" => "__builtin_lsx_vmaxi_d",
+    "llvm.loongarch.lsx.vmaxi.du" => "__builtin_lsx_vmaxi_du",
+    "llvm.loongarch.lsx.vmaxi.h" => "__builtin_lsx_vmaxi_h",
+    "llvm.loongarch.lsx.vmaxi.hu" => "__builtin_lsx_vmaxi_hu",
+    "llvm.loongarch.lsx.vmaxi.w" => "__builtin_lsx_vmaxi_w",
+    "llvm.loongarch.lsx.vmaxi.wu" => "__builtin_lsx_vmaxi_wu",
+    "llvm.loongarch.lsx.vmin.b" => "__builtin_lsx_vmin_b",
+    "llvm.loongarch.lsx.vmin.bu" => "__builtin_lsx_vmin_bu",
+    "llvm.loongarch.lsx.vmin.d" => "__builtin_lsx_vmin_d",
+    "llvm.loongarch.lsx.vmin.du" => "__builtin_lsx_vmin_du",
+    "llvm.loongarch.lsx.vmin.h" => "__builtin_lsx_vmin_h",
+    "llvm.loongarch.lsx.vmin.hu" => "__builtin_lsx_vmin_hu",
+    "llvm.loongarch.lsx.vmin.w" => "__builtin_lsx_vmin_w",
+    "llvm.loongarch.lsx.vmin.wu" => "__builtin_lsx_vmin_wu",
+    "llvm.loongarch.lsx.vmini.b" => "__builtin_lsx_vmini_b",
+    "llvm.loongarch.lsx.vmini.bu" => "__builtin_lsx_vmini_bu",
+    "llvm.loongarch.lsx.vmini.d" => "__builtin_lsx_vmini_d",
+    "llvm.loongarch.lsx.vmini.du" => "__builtin_lsx_vmini_du",
+    "llvm.loongarch.lsx.vmini.h" => "__builtin_lsx_vmini_h",
+    "llvm.loongarch.lsx.vmini.hu" => "__builtin_lsx_vmini_hu",
+    "llvm.loongarch.lsx.vmini.w" => "__builtin_lsx_vmini_w",
+    "llvm.loongarch.lsx.vmini.wu" => "__builtin_lsx_vmini_wu",
+    "llvm.loongarch.lsx.vmod.b" => "__builtin_lsx_vmod_b",
+    "llvm.loongarch.lsx.vmod.bu" => "__builtin_lsx_vmod_bu",
+    "llvm.loongarch.lsx.vmod.d" => "__builtin_lsx_vmod_d",
+    "llvm.loongarch.lsx.vmod.du" => "__builtin_lsx_vmod_du",
+    "llvm.loongarch.lsx.vmod.h" => "__builtin_lsx_vmod_h",
+    "llvm.loongarch.lsx.vmod.hu" => "__builtin_lsx_vmod_hu",
+    "llvm.loongarch.lsx.vmod.w" => "__builtin_lsx_vmod_w",
+    "llvm.loongarch.lsx.vmod.wu" => "__builtin_lsx_vmod_wu",
+    "llvm.loongarch.lsx.vmskgez.b" => "__builtin_lsx_vmskgez_b",
+    "llvm.loongarch.lsx.vmskltz.b" => "__builtin_lsx_vmskltz_b",
+    "llvm.loongarch.lsx.vmskltz.d" => "__builtin_lsx_vmskltz_d",
+    "llvm.loongarch.lsx.vmskltz.h" => "__builtin_lsx_vmskltz_h",
+    "llvm.loongarch.lsx.vmskltz.w" => "__builtin_lsx_vmskltz_w",
+    "llvm.loongarch.lsx.vmsknz.b" => "__builtin_lsx_vmsknz_b",
+    "llvm.loongarch.lsx.vmsub.b" => "__builtin_lsx_vmsub_b",
+    "llvm.loongarch.lsx.vmsub.d" => "__builtin_lsx_vmsub_d",
+    "llvm.loongarch.lsx.vmsub.h" => "__builtin_lsx_vmsub_h",
+    "llvm.loongarch.lsx.vmsub.w" => "__builtin_lsx_vmsub_w",
+    "llvm.loongarch.lsx.vmuh.b" => "__builtin_lsx_vmuh_b",
+    "llvm.loongarch.lsx.vmuh.bu" => "__builtin_lsx_vmuh_bu",
+    "llvm.loongarch.lsx.vmuh.d" => "__builtin_lsx_vmuh_d",
+    "llvm.loongarch.lsx.vmuh.du" => "__builtin_lsx_vmuh_du",
+    "llvm.loongarch.lsx.vmuh.h" => "__builtin_lsx_vmuh_h",
+    "llvm.loongarch.lsx.vmuh.hu" => "__builtin_lsx_vmuh_hu",
+    "llvm.loongarch.lsx.vmuh.w" => "__builtin_lsx_vmuh_w",
+    "llvm.loongarch.lsx.vmuh.wu" => "__builtin_lsx_vmuh_wu",
+    "llvm.loongarch.lsx.vmul.b" => "__builtin_lsx_vmul_b",
+    "llvm.loongarch.lsx.vmul.d" => "__builtin_lsx_vmul_d",
+    "llvm.loongarch.lsx.vmul.h" => "__builtin_lsx_vmul_h",
+    "llvm.loongarch.lsx.vmul.w" => "__builtin_lsx_vmul_w",
+    "llvm.loongarch.lsx.vmulwev.d.w" => "__builtin_lsx_vmulwev_d_w",
+    "llvm.loongarch.lsx.vmulwev.d.wu" => "__builtin_lsx_vmulwev_d_wu",
+    "llvm.loongarch.lsx.vmulwev.d.wu.w" => "__builtin_lsx_vmulwev_d_wu_w",
+    "llvm.loongarch.lsx.vmulwev.h.b" => "__builtin_lsx_vmulwev_h_b",
+    "llvm.loongarch.lsx.vmulwev.h.bu" => "__builtin_lsx_vmulwev_h_bu",
+    "llvm.loongarch.lsx.vmulwev.h.bu.b" => "__builtin_lsx_vmulwev_h_bu_b",
+    "llvm.loongarch.lsx.vmulwev.q.d" => "__builtin_lsx_vmulwev_q_d",
+    "llvm.loongarch.lsx.vmulwev.q.du" => "__builtin_lsx_vmulwev_q_du",
+    "llvm.loongarch.lsx.vmulwev.q.du.d" => "__builtin_lsx_vmulwev_q_du_d",
+    "llvm.loongarch.lsx.vmulwev.w.h" => "__builtin_lsx_vmulwev_w_h",
+    "llvm.loongarch.lsx.vmulwev.w.hu" => "__builtin_lsx_vmulwev_w_hu",
+    "llvm.loongarch.lsx.vmulwev.w.hu.h" => "__builtin_lsx_vmulwev_w_hu_h",
+    "llvm.loongarch.lsx.vmulwod.d.w" => "__builtin_lsx_vmulwod_d_w",
+    "llvm.loongarch.lsx.vmulwod.d.wu" => "__builtin_lsx_vmulwod_d_wu",
+    "llvm.loongarch.lsx.vmulwod.d.wu.w" => "__builtin_lsx_vmulwod_d_wu_w",
+    "llvm.loongarch.lsx.vmulwod.h.b" => "__builtin_lsx_vmulwod_h_b",
+    "llvm.loongarch.lsx.vmulwod.h.bu" => "__builtin_lsx_vmulwod_h_bu",
+    "llvm.loongarch.lsx.vmulwod.h.bu.b" => "__builtin_lsx_vmulwod_h_bu_b",
+    "llvm.loongarch.lsx.vmulwod.q.d" => "__builtin_lsx_vmulwod_q_d",
+    "llvm.loongarch.lsx.vmulwod.q.du" => "__builtin_lsx_vmulwod_q_du",
+    "llvm.loongarch.lsx.vmulwod.q.du.d" => "__builtin_lsx_vmulwod_q_du_d",
+    "llvm.loongarch.lsx.vmulwod.w.h" => "__builtin_lsx_vmulwod_w_h",
+    "llvm.loongarch.lsx.vmulwod.w.hu" => "__builtin_lsx_vmulwod_w_hu",
+    "llvm.loongarch.lsx.vmulwod.w.hu.h" => "__builtin_lsx_vmulwod_w_hu_h",
+    "llvm.loongarch.lsx.vneg.b" => "__builtin_lsx_vneg_b",
+    "llvm.loongarch.lsx.vneg.d" => "__builtin_lsx_vneg_d",
+    "llvm.loongarch.lsx.vneg.h" => "__builtin_lsx_vneg_h",
+    "llvm.loongarch.lsx.vneg.w" => "__builtin_lsx_vneg_w",
+    "llvm.loongarch.lsx.vnor.v" => "__builtin_lsx_vnor_v",
+    "llvm.loongarch.lsx.vnori.b" => "__builtin_lsx_vnori_b",
+    "llvm.loongarch.lsx.vor.v" => "__builtin_lsx_vor_v",
+    "llvm.loongarch.lsx.vori.b" => "__builtin_lsx_vori_b",
+    "llvm.loongarch.lsx.vorn.v" => "__builtin_lsx_vorn_v",
+    "llvm.loongarch.lsx.vpackev.b" => "__builtin_lsx_vpackev_b",
+    "llvm.loongarch.lsx.vpackev.d" => "__builtin_lsx_vpackev_d",
+    "llvm.loongarch.lsx.vpackev.h" => "__builtin_lsx_vpackev_h",
+    "llvm.loongarch.lsx.vpackev.w" => "__builtin_lsx_vpackev_w",
+    "llvm.loongarch.lsx.vpackod.b" => "__builtin_lsx_vpackod_b",
+    "llvm.loongarch.lsx.vpackod.d" => "__builtin_lsx_vpackod_d",
+    "llvm.loongarch.lsx.vpackod.h" => "__builtin_lsx_vpackod_h",
+    "llvm.loongarch.lsx.vpackod.w" => "__builtin_lsx_vpackod_w",
+    "llvm.loongarch.lsx.vpcnt.b" => "__builtin_lsx_vpcnt_b",
+    "llvm.loongarch.lsx.vpcnt.d" => "__builtin_lsx_vpcnt_d",
+    "llvm.loongarch.lsx.vpcnt.h" => "__builtin_lsx_vpcnt_h",
+    "llvm.loongarch.lsx.vpcnt.w" => "__builtin_lsx_vpcnt_w",
+    "llvm.loongarch.lsx.vpermi.w" => "__builtin_lsx_vpermi_w",
+    "llvm.loongarch.lsx.vpickev.b" => "__builtin_lsx_vpickev_b",
+    "llvm.loongarch.lsx.vpickev.d" => "__builtin_lsx_vpickev_d",
+    "llvm.loongarch.lsx.vpickev.h" => "__builtin_lsx_vpickev_h",
+    "llvm.loongarch.lsx.vpickev.w" => "__builtin_lsx_vpickev_w",
+    "llvm.loongarch.lsx.vpickod.b" => "__builtin_lsx_vpickod_b",
+    "llvm.loongarch.lsx.vpickod.d" => "__builtin_lsx_vpickod_d",
+    "llvm.loongarch.lsx.vpickod.h" => "__builtin_lsx_vpickod_h",
+    "llvm.loongarch.lsx.vpickod.w" => "__builtin_lsx_vpickod_w",
+    "llvm.loongarch.lsx.vpickve2gr.b" => "__builtin_lsx_vpickve2gr_b",
+    "llvm.loongarch.lsx.vpickve2gr.bu" => "__builtin_lsx_vpickve2gr_bu",
+    "llvm.loongarch.lsx.vpickve2gr.d" => "__builtin_lsx_vpickve2gr_d",
+    "llvm.loongarch.lsx.vpickve2gr.du" => "__builtin_lsx_vpickve2gr_du",
+    "llvm.loongarch.lsx.vpickve2gr.h" => "__builtin_lsx_vpickve2gr_h",
+    "llvm.loongarch.lsx.vpickve2gr.hu" => "__builtin_lsx_vpickve2gr_hu",
+    "llvm.loongarch.lsx.vpickve2gr.w" => "__builtin_lsx_vpickve2gr_w",
+    "llvm.loongarch.lsx.vpickve2gr.wu" => "__builtin_lsx_vpickve2gr_wu",
+    "llvm.loongarch.lsx.vreplgr2vr.b" => "__builtin_lsx_vreplgr2vr_b",
+    "llvm.loongarch.lsx.vreplgr2vr.d" => "__builtin_lsx_vreplgr2vr_d",
+    "llvm.loongarch.lsx.vreplgr2vr.h" => "__builtin_lsx_vreplgr2vr_h",
+    "llvm.loongarch.lsx.vreplgr2vr.w" => "__builtin_lsx_vreplgr2vr_w",
+    "llvm.loongarch.lsx.vrepli.b" => "__builtin_lsx_vrepli_b",
+    "llvm.loongarch.lsx.vrepli.d" => "__builtin_lsx_vrepli_d",
+    "llvm.loongarch.lsx.vrepli.h" => "__builtin_lsx_vrepli_h",
+    "llvm.loongarch.lsx.vrepli.w" => "__builtin_lsx_vrepli_w",
+    "llvm.loongarch.lsx.vreplve.b" => "__builtin_lsx_vreplve_b",
+    "llvm.loongarch.lsx.vreplve.d" => "__builtin_lsx_vreplve_d",
+    "llvm.loongarch.lsx.vreplve.h" => "__builtin_lsx_vreplve_h",
+    "llvm.loongarch.lsx.vreplve.w" => "__builtin_lsx_vreplve_w",
+    "llvm.loongarch.lsx.vreplvei.b" => "__builtin_lsx_vreplvei_b",
+    "llvm.loongarch.lsx.vreplvei.d" => "__builtin_lsx_vreplvei_d",
+    "llvm.loongarch.lsx.vreplvei.h" => "__builtin_lsx_vreplvei_h",
+    "llvm.loongarch.lsx.vreplvei.w" => "__builtin_lsx_vreplvei_w",
+    "llvm.loongarch.lsx.vrotr.b" => "__builtin_lsx_vrotr_b",
+    "llvm.loongarch.lsx.vrotr.d" => "__builtin_lsx_vrotr_d",
+    "llvm.loongarch.lsx.vrotr.h" => "__builtin_lsx_vrotr_h",
+    "llvm.loongarch.lsx.vrotr.w" => "__builtin_lsx_vrotr_w",
+    "llvm.loongarch.lsx.vrotri.b" => "__builtin_lsx_vrotri_b",
+    "llvm.loongarch.lsx.vrotri.d" => "__builtin_lsx_vrotri_d",
+    "llvm.loongarch.lsx.vrotri.h" => "__builtin_lsx_vrotri_h",
+    "llvm.loongarch.lsx.vrotri.w" => "__builtin_lsx_vrotri_w",
+    "llvm.loongarch.lsx.vsadd.b" => "__builtin_lsx_vsadd_b",
+    "llvm.loongarch.lsx.vsadd.bu" => "__builtin_lsx_vsadd_bu",
+    "llvm.loongarch.lsx.vsadd.d" => "__builtin_lsx_vsadd_d",
+    "llvm.loongarch.lsx.vsadd.du" => "__builtin_lsx_vsadd_du",
+    "llvm.loongarch.lsx.vsadd.h" => "__builtin_lsx_vsadd_h",
+    "llvm.loongarch.lsx.vsadd.hu" => "__builtin_lsx_vsadd_hu",
+    "llvm.loongarch.lsx.vsadd.w" => "__builtin_lsx_vsadd_w",
+    "llvm.loongarch.lsx.vsadd.wu" => "__builtin_lsx_vsadd_wu",
+    "llvm.loongarch.lsx.vsat.b" => "__builtin_lsx_vsat_b",
+    "llvm.loongarch.lsx.vsat.bu" => "__builtin_lsx_vsat_bu",
+    "llvm.loongarch.lsx.vsat.d" => "__builtin_lsx_vsat_d",
+    "llvm.loongarch.lsx.vsat.du" => "__builtin_lsx_vsat_du",
+    "llvm.loongarch.lsx.vsat.h" => "__builtin_lsx_vsat_h",
+    "llvm.loongarch.lsx.vsat.hu" => "__builtin_lsx_vsat_hu",
+    "llvm.loongarch.lsx.vsat.w" => "__builtin_lsx_vsat_w",
+    "llvm.loongarch.lsx.vsat.wu" => "__builtin_lsx_vsat_wu",
+    "llvm.loongarch.lsx.vseq.b" => "__builtin_lsx_vseq_b",
+    "llvm.loongarch.lsx.vseq.d" => "__builtin_lsx_vseq_d",
+    "llvm.loongarch.lsx.vseq.h" => "__builtin_lsx_vseq_h",
+    "llvm.loongarch.lsx.vseq.w" => "__builtin_lsx_vseq_w",
+    "llvm.loongarch.lsx.vseqi.b" => "__builtin_lsx_vseqi_b",
+    "llvm.loongarch.lsx.vseqi.d" => "__builtin_lsx_vseqi_d",
+    "llvm.loongarch.lsx.vseqi.h" => "__builtin_lsx_vseqi_h",
+    "llvm.loongarch.lsx.vseqi.w" => "__builtin_lsx_vseqi_w",
+    "llvm.loongarch.lsx.vshuf.b" => "__builtin_lsx_vshuf_b",
+    "llvm.loongarch.lsx.vshuf.d" => "__builtin_lsx_vshuf_d",
+    "llvm.loongarch.lsx.vshuf.h" => "__builtin_lsx_vshuf_h",
+    "llvm.loongarch.lsx.vshuf.w" => "__builtin_lsx_vshuf_w",
+    "llvm.loongarch.lsx.vshuf4i.b" => "__builtin_lsx_vshuf4i_b",
+    "llvm.loongarch.lsx.vshuf4i.d" => "__builtin_lsx_vshuf4i_d",
+    "llvm.loongarch.lsx.vshuf4i.h" => "__builtin_lsx_vshuf4i_h",
+    "llvm.loongarch.lsx.vshuf4i.w" => "__builtin_lsx_vshuf4i_w",
+    "llvm.loongarch.lsx.vsigncov.b" => "__builtin_lsx_vsigncov_b",
+    "llvm.loongarch.lsx.vsigncov.d" => "__builtin_lsx_vsigncov_d",
+    "llvm.loongarch.lsx.vsigncov.h" => "__builtin_lsx_vsigncov_h",
+    "llvm.loongarch.lsx.vsigncov.w" => "__builtin_lsx_vsigncov_w",
+    "llvm.loongarch.lsx.vsle.b" => "__builtin_lsx_vsle_b",
+    "llvm.loongarch.lsx.vsle.bu" => "__builtin_lsx_vsle_bu",
+    "llvm.loongarch.lsx.vsle.d" => "__builtin_lsx_vsle_d",
+    "llvm.loongarch.lsx.vsle.du" => "__builtin_lsx_vsle_du",
+    "llvm.loongarch.lsx.vsle.h" => "__builtin_lsx_vsle_h",
+    "llvm.loongarch.lsx.vsle.hu" => "__builtin_lsx_vsle_hu",
+    "llvm.loongarch.lsx.vsle.w" => "__builtin_lsx_vsle_w",
+    "llvm.loongarch.lsx.vsle.wu" => "__builtin_lsx_vsle_wu",
+    "llvm.loongarch.lsx.vslei.b" => "__builtin_lsx_vslei_b",
+    "llvm.loongarch.lsx.vslei.bu" => "__builtin_lsx_vslei_bu",
+    "llvm.loongarch.lsx.vslei.d" => "__builtin_lsx_vslei_d",
+    "llvm.loongarch.lsx.vslei.du" => "__builtin_lsx_vslei_du",
+    "llvm.loongarch.lsx.vslei.h" => "__builtin_lsx_vslei_h",
+    "llvm.loongarch.lsx.vslei.hu" => "__builtin_lsx_vslei_hu",
+    "llvm.loongarch.lsx.vslei.w" => "__builtin_lsx_vslei_w",
+    "llvm.loongarch.lsx.vslei.wu" => "__builtin_lsx_vslei_wu",
+    "llvm.loongarch.lsx.vsll.b" => "__builtin_lsx_vsll_b",
+    "llvm.loongarch.lsx.vsll.d" => "__builtin_lsx_vsll_d",
+    "llvm.loongarch.lsx.vsll.h" => "__builtin_lsx_vsll_h",
+    "llvm.loongarch.lsx.vsll.w" => "__builtin_lsx_vsll_w",
+    "llvm.loongarch.lsx.vslli.b" => "__builtin_lsx_vslli_b",
+    "llvm.loongarch.lsx.vslli.d" => "__builtin_lsx_vslli_d",
+    "llvm.loongarch.lsx.vslli.h" => "__builtin_lsx_vslli_h",
+    "llvm.loongarch.lsx.vslli.w" => "__builtin_lsx_vslli_w",
+    "llvm.loongarch.lsx.vsllwil.d.w" => "__builtin_lsx_vsllwil_d_w",
+    "llvm.loongarch.lsx.vsllwil.du.wu" => "__builtin_lsx_vsllwil_du_wu",
+    "llvm.loongarch.lsx.vsllwil.h.b" => "__builtin_lsx_vsllwil_h_b",
+    "llvm.loongarch.lsx.vsllwil.hu.bu" => "__builtin_lsx_vsllwil_hu_bu",
+    "llvm.loongarch.lsx.vsllwil.w.h" => "__builtin_lsx_vsllwil_w_h",
+    "llvm.loongarch.lsx.vsllwil.wu.hu" => "__builtin_lsx_vsllwil_wu_hu",
+    "llvm.loongarch.lsx.vslt.b" => "__builtin_lsx_vslt_b",
+    "llvm.loongarch.lsx.vslt.bu" => "__builtin_lsx_vslt_bu",
+    "llvm.loongarch.lsx.vslt.d" => "__builtin_lsx_vslt_d",
+    "llvm.loongarch.lsx.vslt.du" => "__builtin_lsx_vslt_du",
+    "llvm.loongarch.lsx.vslt.h" => "__builtin_lsx_vslt_h",
+    "llvm.loongarch.lsx.vslt.hu" => "__builtin_lsx_vslt_hu",
+    "llvm.loongarch.lsx.vslt.w" => "__builtin_lsx_vslt_w",
+    "llvm.loongarch.lsx.vslt.wu" => "__builtin_lsx_vslt_wu",
+    "llvm.loongarch.lsx.vslti.b" => "__builtin_lsx_vslti_b",
+    "llvm.loongarch.lsx.vslti.bu" => "__builtin_lsx_vslti_bu",
+    "llvm.loongarch.lsx.vslti.d" => "__builtin_lsx_vslti_d",
+    "llvm.loongarch.lsx.vslti.du" => "__builtin_lsx_vslti_du",
+    "llvm.loongarch.lsx.vslti.h" => "__builtin_lsx_vslti_h",
+    "llvm.loongarch.lsx.vslti.hu" => "__builtin_lsx_vslti_hu",
+    "llvm.loongarch.lsx.vslti.w" => "__builtin_lsx_vslti_w",
+    "llvm.loongarch.lsx.vslti.wu" => "__builtin_lsx_vslti_wu",
+    "llvm.loongarch.lsx.vsra.b" => "__builtin_lsx_vsra_b",
+    "llvm.loongarch.lsx.vsra.d" => "__builtin_lsx_vsra_d",
+    "llvm.loongarch.lsx.vsra.h" => "__builtin_lsx_vsra_h",
+    "llvm.loongarch.lsx.vsra.w" => "__builtin_lsx_vsra_w",
+    "llvm.loongarch.lsx.vsrai.b" => "__builtin_lsx_vsrai_b",
+    "llvm.loongarch.lsx.vsrai.d" => "__builtin_lsx_vsrai_d",
+    "llvm.loongarch.lsx.vsrai.h" => "__builtin_lsx_vsrai_h",
+    "llvm.loongarch.lsx.vsrai.w" => "__builtin_lsx_vsrai_w",
+    "llvm.loongarch.lsx.vsran.b.h" => "__builtin_lsx_vsran_b_h",
+    "llvm.loongarch.lsx.vsran.h.w" => "__builtin_lsx_vsran_h_w",
+    "llvm.loongarch.lsx.vsran.w.d" => "__builtin_lsx_vsran_w_d",
+    "llvm.loongarch.lsx.vsrani.b.h" => "__builtin_lsx_vsrani_b_h",
+    "llvm.loongarch.lsx.vsrani.d.q" => "__builtin_lsx_vsrani_d_q",
+    "llvm.loongarch.lsx.vsrani.h.w" => "__builtin_lsx_vsrani_h_w",
+    "llvm.loongarch.lsx.vsrani.w.d" => "__builtin_lsx_vsrani_w_d",
+    "llvm.loongarch.lsx.vsrar.b" => "__builtin_lsx_vsrar_b",
+    "llvm.loongarch.lsx.vsrar.d" => "__builtin_lsx_vsrar_d",
+    "llvm.loongarch.lsx.vsrar.h" => "__builtin_lsx_vsrar_h",
+    "llvm.loongarch.lsx.vsrar.w" => "__builtin_lsx_vsrar_w",
+    "llvm.loongarch.lsx.vsrari.b" => "__builtin_lsx_vsrari_b",
+    "llvm.loongarch.lsx.vsrari.d" => "__builtin_lsx_vsrari_d",
+    "llvm.loongarch.lsx.vsrari.h" => "__builtin_lsx_vsrari_h",
+    "llvm.loongarch.lsx.vsrari.w" => "__builtin_lsx_vsrari_w",
+    "llvm.loongarch.lsx.vsrarn.b.h" => "__builtin_lsx_vsrarn_b_h",
+    "llvm.loongarch.lsx.vsrarn.h.w" => "__builtin_lsx_vsrarn_h_w",
+    "llvm.loongarch.lsx.vsrarn.w.d" => "__builtin_lsx_vsrarn_w_d",
+    "llvm.loongarch.lsx.vsrarni.b.h" => "__builtin_lsx_vsrarni_b_h",
+    "llvm.loongarch.lsx.vsrarni.d.q" => "__builtin_lsx_vsrarni_d_q",
+    "llvm.loongarch.lsx.vsrarni.h.w" => "__builtin_lsx_vsrarni_h_w",
+    "llvm.loongarch.lsx.vsrarni.w.d" => "__builtin_lsx_vsrarni_w_d",
+    "llvm.loongarch.lsx.vsrl.b" => "__builtin_lsx_vsrl_b",
+    "llvm.loongarch.lsx.vsrl.d" => "__builtin_lsx_vsrl_d",
+    "llvm.loongarch.lsx.vsrl.h" => "__builtin_lsx_vsrl_h",
+    "llvm.loongarch.lsx.vsrl.w" => "__builtin_lsx_vsrl_w",
+    "llvm.loongarch.lsx.vsrli.b" => "__builtin_lsx_vsrli_b",
+    "llvm.loongarch.lsx.vsrli.d" => "__builtin_lsx_vsrli_d",
+    "llvm.loongarch.lsx.vsrli.h" => "__builtin_lsx_vsrli_h",
+    "llvm.loongarch.lsx.vsrli.w" => "__builtin_lsx_vsrli_w",
+    "llvm.loongarch.lsx.vsrln.b.h" => "__builtin_lsx_vsrln_b_h",
+    "llvm.loongarch.lsx.vsrln.h.w" => "__builtin_lsx_vsrln_h_w",
+    "llvm.loongarch.lsx.vsrln.w.d" => "__builtin_lsx_vsrln_w_d",
+    "llvm.loongarch.lsx.vsrlni.b.h" => "__builtin_lsx_vsrlni_b_h",
+    "llvm.loongarch.lsx.vsrlni.d.q" => "__builtin_lsx_vsrlni_d_q",
+    "llvm.loongarch.lsx.vsrlni.h.w" => "__builtin_lsx_vsrlni_h_w",
+    "llvm.loongarch.lsx.vsrlni.w.d" => "__builtin_lsx_vsrlni_w_d",
+    "llvm.loongarch.lsx.vsrlr.b" => "__builtin_lsx_vsrlr_b",
+    "llvm.loongarch.lsx.vsrlr.d" => "__builtin_lsx_vsrlr_d",
+    "llvm.loongarch.lsx.vsrlr.h" => "__builtin_lsx_vsrlr_h",
+    "llvm.loongarch.lsx.vsrlr.w" => "__builtin_lsx_vsrlr_w",
+    "llvm.loongarch.lsx.vsrlri.b" => "__builtin_lsx_vsrlri_b",
+    "llvm.loongarch.lsx.vsrlri.d" => "__builtin_lsx_vsrlri_d",
+    "llvm.loongarch.lsx.vsrlri.h" => "__builtin_lsx_vsrlri_h",
+    "llvm.loongarch.lsx.vsrlri.w" => "__builtin_lsx_vsrlri_w",
+    "llvm.loongarch.lsx.vsrlrn.b.h" => "__builtin_lsx_vsrlrn_b_h",
+    "llvm.loongarch.lsx.vsrlrn.h.w" => "__builtin_lsx_vsrlrn_h_w",
+    "llvm.loongarch.lsx.vsrlrn.w.d" => "__builtin_lsx_vsrlrn_w_d",
+    "llvm.loongarch.lsx.vsrlrni.b.h" => "__builtin_lsx_vsrlrni_b_h",
+    "llvm.loongarch.lsx.vsrlrni.d.q" => "__builtin_lsx_vsrlrni_d_q",
+    "llvm.loongarch.lsx.vsrlrni.h.w" => "__builtin_lsx_vsrlrni_h_w",
+    "llvm.loongarch.lsx.vsrlrni.w.d" => "__builtin_lsx_vsrlrni_w_d",
+    "llvm.loongarch.lsx.vssran.b.h" => "__builtin_lsx_vssran_b_h",
+    "llvm.loongarch.lsx.vssran.bu.h" => "__builtin_lsx_vssran_bu_h",
+    "llvm.loongarch.lsx.vssran.h.w" => "__builtin_lsx_vssran_h_w",
+    "llvm.loongarch.lsx.vssran.hu.w" => "__builtin_lsx_vssran_hu_w",
+    "llvm.loongarch.lsx.vssran.w.d" => "__builtin_lsx_vssran_w_d",
+    "llvm.loongarch.lsx.vssran.wu.d" => "__builtin_lsx_vssran_wu_d",
+    "llvm.loongarch.lsx.vssrani.b.h" => "__builtin_lsx_vssrani_b_h",
+    "llvm.loongarch.lsx.vssrani.bu.h" => "__builtin_lsx_vssrani_bu_h",
+    "llvm.loongarch.lsx.vssrani.d.q" => "__builtin_lsx_vssrani_d_q",
+    "llvm.loongarch.lsx.vssrani.du.q" => "__builtin_lsx_vssrani_du_q",
+    "llvm.loongarch.lsx.vssrani.h.w" => "__builtin_lsx_vssrani_h_w",
+    "llvm.loongarch.lsx.vssrani.hu.w" => "__builtin_lsx_vssrani_hu_w",
+    "llvm.loongarch.lsx.vssrani.w.d" => "__builtin_lsx_vssrani_w_d",
+    "llvm.loongarch.lsx.vssrani.wu.d" => "__builtin_lsx_vssrani_wu_d",
+    "llvm.loongarch.lsx.vssrarn.b.h" => "__builtin_lsx_vssrarn_b_h",
+    "llvm.loongarch.lsx.vssrarn.bu.h" => "__builtin_lsx_vssrarn_bu_h",
+    "llvm.loongarch.lsx.vssrarn.h.w" => "__builtin_lsx_vssrarn_h_w",
+    "llvm.loongarch.lsx.vssrarn.hu.w" => "__builtin_lsx_vssrarn_hu_w",
+    "llvm.loongarch.lsx.vssrarn.w.d" => "__builtin_lsx_vssrarn_w_d",
+    "llvm.loongarch.lsx.vssrarn.wu.d" => "__builtin_lsx_vssrarn_wu_d",
+    "llvm.loongarch.lsx.vssrarni.b.h" => "__builtin_lsx_vssrarni_b_h",
+    "llvm.loongarch.lsx.vssrarni.bu.h" => "__builtin_lsx_vssrarni_bu_h",
+    "llvm.loongarch.lsx.vssrarni.d.q" => "__builtin_lsx_vssrarni_d_q",
+    "llvm.loongarch.lsx.vssrarni.du.q" => "__builtin_lsx_vssrarni_du_q",
+    "llvm.loongarch.lsx.vssrarni.h.w" => "__builtin_lsx_vssrarni_h_w",
+    "llvm.loongarch.lsx.vssrarni.hu.w" => "__builtin_lsx_vssrarni_hu_w",
+    "llvm.loongarch.lsx.vssrarni.w.d" => "__builtin_lsx_vssrarni_w_d",
+    "llvm.loongarch.lsx.vssrarni.wu.d" => "__builtin_lsx_vssrarni_wu_d",
+    "llvm.loongarch.lsx.vssrln.b.h" => "__builtin_lsx_vssrln_b_h",
+    "llvm.loongarch.lsx.vssrln.bu.h" => "__builtin_lsx_vssrln_bu_h",
+    "llvm.loongarch.lsx.vssrln.h.w" => "__builtin_lsx_vssrln_h_w",
+    "llvm.loongarch.lsx.vssrln.hu.w" => "__builtin_lsx_vssrln_hu_w",
+    "llvm.loongarch.lsx.vssrln.w.d" => "__builtin_lsx_vssrln_w_d",
+    "llvm.loongarch.lsx.vssrln.wu.d" => "__builtin_lsx_vssrln_wu_d",
+    "llvm.loongarch.lsx.vssrlni.b.h" => "__builtin_lsx_vssrlni_b_h",
+    "llvm.loongarch.lsx.vssrlni.bu.h" => "__builtin_lsx_vssrlni_bu_h",
+    "llvm.loongarch.lsx.vssrlni.d.q" => "__builtin_lsx_vssrlni_d_q",
+    "llvm.loongarch.lsx.vssrlni.du.q" => "__builtin_lsx_vssrlni_du_q",
+    "llvm.loongarch.lsx.vssrlni.h.w" => "__builtin_lsx_vssrlni_h_w",
+    "llvm.loongarch.lsx.vssrlni.hu.w" => "__builtin_lsx_vssrlni_hu_w",
+    "llvm.loongarch.lsx.vssrlni.w.d" => "__builtin_lsx_vssrlni_w_d",
+    "llvm.loongarch.lsx.vssrlni.wu.d" => "__builtin_lsx_vssrlni_wu_d",
+    "llvm.loongarch.lsx.vssrlrn.b.h" => "__builtin_lsx_vssrlrn_b_h",
+    "llvm.loongarch.lsx.vssrlrn.bu.h" => "__builtin_lsx_vssrlrn_bu_h",
+    "llvm.loongarch.lsx.vssrlrn.h.w" => "__builtin_lsx_vssrlrn_h_w",
+    "llvm.loongarch.lsx.vssrlrn.hu.w" => "__builtin_lsx_vssrlrn_hu_w",
+    "llvm.loongarch.lsx.vssrlrn.w.d" => "__builtin_lsx_vssrlrn_w_d",
+    "llvm.loongarch.lsx.vssrlrn.wu.d" => "__builtin_lsx_vssrlrn_wu_d",
+    "llvm.loongarch.lsx.vssrlrni.b.h" => "__builtin_lsx_vssrlrni_b_h",
+    "llvm.loongarch.lsx.vssrlrni.bu.h" => "__builtin_lsx_vssrlrni_bu_h",
+    "llvm.loongarch.lsx.vssrlrni.d.q" => "__builtin_lsx_vssrlrni_d_q",
+    "llvm.loongarch.lsx.vssrlrni.du.q" => "__builtin_lsx_vssrlrni_du_q",
+    "llvm.loongarch.lsx.vssrlrni.h.w" => "__builtin_lsx_vssrlrni_h_w",
+    "llvm.loongarch.lsx.vssrlrni.hu.w" => "__builtin_lsx_vssrlrni_hu_w",
+    "llvm.loongarch.lsx.vssrlrni.w.d" => "__builtin_lsx_vssrlrni_w_d",
+    "llvm.loongarch.lsx.vssrlrni.wu.d" => "__builtin_lsx_vssrlrni_wu_d",
+    "llvm.loongarch.lsx.vssub.b" => "__builtin_lsx_vssub_b",
+    "llvm.loongarch.lsx.vssub.bu" => "__builtin_lsx_vssub_bu",
+    "llvm.loongarch.lsx.vssub.d" => "__builtin_lsx_vssub_d",
+    "llvm.loongarch.lsx.vssub.du" => "__builtin_lsx_vssub_du",
+    "llvm.loongarch.lsx.vssub.h" => "__builtin_lsx_vssub_h",
+    "llvm.loongarch.lsx.vssub.hu" => "__builtin_lsx_vssub_hu",
+    "llvm.loongarch.lsx.vssub.w" => "__builtin_lsx_vssub_w",
+    "llvm.loongarch.lsx.vssub.wu" => "__builtin_lsx_vssub_wu",
+    "llvm.loongarch.lsx.vst" => "__builtin_lsx_vst",
+    "llvm.loongarch.lsx.vstelm.b" => "__builtin_lsx_vstelm_b",
+    "llvm.loongarch.lsx.vstelm.d" => "__builtin_lsx_vstelm_d",
+    "llvm.loongarch.lsx.vstelm.h" => "__builtin_lsx_vstelm_h",
+    "llvm.loongarch.lsx.vstelm.w" => "__builtin_lsx_vstelm_w",
+    "llvm.loongarch.lsx.vstx" => "__builtin_lsx_vstx",
+    "llvm.loongarch.lsx.vsub.b" => "__builtin_lsx_vsub_b",
+    "llvm.loongarch.lsx.vsub.d" => "__builtin_lsx_vsub_d",
+    "llvm.loongarch.lsx.vsub.h" => "__builtin_lsx_vsub_h",
+    "llvm.loongarch.lsx.vsub.q" => "__builtin_lsx_vsub_q",
+    "llvm.loongarch.lsx.vsub.w" => "__builtin_lsx_vsub_w",
+    "llvm.loongarch.lsx.vsubi.bu" => "__builtin_lsx_vsubi_bu",
+    "llvm.loongarch.lsx.vsubi.du" => "__builtin_lsx_vsubi_du",
+    "llvm.loongarch.lsx.vsubi.hu" => "__builtin_lsx_vsubi_hu",
+    "llvm.loongarch.lsx.vsubi.wu" => "__builtin_lsx_vsubi_wu",
+    "llvm.loongarch.lsx.vsubwev.d.w" => "__builtin_lsx_vsubwev_d_w",
+    "llvm.loongarch.lsx.vsubwev.d.wu" => "__builtin_lsx_vsubwev_d_wu",
+    "llvm.loongarch.lsx.vsubwev.h.b" => "__builtin_lsx_vsubwev_h_b",
+    "llvm.loongarch.lsx.vsubwev.h.bu" => "__builtin_lsx_vsubwev_h_bu",
+    "llvm.loongarch.lsx.vsubwev.q.d" => "__builtin_lsx_vsubwev_q_d",
+    "llvm.loongarch.lsx.vsubwev.q.du" => "__builtin_lsx_vsubwev_q_du",
+    "llvm.loongarch.lsx.vsubwev.w.h" => "__builtin_lsx_vsubwev_w_h",
+    "llvm.loongarch.lsx.vsubwev.w.hu" => "__builtin_lsx_vsubwev_w_hu",
+    "llvm.loongarch.lsx.vsubwod.d.w" => "__builtin_lsx_vsubwod_d_w",
+    "llvm.loongarch.lsx.vsubwod.d.wu" => "__builtin_lsx_vsubwod_d_wu",
+    "llvm.loongarch.lsx.vsubwod.h.b" => "__builtin_lsx_vsubwod_h_b",
+    "llvm.loongarch.lsx.vsubwod.h.bu" => "__builtin_lsx_vsubwod_h_bu",
+    "llvm.loongarch.lsx.vsubwod.q.d" => "__builtin_lsx_vsubwod_q_d",
+    "llvm.loongarch.lsx.vsubwod.q.du" => "__builtin_lsx_vsubwod_q_du",
+    "llvm.loongarch.lsx.vsubwod.w.h" => "__builtin_lsx_vsubwod_w_h",
+    "llvm.loongarch.lsx.vsubwod.w.hu" => "__builtin_lsx_vsubwod_w_hu",
+    "llvm.loongarch.lsx.vxor.v" => "__builtin_lsx_vxor_v",
+    "llvm.loongarch.lsx.vxori.b" => "__builtin_lsx_vxori_b",
+    "llvm.loongarch.movfcsr2gr" => "__builtin_loongarch_movfcsr2gr",
+    "llvm.loongarch.movgr2fcsr" => "__builtin_loongarch_movgr2fcsr",
+    "llvm.loongarch.syscall" => "__builtin_loongarch_syscall",
     // mips
     "llvm.mips.absq.s.ph" => "__builtin_mips_absq_s_ph",
     "llvm.mips.absq.s.qb" => "__builtin_mips_absq_s_qb",
@@ -2954,6 +4442,8 @@ match name {
     "llvm.nvvm.barrier0.and" => "__nvvm_bar0_and",
     "llvm.nvvm.barrier0.or" => "__nvvm_bar0_or",
     "llvm.nvvm.barrier0.popc" => "__nvvm_bar0_popc",
+    "llvm.nvvm.bf2h.rn" => "__nvvm_bf2h_rn",
+    "llvm.nvvm.bf2h.rn.ftz" => "__nvvm_bf2h_rn_ftz",
     "llvm.nvvm.bitcast.d2ll" => "__nvvm_bitcast_d2ll",
     "llvm.nvvm.bitcast.f2i" => "__nvvm_bitcast_f2i",
     "llvm.nvvm.bitcast.i2f" => "__nvvm_bitcast_i2f",
@@ -3016,8 +4506,6 @@ match name {
     "llvm.nvvm.div.rz.ftz.f" => "__nvvm_div_rz_ftz_f",
     "llvm.nvvm.ex2.approx.d" => "__nvvm_ex2_approx_d",
     "llvm.nvvm.ex2.approx.f" => "__nvvm_ex2_approx_f",
-    "llvm.nvvm.ex2.approx.f16" => "__nvvm_ex2_approx_f16",
-    "llvm.nvvm.ex2.approx.f16x2" => "__nvvm_ex2_approx_f16x2",
     "llvm.nvvm.ex2.approx.ftz.f" => "__nvvm_ex2_approx_ftz_f",
     "llvm.nvvm.f2bf16.rn" => "__nvvm_f2bf16_rn",
     "llvm.nvvm.f2bf16.rn.relu" => "__nvvm_f2bf16_rn_relu",
@@ -3079,11 +4567,17 @@ match name {
     "llvm.nvvm.fma.rn.bf16x2" => "__nvvm_fma_rn_bf16x2",
     "llvm.nvvm.fma.rn.d" => "__nvvm_fma_rn_d",
     "llvm.nvvm.fma.rn.f" => "__nvvm_fma_rn_f",
-    "llvm.nvvm.fma.rn.f16" => "__nvvm_fma_rn_f16",
-    "llvm.nvvm.fma.rn.f16x2" => "__nvvm_fma_rn_f16x2",
+    "llvm.nvvm.fma.rn.ftz.bf16" => "__nvvm_fma_rn_ftz_bf16",
+    "llvm.nvvm.fma.rn.ftz.bf16x2" => "__nvvm_fma_rn_ftz_bf16x2",
     "llvm.nvvm.fma.rn.ftz.f" => "__nvvm_fma_rn_ftz_f",
+    "llvm.nvvm.fma.rn.ftz.relu.bf16" => "__nvvm_fma_rn_ftz_relu_bf16",
+    "llvm.nvvm.fma.rn.ftz.relu.bf16x2" => "__nvvm_fma_rn_ftz_relu_bf16x2",
+    "llvm.nvvm.fma.rn.ftz.sat.bf16" => "__nvvm_fma_rn_ftz_sat_bf16",
+    "llvm.nvvm.fma.rn.ftz.sat.bf16x2" => "__nvvm_fma_rn_ftz_sat_bf16x2",
     "llvm.nvvm.fma.rn.relu.bf16" => "__nvvm_fma_rn_relu_bf16",
     "llvm.nvvm.fma.rn.relu.bf16x2" => "__nvvm_fma_rn_relu_bf16x2",
+    "llvm.nvvm.fma.rn.sat.bf16" => "__nvvm_fma_rn_sat_bf16",
+    "llvm.nvvm.fma.rn.sat.bf16x2" => "__nvvm_fma_rn_sat_bf16x2",
     "llvm.nvvm.fma.rp.d" => "__nvvm_fma_rp_d",
     "llvm.nvvm.fma.rp.f" => "__nvvm_fma_rp_f",
     "llvm.nvvm.fma.rp.ftz.f" => "__nvvm_fma_rp_ftz_f",
@@ -3094,11 +4588,17 @@ match name {
     "llvm.nvvm.fmax.bf16x2" => "__nvvm_fmax_bf16x2",
     "llvm.nvvm.fmax.d" => "__nvvm_fmax_d",
     "llvm.nvvm.fmax.f" => "__nvvm_fmax_f",
-    "llvm.nvvm.fmax.f16" => "__nvvm_fmax_f16",
-    "llvm.nvvm.fmax.f16x2" => "__nvvm_fmax_f16x2",
+    "llvm.nvvm.fmax.ftz.bf16" => "__nvvm_fmax_ftz_bf16",
+    "llvm.nvvm.fmax.ftz.bf16x2" => "__nvvm_fmax_ftz_bf16x2",
     "llvm.nvvm.fmax.ftz.f" => "__nvvm_fmax_ftz_f",
+    "llvm.nvvm.fmax.ftz.nan.bf16" => "__nvvm_fmax_ftz_nan_bf16",
+    "llvm.nvvm.fmax.ftz.nan.bf16x2" => "__nvvm_fmax_ftz_nan_bf16x2",
     "llvm.nvvm.fmax.ftz.nan.f" => "__nvvm_fmax_ftz_nan_f",
+    "llvm.nvvm.fmax.ftz.nan.xorsign.abs.bf16" => "__nvvm_fmax_ftz_nan_xorsign_abs_bf16",
+    "llvm.nvvm.fmax.ftz.nan.xorsign.abs.bf16x2" => "__nvvm_fmax_ftz_nan_xorsign_abs_bf16x2",
     "llvm.nvvm.fmax.ftz.nan.xorsign.abs.f" => "__nvvm_fmax_ftz_nan_xorsign_abs_f",
+    "llvm.nvvm.fmax.ftz.xorsign.abs.bf16" => "__nvvm_fmax_ftz_xorsign_abs_bf16",
+    "llvm.nvvm.fmax.ftz.xorsign.abs.bf16x2" => "__nvvm_fmax_ftz_xorsign_abs_bf16x2",
     "llvm.nvvm.fmax.ftz.xorsign.abs.f" => "__nvvm_fmax_ftz_xorsign_abs_f",
     "llvm.nvvm.fmax.nan.bf16" => "__nvvm_fmax_nan_bf16",
     "llvm.nvvm.fmax.nan.bf16x2" => "__nvvm_fmax_nan_bf16x2",
@@ -3113,11 +4613,17 @@ match name {
     "llvm.nvvm.fmin.bf16x2" => "__nvvm_fmin_bf16x2",
     "llvm.nvvm.fmin.d" => "__nvvm_fmin_d",
     "llvm.nvvm.fmin.f" => "__nvvm_fmin_f",
-    "llvm.nvvm.fmin.f16" => "__nvvm_fmin_f16",
-    "llvm.nvvm.fmin.f16x2" => "__nvvm_fmin_f16x2",
+    "llvm.nvvm.fmin.ftz.bf16" => "__nvvm_fmin_ftz_bf16",
+    "llvm.nvvm.fmin.ftz.bf16x2" => "__nvvm_fmin_ftz_bf16x2",
     "llvm.nvvm.fmin.ftz.f" => "__nvvm_fmin_ftz_f",
+    "llvm.nvvm.fmin.ftz.nan.bf16" => "__nvvm_fmin_ftz_nan_bf16",
+    "llvm.nvvm.fmin.ftz.nan.bf16x2" => "__nvvm_fmin_ftz_nan_bf16x2",
     "llvm.nvvm.fmin.ftz.nan.f" => "__nvvm_fmin_ftz_nan_f",
+    "llvm.nvvm.fmin.ftz.nan.xorsign.abs.bf16" => "__nvvm_fmin_ftz_nan_xorsign_abs_bf16",
+    "llvm.nvvm.fmin.ftz.nan.xorsign.abs.bf16x2" => "__nvvm_fmin_ftz_nan_xorsign_abs_bf16x2",
     "llvm.nvvm.fmin.ftz.nan.xorsign.abs.f" => "__nvvm_fmin_ftz_nan_xorsign_abs_f",
+    "llvm.nvvm.fmin.ftz.xorsign.abs.bf16" => "__nvvm_fmin_ftz_xorsign_abs_bf16",
+    "llvm.nvvm.fmin.ftz.xorsign.abs.bf16x2" => "__nvvm_fmin_ftz_xorsign_abs_bf16x2",
     "llvm.nvvm.fmin.ftz.xorsign.abs.f" => "__nvvm_fmin_ftz_xorsign_abs_f",
     "llvm.nvvm.fmin.nan.bf16" => "__nvvm_fmin_nan_bf16",
     "llvm.nvvm.fmin.nan.bf16x2" => "__nvvm_fmin_nan_bf16x2",
@@ -3979,6 +5485,7 @@ match name {
     "llvm.ppc.maddhd" => "__builtin_ppc_maddhd",
     "llvm.ppc.maddhdu" => "__builtin_ppc_maddhdu",
     "llvm.ppc.maddld" => "__builtin_ppc_maddld",
+    "llvm.ppc.mffsl" => "__builtin_ppc_mffsl",
     "llvm.ppc.mfmsr" => "__builtin_ppc_mfmsr",
     "llvm.ppc.mftbu" => "__builtin_ppc_mftbu",
     "llvm.ppc.mtfsb0" => "__builtin_ppc_mtfsb0",
@@ -4213,6 +5720,28 @@ match name {
     "llvm.r600.read.tgid.x" => "__builtin_r600_read_tgid_x",
     "llvm.r600.read.tgid.y" => "__builtin_r600_read_tgid_y",
     "llvm.r600.read.tgid.z" => "__builtin_r600_read_tgid_z",
+    // riscv
+    "llvm.riscv.aes32dsi" => "__builtin_riscv_aes32dsi",
+    "llvm.riscv.aes32dsmi" => "__builtin_riscv_aes32dsmi",
+    "llvm.riscv.aes32esi" => "__builtin_riscv_aes32esi",
+    "llvm.riscv.aes32esmi" => "__builtin_riscv_aes32esmi",
+    "llvm.riscv.aes64ds" => "__builtin_riscv_aes64ds",
+    "llvm.riscv.aes64dsm" => "__builtin_riscv_aes64dsm",
+    "llvm.riscv.aes64es" => "__builtin_riscv_aes64es",
+    "llvm.riscv.aes64esm" => "__builtin_riscv_aes64esm",
+    "llvm.riscv.aes64im" => "__builtin_riscv_aes64im",
+    "llvm.riscv.aes64ks1i" => "__builtin_riscv_aes64ks1i",
+    "llvm.riscv.aes64ks2" => "__builtin_riscv_aes64ks2",
+    "llvm.riscv.sha512sig0" => "__builtin_riscv_sha512sig0",
+    "llvm.riscv.sha512sig0h" => "__builtin_riscv_sha512sig0h",
+    "llvm.riscv.sha512sig0l" => "__builtin_riscv_sha512sig0l",
+    "llvm.riscv.sha512sig1" => "__builtin_riscv_sha512sig1",
+    "llvm.riscv.sha512sig1h" => "__builtin_riscv_sha512sig1h",
+    "llvm.riscv.sha512sig1l" => "__builtin_riscv_sha512sig1l",
+    "llvm.riscv.sha512sum0" => "__builtin_riscv_sha512sum0",
+    "llvm.riscv.sha512sum0r" => "__builtin_riscv_sha512sum0r",
+    "llvm.riscv.sha512sum1" => "__builtin_riscv_sha512sum1",
+    "llvm.riscv.sha512sum1r" => "__builtin_riscv_sha512sum1r",
     // s390
     "llvm.s390.efpc" => "__builtin_s390_efpc",
     "llvm.s390.etnd" => "__builtin_tx_nesting_depth",
@@ -5912,6 +7441,18 @@ match name {
     "llvm.x86.avx2.vpdpbuud.256" => "__builtin_ia32_vpdpbuud256",
     "llvm.x86.avx2.vpdpbuuds.128" => "__builtin_ia32_vpdpbuuds128",
     "llvm.x86.avx2.vpdpbuuds.256" => "__builtin_ia32_vpdpbuuds256",
+    "llvm.x86.avx2.vpdpwsud.128" => "__builtin_ia32_vpdpwsud128",
+    "llvm.x86.avx2.vpdpwsud.256" => "__builtin_ia32_vpdpwsud256",
+    "llvm.x86.avx2.vpdpwsuds.128" => "__builtin_ia32_vpdpwsuds128",
+    "llvm.x86.avx2.vpdpwsuds.256" => "__builtin_ia32_vpdpwsuds256",
+    "llvm.x86.avx2.vpdpwusd.128" => "__builtin_ia32_vpdpwusd128",
+    "llvm.x86.avx2.vpdpwusd.256" => "__builtin_ia32_vpdpwusd256",
+    "llvm.x86.avx2.vpdpwusds.128" => "__builtin_ia32_vpdpwusds128",
+    "llvm.x86.avx2.vpdpwusds.256" => "__builtin_ia32_vpdpwusds256",
+    "llvm.x86.avx2.vpdpwuud.128" => "__builtin_ia32_vpdpwuud128",
+    "llvm.x86.avx2.vpdpwuud.256" => "__builtin_ia32_vpdpwuud256",
+    "llvm.x86.avx2.vpdpwuuds.128" => "__builtin_ia32_vpdpwuuds128",
+    "llvm.x86.avx2.vpdpwuuds.256" => "__builtin_ia32_vpdpwuuds256",
     "llvm.x86.avx2.vperm2i128" => "__builtin_ia32_permti256",
     "llvm.x86.avx512.add.pd.512" => "__builtin_ia32_addpd512",
     "llvm.x86.avx512.add.ps.512" => "__builtin_ia32_addps512",
@@ -7882,6 +9423,8 @@ match name {
     "llvm.x86.tpause" => "__builtin_ia32_tpause",
     "llvm.x86.umonitor" => "__builtin_ia32_umonitor",
     "llvm.x86.umwait" => "__builtin_ia32_umwait",
+    "llvm.x86.urdmsr" => "__builtin_ia32_urdmsr",
+    "llvm.x86.uwrmsr" => "__builtin_ia32_uwrmsr",
     "llvm.x86.vbcstnebf162ps128" => "__builtin_ia32_vbcstnebf162ps128",
     "llvm.x86.vbcstnebf162ps256" => "__builtin_ia32_vbcstnebf162ps256",
     "llvm.x86.vbcstnesh2ps128" => "__builtin_ia32_vbcstnesh2ps128",
@@ -7909,6 +9452,16 @@ match name {
     "llvm.x86.vgf2p8mulb.128" => "__builtin_ia32_vgf2p8mulb_v16qi",
     "llvm.x86.vgf2p8mulb.256" => "__builtin_ia32_vgf2p8mulb_v32qi",
     "llvm.x86.vgf2p8mulb.512" => "__builtin_ia32_vgf2p8mulb_v64qi",
+    "llvm.x86.vsha512msg1" => "__builtin_ia32_vsha512msg1",
+    "llvm.x86.vsha512msg2" => "__builtin_ia32_vsha512msg2",
+    "llvm.x86.vsha512rnds2" => "__builtin_ia32_vsha512rnds2",
+    "llvm.x86.vsm3msg1" => "__builtin_ia32_vsm3msg1",
+    "llvm.x86.vsm3msg2" => "__builtin_ia32_vsm3msg2",
+    "llvm.x86.vsm3rnds2" => "__builtin_ia32_vsm3rnds2",
+    "llvm.x86.vsm4key4128" => "__builtin_ia32_vsm4key4128",
+    "llvm.x86.vsm4key4256" => "__builtin_ia32_vsm4key4256",
+    "llvm.x86.vsm4rnds4128" => "__builtin_ia32_vsm4rnds4128",
+    "llvm.x86.vsm4rnds4256" => "__builtin_ia32_vsm4rnds4256",
     "llvm.x86.wbinvd" => "__builtin_ia32_wbinvd",
     "llvm.x86.wbnoinvd" => "__builtin_ia32_wbnoinvd",
     "llvm.x86.wrfsbase.32" => "__builtin_ia32_wrfsbase32",
diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/llvm.rs b/compiler/rustc_codegen_gcc/src/intrinsic/llvm.rs
index f28348380d7..35eb4a11005 100644
--- a/compiler/rustc_codegen_gcc/src/intrinsic/llvm.rs
+++ b/compiler/rustc_codegen_gcc/src/intrinsic/llvm.rs
@@ -236,11 +236,17 @@ pub fn adjust_intrinsic_arguments<'a, 'b, 'gcc, 'tcx>(builder: &Builder<'a, 'gcc
                 let arg2 = builder.context.new_cast(None, arg2, arg2_type);
                 args = vec![new_args[0], arg2].into();
             },
+            // These builtins are sent one more argument than needed.
             "__builtin_prefetch" => {
                 let mut new_args = args.to_vec();
                 new_args.pop();
                 args = new_args.into();
             },
+            // The GCC version returns one value of the tuple through a pointer.
+            "__builtin_ia32_rdrand64_step" => {
+                let arg = builder.current_func().new_local(None, builder.ulonglong_type, "return_rdrand_arg");
+                args = vec![arg.get_address(None)].into();
+            },
             _ => (),
         }
     }
@@ -361,6 +367,19 @@ pub fn adjust_intrinsic_return_value<'a, 'gcc, 'tcx>(builder: &Builder<'a, 'gcc,
             // builtin twice, we overwrite the return value with a dummy value.
             return_value = builder.context.new_rvalue_zero(builder.int_type);
         },
+        "__builtin_ia32_rdrand64_step" => {
+            let random_number = args[0].dereference(None).to_rvalue();
+            let success_variable = builder.current_func().new_local(None, return_value.get_type(), "success");
+            builder.llbb().add_assignment(None, success_variable, return_value);
+
+            let field1 = builder.context.new_field(None, random_number.get_type(), "random_number");
+            let field2 = builder.context.new_field(None, return_value.get_type(), "success");
+            let struct_type = builder.context.new_struct_type(None, "rdrand_result", &[field1, field2]);
+            return_value = builder.context.new_struct_constructor(None, struct_type.as_type(), None, &[
+                random_number,
+                success_variable.to_rvalue(),
+            ]);
+        },
         _ => (),
     }
 
@@ -413,15 +432,21 @@ pub fn ignore_arg_cast(func_name: &str, index: usize, args_len: usize) -> bool {
 
 #[cfg(not(feature="master"))]
 pub fn intrinsic<'gcc, 'tcx>(name: &str, cx: &CodegenCx<'gcc, 'tcx>) -> Function<'gcc> {
-    match name {
-        "llvm.x86.xgetbv" | "llvm.x86.sse2.pause" => {
-            let gcc_name = "__builtin_trap";
-            let func = cx.context.get_builtin_function(gcc_name);
-            cx.functions.borrow_mut().insert(gcc_name.to_string(), func);
-            return func;
-        },
-        _ => unimplemented!("unsupported LLVM intrinsic {}", name),
-    }
+    let gcc_name =
+        match name {
+            "llvm.x86.sse2.pause" => {
+                // NOTE: pause is only a hint, so we use a dummy built-in because target built-ins
+                // are not supported in libgccjit 12.
+                "__builtin_inff"
+            },
+            "llvm.x86.xgetbv" => {
+                "__builtin_trap"
+            },
+            _ => unimplemented!("unsupported LLVM intrinsic {}", name),
+        };
+    let func = cx.context.get_builtin_function(gcc_name);
+    cx.functions.borrow_mut().insert(gcc_name.to_string(), func);
+    return func;
 }
 
 #[cfg(feature="master")]
@@ -613,6 +638,7 @@ pub fn intrinsic<'gcc, 'tcx>(name: &str, cx: &CodegenCx<'gcc, 'tcx>) -> Function
         "llvm.fshr.v8i16" => "__builtin_ia32_vpshrdv_v8hi",
         "llvm.x86.fma.vfmadd.sd" => "__builtin_ia32_vfmaddsd3",
         "llvm.x86.fma.vfmadd.ss" => "__builtin_ia32_vfmaddss3",
+        "llvm.x86.rdrand.64" => "__builtin_ia32_rdrand64_step",
 
         // The above doc points to unknown builtins for the following, so override them:
         "llvm.x86.avx2.gather.d.d" => "__builtin_ia32_gathersiv4si",
diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs
index 68a087a1d7f..ba1cae03f3e 100644
--- a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs
+++ b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs
@@ -4,15 +4,17 @@ mod simd;
 #[cfg(feature="master")]
 use std::iter;
 
-use gccjit::{ComparisonOp, Function, RValue, ToRValue, Type, UnaryOp, FunctionType};
+#[cfg(feature="master")]
+use gccjit::FunctionType;
+use gccjit::{ComparisonOp, Function, RValue, ToRValue, Type, UnaryOp};
 use rustc_codegen_ssa::MemFlags;
 use rustc_codegen_ssa::base::wants_msvc_seh;
 use rustc_codegen_ssa::common::IntPredicate;
 use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue};
 use rustc_codegen_ssa::mir::place::PlaceRef;
-use rustc_codegen_ssa::traits::{ArgAbiMethods, BaseTypeMethods, BuilderMethods, ConstMethods, IntrinsicCallMethods};
+use rustc_codegen_ssa::traits::{ArgAbiMethods, BuilderMethods, ConstMethods, IntrinsicCallMethods};
 #[cfg(feature="master")]
-use rustc_codegen_ssa::traits::MiscMethods;
+use rustc_codegen_ssa::traits::{BaseTypeMethods, MiscMethods};
 use rustc_codegen_ssa::errors::InvalidMonomorphization;
 use rustc_middle::bug;
 use rustc_middle::ty::{self, Instance, Ty};
@@ -143,11 +145,15 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
 
                 sym::volatile_load | sym::unaligned_volatile_load => {
                     let tp_ty = fn_args.type_at(0);
-                    let mut ptr = args[0].immediate();
-                    if let PassMode::Cast { cast: ty, .. } = &fn_abi.ret.mode {
-                        ptr = self.pointercast(ptr, self.type_ptr_to(ty.gcc_type(self)));
-                    }
-                    let load = self.volatile_load(ptr.get_type(), ptr);
+                    let ptr = args[0].immediate();
+                    let load =
+                        if let PassMode::Cast { cast: ty, pad_i32: _ } = &fn_abi.ret.mode {
+                            let gcc_ty = ty.gcc_type(self);
+                            self.volatile_load(gcc_ty, ptr)
+                        }
+                        else {
+                            self.volatile_load(self.layout_of(tp_ty).gcc_type(self), ptr)
+                        };
                     // TODO(antoyo): set alignment.
                     self.to_immediate(load, self.layout_of(tp_ty))
                 }
@@ -819,75 +825,58 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
                 value
             };
 
-        if value_type.is_u128(&self.cx) {
-            // TODO(antoyo): implement in the normal algorithm below to have a more efficient
-            // implementation (that does not require a call to __popcountdi2).
-            let popcount = self.context.get_builtin_function("__builtin_popcountll");
+        // only break apart 128-bit ints if they're not natively supported
+        // TODO(antoyo): remove this if/when native 128-bit integers land in libgccjit
+        if value_type.is_u128(&self.cx) && !self.cx.supports_128bit_integers {
             let sixty_four = self.gcc_int(value_type, 64);
             let right_shift = self.gcc_lshr(value, sixty_four);
             let high = self.gcc_int_cast(right_shift, self.cx.ulonglong_type);
-            let high = self.context.new_call(None, popcount, &[high]);
+            let high = self.pop_count(high);
             let low = self.gcc_int_cast(value, self.cx.ulonglong_type);
-            let low = self.context.new_call(None, popcount, &[low]);
+            let low = self.pop_count(low);
             let res = high + low;
             return self.gcc_int_cast(res, result_type);
         }
 
-        // First step.
-        let mask = self.context.new_rvalue_from_long(value_type, 0x5555555555555555);
-        let left = value & mask;
-        let shifted = value >> self.context.new_rvalue_from_int(value_type, 1);
-        let right = shifted & mask;
-        let value = left + right;
-
-        // Second step.
-        let mask = self.context.new_rvalue_from_long(value_type, 0x3333333333333333);
-        let left = value & mask;
-        let shifted = value >> self.context.new_rvalue_from_int(value_type, 2);
-        let right = shifted & mask;
-        let value = left + right;
-
-        // Third step.
-        let mask = self.context.new_rvalue_from_long(value_type, 0x0F0F0F0F0F0F0F0F);
-        let left = value & mask;
-        let shifted = value >> self.context.new_rvalue_from_int(value_type, 4);
-        let right = shifted & mask;
-        let value = left + right;
-
-        if value_type.is_u8(&self.cx) {
-            return self.context.new_cast(None, value, result_type);
-        }
-
-        // Fourth step.
-        let mask = self.context.new_rvalue_from_long(value_type, 0x00FF00FF00FF00FF);
-        let left = value & mask;
-        let shifted = value >> self.context.new_rvalue_from_int(value_type, 8);
-        let right = shifted & mask;
-        let value = left + right;
-
-        if value_type.is_u16(&self.cx) {
-            return self.context.new_cast(None, value, result_type);
-        }
-
-        // Fifth step.
-        let mask = self.context.new_rvalue_from_long(value_type, 0x0000FFFF0000FFFF);
-        let left = value & mask;
-        let shifted = value >> self.context.new_rvalue_from_int(value_type, 16);
-        let right = shifted & mask;
-        let value = left + right;
-
-        if value_type.is_u32(&self.cx) {
-            return self.context.new_cast(None, value, result_type);
-        }
-
-        // Sixth step.
-        let mask = self.context.new_rvalue_from_long(value_type, 0x00000000FFFFFFFF);
-        let left = value & mask;
-        let shifted = value >> self.context.new_rvalue_from_int(value_type, 32);
-        let right = shifted & mask;
-        let value = left + right;
-
-        self.context.new_cast(None, value, result_type)
+        // Use Wenger's algorithm for population count, gcc's seems to play better with it
+        // for (int counter = 0; value != 0; counter++) {
+        //     value &= value - 1;
+        // }
+        let func = self.current_func.borrow().expect("func");
+        let loop_head = func.new_block("head");
+        let loop_body = func.new_block("body");
+        let loop_tail = func.new_block("tail");
+
+        let counter_type = self.int_type;
+        let counter = self.current_func().new_local(None, counter_type, "popcount_counter");
+        let val = self.current_func().new_local(None, value_type, "popcount_value");
+        let zero = self.gcc_zero(counter_type);
+        self.llbb().add_assignment(None, counter, zero);
+        self.llbb().add_assignment(None, val, value);
+        self.br(loop_head);
+
+        // check if value isn't zero
+        self.switch_to_block(loop_head);
+        let zero = self.gcc_zero(value_type);
+        let cond = self.gcc_icmp(IntPredicate::IntNE, val.to_rvalue(), zero);
+        self.cond_br(cond, loop_body, loop_tail);
+
+        // val &= val - 1;
+        self.switch_to_block(loop_body);
+        let one = self.gcc_int(value_type, 1);
+        let sub = self.gcc_sub(val.to_rvalue(), one);
+        let op = self.gcc_and(val.to_rvalue(), sub);
+        loop_body.add_assignment(None, val, op);
+
+        // counter += 1
+        let one = self.gcc_int(counter_type, 1);
+        let op = self.gcc_add(counter.to_rvalue(), one);
+        loop_body.add_assignment(None, counter, op);
+        self.br(loop_head);
+
+        // end of loop
+        self.switch_to_block(loop_tail);
+        self.gcc_int_cast(counter.to_rvalue(), result_type)
     }
 
     // Algorithm from: https://blog.regehr.org/archives/1063
@@ -947,15 +936,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
                             128 => "__rust_i128_addo",
                             _ => unreachable!(),
                         };
-                    let param_a = self.context.new_parameter(None, result_type, "a");
-                    let param_b = self.context.new_parameter(None, result_type, "b");
-                    let result_field = self.context.new_field(None, result_type, "result");
-                    let overflow_field = self.context.new_field(None, self.bool_type, "overflow");
-                    let return_type = self.context.new_struct_type(None, "result_overflow", &[result_field, overflow_field]);
-                    let func = self.context.new_function(None, FunctionType::Extern, return_type.as_type(), &[param_a, param_b], func_name, false);
-                    let result = self.context.new_call(None, func, &[lhs, rhs]);
-                    let overflow = result.access_field(None, overflow_field);
-                    let int_result = result.access_field(None, result_field);
+                    let (int_result, overflow) = self.operation_with_overflow(func_name, lhs, rhs);
                     self.llbb().add_assignment(None, res, int_result);
                     overflow
                 };
@@ -1017,15 +998,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
                             128 => "__rust_i128_subo",
                             _ => unreachable!(),
                         };
-                    let param_a = self.context.new_parameter(None, result_type, "a");
-                    let param_b = self.context.new_parameter(None, result_type, "b");
-                    let result_field = self.context.new_field(None, result_type, "result");
-                    let overflow_field = self.context.new_field(None, self.bool_type, "overflow");
-                    let return_type = self.context.new_struct_type(None, "result_overflow", &[result_field, overflow_field]);
-                    let func = self.context.new_function(None, FunctionType::Extern, return_type.as_type(), &[param_a, param_b], func_name, false);
-                    let result = self.context.new_call(None, func, &[lhs, rhs]);
-                    let overflow = result.access_field(None, overflow_field);
-                    let int_result = result.access_field(None, result_field);
+                    let (int_result, overflow) = self.operation_with_overflow(func_name, lhs, rhs);
                     self.llbb().add_assignment(None, res, int_result);
                     overflow
                 };
@@ -1197,7 +1170,7 @@ fn get_rust_try_fn<'a, 'gcc, 'tcx>(cx: &'a CodegenCx<'gcc, 'tcx>, codegen: &mut
 #[cfg(feature="master")]
 fn gen_fn<'a, 'gcc, 'tcx>(cx: &'a CodegenCx<'gcc, 'tcx>, name: &str, rust_fn_sig: ty::PolyFnSig<'tcx>, codegen: &mut dyn FnMut(Builder<'a, 'gcc, 'tcx>)) -> (Type<'gcc>, Function<'gcc>) {
     let fn_abi = cx.fn_abi_of_fn_ptr(rust_fn_sig, ty::List::empty());
-    let (typ, _, _, _) = fn_abi.gcc_type(cx);
+    let return_type = fn_abi.gcc_type(cx).return_type;
     // FIXME(eddyb) find a nicer way to do this.
     cx.linkage.set(FunctionType::Internal);
     let func = cx.declare_fn(name, fn_abi);
@@ -1207,5 +1180,5 @@ fn gen_fn<'a, 'gcc, 'tcx>(cx: &'a CodegenCx<'gcc, 'tcx>, name: &str, rust_fn_sig
     let block = Builder::append_block(cx, func_val, "entry-block");
     let bx = Builder::build(cx, block);
     codegen(bx);
-    (typ, func)
+    (return_type, func)
 }
diff --git a/compiler/rustc_codegen_gcc/src/lib.rs b/compiler/rustc_codegen_gcc/src/lib.rs
index ce7e31682f1..a530fc994a2 100644
--- a/compiler/rustc_codegen_gcc/src/lib.rs
+++ b/compiler/rustc_codegen_gcc/src/lib.rs
@@ -2,10 +2,19 @@
  * TODO(antoyo): implement equality in libgccjit based on https://zpz.github.io/blog/overloading-equality-operator-in-cpp-class-hierarchy/ (for type equality?)
  * TODO(antoyo): support #[inline] attributes.
  * TODO(antoyo): support LTO (gcc's equivalent to Full LTO is -flto -flto-partition=one — https://documentation.suse.com/sbp/all/html/SBP-GCC-10/index.html).
+ * For Thin LTO, this might be helpful:
+ * In gcc 4.6 -fwhopr was removed and became default with -flto. The non-whopr path can still be executed via -flto-partition=none.
+ *
+ * Maybe some missing optizations enabled by rustc's LTO is in there: https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html
+ * Like -fipa-icf (should be already enabled) and maybe -fdevirtualize-at-ltrans.
+ * TODO: disable debug info always being emitted. Perhaps this slows down things?
  *
  * TODO(antoyo): remove the patches.
  */
 
+#![cfg_attr(not(bootstrap), allow(internal_features))]
+#![cfg_attr(not(bootstrap), doc(rust_logo))]
+#![cfg_attr(not(bootstrap), feature(rustdoc_internals))]
 #![feature(
     rustc_private,
     decl_macro,
@@ -28,6 +37,7 @@ extern crate rustc_codegen_ssa;
 extern crate rustc_data_structures;
 extern crate rustc_errors;
 extern crate rustc_fluent_macro;
+extern crate rustc_fs_util;
 extern crate rustc_hir;
 extern crate rustc_macros;
 extern crate rustc_metadata;
@@ -35,7 +45,8 @@ extern crate rustc_middle;
 extern crate rustc_session;
 extern crate rustc_span;
 extern crate rustc_target;
-extern crate tempfile;
+#[macro_use]
+extern crate tracing;
 
 // This prevents duplicating functions and statics that are already part of the host rustc process.
 #[allow(unused_extern_crates)]
@@ -57,6 +68,7 @@ mod coverageinfo;
 mod debuginfo;
 mod declare;
 mod errors;
+mod gcc_util;
 mod int;
 mod intrinsic;
 mod mono_item;
@@ -64,18 +76,29 @@ mod type_;
 mod type_of;
 
 use std::any::Any;
-use std::sync::{Arc, Mutex};
-
-use crate::errors::LTONotSupported;
-use gccjit::{Context, OptimizationLevel, CType};
+use std::fmt::Debug;
+use std::sync::Arc;
+use std::sync::Mutex;
+#[cfg(not(feature="master"))]
+use std::sync::atomic::AtomicBool;
+#[cfg(not(feature="master"))]
+use std::sync::atomic::Ordering;
+
+use gccjit::{Context, OptimizationLevel};
+#[cfg(feature="master")]
+use gccjit::TargetInfo;
+#[cfg(not(feature="master"))]
+use gccjit::CType;
+use errors::LTONotSupported;
 use rustc_ast::expand::allocator::AllocatorKind;
 use rustc_codegen_ssa::{CodegenResults, CompiledModule, ModuleCodegen};
 use rustc_codegen_ssa::base::codegen_crate;
 use rustc_codegen_ssa::back::write::{CodegenContext, FatLtoInput, ModuleConfig, TargetMachineFactoryFn};
 use rustc_codegen_ssa::back::lto::{LtoModuleCodegen, SerializedModule, ThinModule};
 use rustc_codegen_ssa::target_features::supported_target_features;
-use rustc_codegen_ssa::traits::{CodegenBackend, ExtraBackendMethods, ModuleBufferMethods, ThinBufferMethods, WriteBackendMethods};
 use rustc_data_structures::fx::FxIndexMap;
+use rustc_data_structures::sync::IntoDynSyncSend;
+use rustc_codegen_ssa::traits::{CodegenBackend, ExtraBackendMethods, ThinBufferMethods, WriteBackendMethods};
 use rustc_errors::{DiagnosticMessage, ErrorGuaranteed, Handler, SubdiagnosticMessage};
 use rustc_fluent_macro::fluent_messages;
 use rustc_metadata::EncodedMetadata;
@@ -88,6 +111,9 @@ use rustc_span::Symbol;
 use rustc_span::fatal_error::FatalError;
 use tempfile::TempDir;
 
+use crate::back::lto::ModuleBuffer;
+use crate::gcc_util::target_cpu;
+
 fluent_messages! { "../messages.ftl" }
 
 pub struct PrintOnPanic<F: Fn() -> String>(pub F);
@@ -100,9 +126,47 @@ impl<F: Fn() -> String> Drop for PrintOnPanic<F> {
     }
 }
 
+#[cfg(not(feature="master"))]
+#[derive(Debug)]
+pub struct TargetInfo {
+    supports_128bit_integers: AtomicBool,
+}
+
+#[cfg(not(feature="master"))]
+impl TargetInfo {
+    fn cpu_supports(&self, _feature: &str) -> bool {
+        false
+    }
+
+    fn supports_128bit_int(&self) -> bool {
+        self.supports_128bit_integers.load(Ordering::SeqCst)
+    }
+}
+
+#[derive(Clone)]
+pub struct LockedTargetInfo {
+    info: Arc<Mutex<IntoDynSyncSend<TargetInfo>>>,
+}
+
+impl Debug for LockedTargetInfo {
+    fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        self.info.lock().expect("lock").fmt(formatter)
+    }
+}
+
+impl LockedTargetInfo {
+    fn cpu_supports(&self, feature: &str) -> bool {
+        self.info.lock().expect("lock").cpu_supports(feature)
+    }
+
+    fn supports_128bit_int(&self) -> bool {
+        self.info.lock().expect("lock").supports_128bit_int()
+    }
+}
+
 #[derive(Clone)]
 pub struct GccCodegenBackend {
-    supports_128bit_integers: Arc<Mutex<bool>>,
+    target_info: LockedTargetInfo,
 }
 
 impl CodegenBackend for GccCodegenBackend {
@@ -112,24 +176,40 @@ impl CodegenBackend for GccCodegenBackend {
 
     fn init(&self, sess: &Session) {
         #[cfg(feature="master")]
+        {
+            let target_cpu = target_cpu(sess);
+
+            // Get the second TargetInfo with the correct CPU features by setting the arch.
+            let context = Context::default();
+            if target_cpu != "generic" {
+                context.add_command_line_option(&format!("-march={}", target_cpu));
+            }
+
+            **self.target_info.info.lock().expect("lock") = context.get_target_info();
+        }
+
+        #[cfg(feature="master")]
         gccjit::set_global_personality_function_name(b"rust_eh_personality\0");
-        if sess.lto() != Lto::No {
+        if sess.lto() == Lto::Thin {
             sess.emit_warning(LTONotSupported {});
         }
 
-        let temp_dir = TempDir::new().expect("cannot create temporary directory");
-        let temp_file = temp_dir.into_path().join("result.asm");
-        let check_context = Context::default();
-        check_context.set_print_errors_to_stderr(false);
-        let _int128_ty = check_context.new_c_type(CType::UInt128t);
-        // NOTE: we cannot just call compile() as this would require other files than libgccjit.so.
-        check_context.compile_to_file(gccjit::OutputKind::Assembler, temp_file.to_str().expect("path to str"));
-        *self.supports_128bit_integers.lock().expect("lock") = check_context.get_last_error() == Ok(None);
+        #[cfg(not(feature="master"))]
+        {
+            let temp_dir = TempDir::new().expect("cannot create temporary directory");
+            let temp_file = temp_dir.into_path().join("result.asm");
+            let check_context = Context::default();
+            check_context.set_print_errors_to_stderr(false);
+            let _int128_ty = check_context.new_c_type(CType::UInt128t);
+            // NOTE: we cannot just call compile() as this would require other files than libgccjit.so.
+            check_context.compile_to_file(gccjit::OutputKind::Assembler, temp_file.to_str().expect("path to str"));
+            self.target_info.info.lock().expect("lock").supports_128bit_integers.store(check_context.get_last_error() == Ok(None), Ordering::SeqCst);
+        }
     }
 
     fn provide(&self, providers: &mut Providers) {
-        // FIXME(antoyo) compute list of enabled features from cli flags
-        providers.global_backend_features = |_tcx, ()| vec![];
+        providers.global_backend_features =
+            |tcx, ()| gcc_util::global_gcc_features(tcx.sess, true)
     }
 
     fn codegen_crate<'tcx>(&self, tcx: TyCtxt<'tcx>, metadata: EncodedMetadata, need_metadata_module: bool) -> Box<dyn Any> {
@@ -160,7 +240,7 @@ impl CodegenBackend for GccCodegenBackend {
     }
 
     fn target_features(&self, sess: &Session, allow_unstable: bool) -> Vec<Symbol> {
-        target_features(sess, allow_unstable)
+        target_features(sess, allow_unstable, &self.target_info)
     }
 }
 
@@ -168,13 +248,19 @@ impl ExtraBackendMethods for GccCodegenBackend {
     fn codegen_allocator<'tcx>(&self, tcx: TyCtxt<'tcx>, module_name: &str, kind: AllocatorKind, alloc_error_handler_kind: AllocatorKind) -> Self::Module {
         let mut mods = GccContext {
             context: Context::default(),
+            should_combine_object_files: false,
+            temp_dir: None,
         };
+
+        if tcx.sess.target.arch == "x86" || tcx.sess.target.arch == "x86_64" {
+            mods.context.add_command_line_option("-masm=intel");
+        }
         unsafe { allocator::codegen(tcx, &mut mods, module_name, kind, alloc_error_handler_kind); }
         mods
     }
 
     fn compile_codegen_unit(&self, tcx: TyCtxt<'_>, cgu_name: Symbol) -> (ModuleCodegen<Self::Module>, u64) {
-        base::compile_codegen_unit(tcx, cgu_name, *self.supports_128bit_integers.lock().expect("lock"))
+        base::compile_codegen_unit(tcx, cgu_name, self.target_info.clone())
     }
 
     fn target_machine_factory(&self, _sess: &Session, _opt_level: OptLevel, _features: &[String]) -> TargetMachineFactoryFn<Self> {
@@ -185,14 +271,6 @@ impl ExtraBackendMethods for GccCodegenBackend {
     }
 }
 
-pub struct ModuleBuffer;
-
-impl ModuleBufferMethods for ModuleBuffer {
-    fn data(&self) -> &[u8] {
-        unimplemented!();
-    }
-}
-
 pub struct ThinBuffer;
 
 impl ThinBufferMethods for ThinBuffer {
@@ -203,6 +281,9 @@ impl ThinBufferMethods for ThinBuffer {
 
 pub struct GccContext {
     context: Context<'static>,
+    should_combine_object_files: bool,
+    // Temporary directory used by LTO. We keep it here so that it's not removed before linking.
+    temp_dir: Option<TempDir>,
 }
 
 unsafe impl Send for GccContext {}
@@ -217,18 +298,8 @@ impl WriteBackendMethods for GccCodegenBackend {
     type ThinData = ();
     type ThinBuffer = ThinBuffer;
 
-    fn run_fat_lto(_cgcx: &CodegenContext<Self>, mut modules: Vec<FatLtoInput<Self>>, _cached_modules: Vec<(SerializedModule<Self::ModuleBuffer>, WorkProduct)>) -> Result<LtoModuleCodegen<Self>, FatalError> {
-        // TODO(antoyo): implement LTO by sending -flto to libgccjit and adding the appropriate gcc linker plugins.
-        // NOTE: implemented elsewhere.
-        // TODO(antoyo): what is implemented elsewhere ^ ?
-        let module =
-            match modules.remove(0) {
-                FatLtoInput::InMemory(module) => module,
-                FatLtoInput::Serialized { .. } => {
-                    unimplemented!();
-                }
-            };
-        Ok(LtoModuleCodegen::Fat { module, _serialized_bitcode: vec![] })
+    fn run_fat_lto(cgcx: &CodegenContext<Self>, modules: Vec<FatLtoInput<Self>>, cached_modules: Vec<(SerializedModule<Self::ModuleBuffer>, WorkProduct)>) -> Result<LtoModuleCodegen<Self>, FatalError> {
+        back::lto::run_fat(cgcx, modules, cached_modules)
     }
 
     fn run_thin_lto(_cgcx: &CodegenContext<Self>, _modules: Vec<(String, Self::ThinBuffer)>, _cached_modules: Vec<(SerializedModule<Self::ModuleBuffer>, WorkProduct)>) -> Result<(Vec<LtoModuleCodegen<Self>>, Vec<WorkProduct>), FatalError> {
@@ -277,8 +348,19 @@ impl WriteBackendMethods for GccCodegenBackend {
 /// This is the entrypoint for a hot plugged rustc_codegen_gccjit
 #[no_mangle]
 pub fn __rustc_codegen_backend() -> Box<dyn CodegenBackend> {
+    #[cfg(feature="master")]
+    let info = {
+        // Check whether the target supports 128-bit integers.
+        let context = Context::default();
+        Arc::new(Mutex::new(IntoDynSyncSend(context.get_target_info())))
+    };
+    #[cfg(not(feature="master"))]
+    let info = Arc::new(Mutex::new(IntoDynSyncSend(TargetInfo {
+        supports_128bit_integers: AtomicBool::new(false),
+    })));
+
     Box::new(GccCodegenBackend {
-        supports_128bit_integers: Arc::new(Mutex::new(false)),
+        target_info: LockedTargetInfo { info },
     })
 }
 
@@ -297,22 +379,7 @@ fn to_gcc_opt_level(optlevel: Option<OptLevel>) -> OptimizationLevel {
     }
 }
 
-fn handle_native(name: &str) -> &str {
-    if name != "native" {
-        return name;
-    }
-
-    unimplemented!();
-}
-
-pub fn target_cpu(sess: &Session) -> &str {
-    match sess.opts.cg.target_cpu {
-        Some(ref name) => handle_native(name),
-        None => handle_native(sess.target.cpu.as_ref()),
-    }
-}
-
-pub fn target_features(sess: &Session, allow_unstable: bool) -> Vec<Symbol> {
+pub fn target_features(sess: &Session, allow_unstable: bool, target_info: &LockedTargetInfo) -> Vec<Symbol> {
     supported_target_features(sess)
         .iter()
         .filter_map(
@@ -321,26 +388,13 @@ pub fn target_features(sess: &Session, allow_unstable: bool) -> Vec<Symbol> {
             },
         )
         .filter(|_feature| {
-            // TODO(antoyo): implement a way to get enabled feature in libgccjit.
-            // Probably using the equivalent of __builtin_cpu_supports.
-            // TODO(antoyo): maybe use whatever outputs the following command:
-            // gcc -march=native -Q --help=target
-            #[cfg(feature="master")]
-            {
-                // NOTE: the CPU in the CI doesn't support sse4a, so disable it to make the stdarch tests pass in the CI.
-                (_feature.contains("sse") || _feature.contains("avx")) && !_feature.contains("avx512") && !_feature.contains("sse4a")
-            }
-            #[cfg(not(feature="master"))]
-            {
-                false
-            }
+            target_info.cpu_supports(_feature)
             /*
                adx, aes, avx, avx2, avx512bf16, avx512bitalg, avx512bw, avx512cd, avx512dq, avx512er, avx512f, avx512ifma,
                avx512pf, avx512vbmi, avx512vbmi2, avx512vl, avx512vnni, avx512vp2intersect, avx512vpopcntdq,
                bmi1, bmi2, cmpxchg16b, ermsb, f16c, fma, fxsr, gfni, lzcnt, movbe, pclmulqdq, popcnt, rdrand, rdseed, rtm,
                sha, sse, sse2, sse3, sse4.1, sse4.2, sse4a, ssse3, tbm, vaes, vpclmulqdq, xsave, xsavec, xsaveopt, xsaves
              */
-            //false
         })
         .map(|feature| Symbol::intern(feature))
         .collect()
diff --git a/compiler/rustc_codegen_gcc/src/type_.rs b/compiler/rustc_codegen_gcc/src/type_.rs
index 31899740514..7a89fe81d38 100644
--- a/compiler/rustc_codegen_gcc/src/type_.rs
+++ b/compiler/rustc_codegen_gcc/src/type_.rs
@@ -119,11 +119,11 @@ impl<'gcc, 'tcx> BaseTypeMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
     }
 
     fn type_f32(&self) -> Type<'gcc> {
-        self.context.new_type::<f32>()
+        self.float_type
     }
 
     fn type_f64(&self) -> Type<'gcc> {
-        self.context.new_type::<f64>()
+        self.double_type
     }
 
     fn type_func(&self, params: &[Type<'gcc>], return_type: Type<'gcc>) -> Type<'gcc> {
@@ -216,17 +216,17 @@ impl<'gcc, 'tcx> BaseTypeMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
         value.get_type()
     }
 
-    fn type_array(&self, ty: Type<'gcc>, len: u64) -> Type<'gcc> {
-        // TODO: remove this as well?
-        /*if let Some(struct_type) = ty.is_struct() {
+    #[cfg_attr(feature="master", allow(unused_mut))]
+    fn type_array(&self, ty: Type<'gcc>, mut len: u64) -> Type<'gcc> {
+        #[cfg(not(feature="master"))]
+        if let Some(struct_type) = ty.is_struct() {
             if struct_type.get_field_count() == 0 {
                 // NOTE: since gccjit only supports i32 for the array size and libcore's tests uses a
                 // size of usize::MAX in test_binary_search, we workaround this by setting the size to
                 // zero for ZSTs.
-                // FIXME(antoyo): fix gccjit API.
                 len = 0;
             }
-        }*/
+        }
 
         self.context.new_array_type(None, ty, len)
     }
diff --git a/compiler/rustc_codegen_gcc/src/type_of.rs b/compiler/rustc_codegen_gcc/src/type_of.rs
index cc467801beb..479a814788a 100644
--- a/compiler/rustc_codegen_gcc/src/type_of.rs
+++ b/compiler/rustc_codegen_gcc/src/type_of.rs
@@ -9,7 +9,7 @@ use rustc_middle::ty::print::with_no_trimmed_paths;
 use rustc_target::abi::{self, Abi, Align, F32, F64, FieldsShape, Int, Integer, Pointer, PointeeInfo, Size, TyAbiInterface, Variants};
 use rustc_target::abi::call::{CastTarget, FnAbi, Reg};
 
-use crate::abi::{FnAbiGccExt, GccType};
+use crate::abi::{FnAbiGcc, FnAbiGccExt, GccType};
 use crate::context::CodegenCx;
 use crate::type_::struct_fields;
 
@@ -87,7 +87,7 @@ fn uncached_gcc_type<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, layout: TyAndLayout
         // FIXME(eddyb) producing readable type names for trait objects can result
         // in problematically distinct types due to HRTB and subtyping (see #47638).
         // ty::Dynamic(..) |
-        ty::Adt(..) | ty::Closure(..) | ty::Foreign(..) | ty::Generator(..) | ty::Str
+        ty::Adt(..) | ty::Closure(..) | ty::Foreign(..) | ty::Coroutine(..) | ty::Str
             if !cx.sess().fewer_names() =>
         {
             let mut name = with_no_trimmed_paths!(layout.ty.to_string());
@@ -98,10 +98,10 @@ fn uncached_gcc_type<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, layout: TyAndLayout
                     write!(&mut name, "::{}", def.variant(index).name).unwrap();
                 }
             }
-            if let (&ty::Generator(_, _, _), &Variants::Single { index }) =
+            if let (&ty::Coroutine(_, _, _), &Variants::Single { index }) =
                 (layout.ty.kind(), &layout.variants)
             {
-                write!(&mut name, "::{}", ty::GeneratorArgs::variant_name(index)).unwrap();
+                write!(&mut name, "::{}", ty::CoroutineArgs::variant_name(index)).unwrap();
             }
             Some(name)
         }
@@ -182,6 +182,7 @@ impl<'tcx> LayoutGccExt<'tcx> for TyAndLayout<'tcx> {
     /// of that field's type - this is useful for taking the address of
     /// that field and ensuring the struct has the right alignment.
     fn gcc_type<'gcc>(&self, cx: &CodegenCx<'gcc, 'tcx>) -> Type<'gcc> {
+        use crate::rustc_middle::ty::layout::FnAbiOf;
         // This must produce the same result for `repr(transparent)` wrappers as for the inner type!
         // In other words, this should generally not look at the type at all, but only at the
         // layout.
@@ -191,7 +192,14 @@ impl<'tcx> LayoutGccExt<'tcx> for TyAndLayout<'tcx> {
             if let Some(&ty) = cx.scalar_types.borrow().get(&self.ty) {
                 return ty;
             }
-            let ty = self.scalar_gcc_type_at(cx, scalar, Size::ZERO);
+            let ty =
+                match *self.ty.kind() {
+                    // NOTE: we cannot remove this match like in the LLVM codegen because the call
+                    // to fn_ptr_backend_type handle the on-stack attribute.
+                    // TODO(antoyo): find a less hackish way to hande the on-stack attribute.
+                    ty::FnPtr(sig) => cx.fn_ptr_backend_type(&cx.fn_abi_of_fn_ptr(sig, ty::List::empty())),
+                    _ => self.scalar_gcc_type_at(cx, scalar, Size::ZERO),
+                };
             cx.scalar_types.borrow_mut().insert(self.ty, ty);
             return ty;
         }
@@ -364,7 +372,13 @@ impl<'gcc, 'tcx> LayoutTypeMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
     }
 
     fn fn_decl_backend_type(&self, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> Type<'gcc> {
-        let (return_type, param_types, variadic, _) = fn_abi.gcc_type(self);
-        self.context.new_function_pointer_type(None, return_type, &param_types, variadic)
+        // FIXME(antoyo): Should we do something with `FnAbiGcc::fn_attributes`?
+        let FnAbiGcc {
+            return_type,
+            arguments_type,
+            is_c_variadic,
+            ..
+        } = fn_abi.gcc_type(self);
+        self.context.new_function_pointer_type(None, return_type, &arguments_type, is_c_variadic)
     }
 }
diff --git a/compiler/rustc_codegen_gcc/test.sh b/compiler/rustc_codegen_gcc/test.sh
index b462e5d156b..e896237a1ea 100755
--- a/compiler/rustc_codegen_gcc/test.sh
+++ b/compiler/rustc_codegen_gcc/test.sh
@@ -3,16 +3,7 @@
 # TODO(antoyo): rewrite to cargo-make (or just) or something like that to only rebuild the sysroot when needed?
 
 set -e
-
-if [ -f ./gcc_path ]; then
-    export GCC_PATH=$(cat gcc_path)
-else
-    echo 'Please put the path to your custom build of libgccjit in the file `gcc_path`, see Readme.md for details'
-    exit 1
-fi
-
-export LD_LIBRARY_PATH="$GCC_PATH"
-export LIBRARY_PATH="$GCC_PATH"
+#set -x
 
 flags=
 gcc_master_branch=1
@@ -21,12 +12,18 @@ funcs=()
 build_only=0
 nb_parts=0
 current_part=0
+use_system_gcc=0
+use_backend=0
+cargo_target_dir=""
+
+export CHANNEL='debug'
 
 while [[ $# -gt 0 ]]; do
     case $1 in
         --release)
             codegen_channel=release
             channel="release"
+            export CHANNEL='release'
             shift
             ;;
         --release-sysroot)
@@ -110,6 +107,22 @@ while [[ $# -gt 0 ]]; do
             build_only=1
             shift
             ;;
+        "--use-system-gcc")
+            use_system_gcc=1
+            shift
+            ;;
+        "--use-backend")
+            use_backend=1
+            shift
+            export BUILTIN_BACKEND=$1
+            shift
+            ;;
+        "--out-dir")
+            shift
+            export CARGO_TARGET_DIR=$1
+            cargo_target_dir=$1
+            shift
+            ;;
         "--nb-parts")
             shift
             nb_parts=$1
@@ -127,13 +140,25 @@ while [[ $# -gt 0 ]]; do
     esac
 done
 
-if [[ $channel == "release" ]]; then
-    export CHANNEL='release'
-    CARGO_INCREMENTAL=1 cargo rustc --release $flags
+if [ -f ./gcc_path ]; then
+    export GCC_PATH=$(cat gcc_path)
+elif (( $use_system_gcc == 1 )); then
+    echo 'Using system GCC'
 else
-    echo $LD_LIBRARY_PATH
-    export CHANNEL='debug'
-    cargo rustc $flags
+    echo 'Please put the path to your custom build of libgccjit in the file `gcc_path`, see Readme.md for details'
+    exit 1
+fi
+
+export LD_LIBRARY_PATH="$GCC_PATH"
+export LIBRARY_PATH="$GCC_PATH"
+
+if [[ $use_backend == 0 ]]; then
+    if [[ $channel == "release" ]]; then
+        CARGO_INCREMENTAL=1 cargo rustc --release $flags
+    else
+        echo $LD_LIBRARY_PATH
+        cargo rustc $flags
+    fi
 fi
 
 if (( $build_only == 1 )); then
@@ -144,20 +169,26 @@ fi
 source config.sh
 
 function clean() {
-    rm -r target/out || true
-    mkdir -p target/out/gccjit
+    rm -r $cargo_target_dir || true
+    mkdir -p $cargo_target_dir/gccjit
 }
 
 function mini_tests() {
     echo "[BUILD] mini_core"
-    $RUSTC example/mini_core.rs --crate-name mini_core --crate-type lib,dylib --target $TARGET_TRIPLE
+    crate_types="lib,dylib"
+
+    if [[ "$HOST_TRIPLE" != "$TARGET_TRIPLE" ]]; then
+        crate_types="lib"
+    fi
+
+    $RUST_CMD example/mini_core.rs --crate-name mini_core --crate-type $crate_types --target $TARGET_TRIPLE
 
     echo "[BUILD] example"
-    $RUSTC example/example.rs --crate-type lib --target $TARGET_TRIPLE
+    $RUST_CMD example/example.rs --crate-type lib --target $TARGET_TRIPLE
 
     echo "[AOT] mini_core_hello_world"
-    $RUSTC example/mini_core_hello_world.rs --crate-name mini_core_hello_world --crate-type bin -g --target $TARGET_TRIPLE
-    $RUN_WRAPPER ./target/out/mini_core_hello_world abc bcd
+    $RUST_CMD example/mini_core_hello_world.rs --crate-name mini_core_hello_world --crate-type bin -g --target $TARGET_TRIPLE
+    $RUN_WRAPPER $cargo_target_dir/mini_core_hello_world abc bcd
 }
 
 function build_sysroot() {
@@ -165,41 +196,61 @@ function build_sysroot() {
     time ./build_sysroot/build_sysroot.sh $sysroot_channel
 }
 
+# TODO(GuillaumeGomez): when rewriting in Rust, refactor with the code in tests/lang_tests_common.rs if possible.
+function run_in_vm() {
+    vm_parent_dir=${CG_GCC_VM_DIR:-$(pwd)}
+    vm_dir=vm
+    exe=$1
+    exe_filename=$(basename $exe)
+    vm_home_dir=$vm_parent_dir/$vm_dir/home
+    vm_exe_path=$vm_home_dir/$exe_filename
+    inside_vm_exe_path=/home/$exe_filename
+    sudo cp $exe $vm_exe_path
+
+    shift
+    pushd $vm_parent_dir
+    sudo chroot $vm_dir qemu-m68k-static $inside_vm_exe_path $@
+    popd
+}
+
 function std_tests() {
     echo "[AOT] arbitrary_self_types_pointers_and_wrappers"
-    $RUSTC example/arbitrary_self_types_pointers_and_wrappers.rs --crate-name arbitrary_self_types_pointers_and_wrappers --crate-type bin --target $TARGET_TRIPLE
-    $RUN_WRAPPER ./target/out/arbitrary_self_types_pointers_and_wrappers
+    $RUST_CMD example/arbitrary_self_types_pointers_and_wrappers.rs --crate-name arbitrary_self_types_pointers_and_wrappers --crate-type bin --target $TARGET_TRIPLE
+    $RUN_WRAPPER $cargo_target_dir/arbitrary_self_types_pointers_and_wrappers
 
     echo "[AOT] alloc_system"
-    $RUSTC example/alloc_system.rs --crate-type lib --target "$TARGET_TRIPLE"
+    $RUST_CMD example/alloc_system.rs --crate-type lib --target "$TARGET_TRIPLE"
 
-    echo "[AOT] alloc_example"
-    $RUSTC example/alloc_example.rs --crate-type bin --target $TARGET_TRIPLE
-    $RUN_WRAPPER ./target/out/alloc_example
+    # FIXME: doesn't work on m68k.
+    if [[ "$HOST_TRIPLE" == "$TARGET_TRIPLE" ]]; then
+        echo "[AOT] alloc_example"
+        $RUST_CMD example/alloc_example.rs --crate-type bin --target $TARGET_TRIPLE
+        $RUN_WRAPPER $cargo_target_dir/alloc_example
+    fi
 
     echo "[AOT] dst_field_align"
     # FIXME(antoyo): Re-add -Zmir-opt-level=2 once rust-lang/rust#67529 is fixed.
-    $RUSTC example/dst-field-align.rs --crate-name dst_field_align --crate-type bin --target $TARGET_TRIPLE
-    $RUN_WRAPPER ./target/out/dst_field_align || (echo $?; false)
+    $RUST_CMD example/dst-field-align.rs --crate-name dst_field_align --crate-type bin --target $TARGET_TRIPLE
+    $RUN_WRAPPER $cargo_target_dir/dst_field_align || (echo $?; false)
 
     echo "[AOT] std_example"
     std_flags="--cfg feature=\"master\""
     if (( $gcc_master_branch == 0 )); then
         std_flags=""
     fi
-    $RUSTC example/std_example.rs --crate-type bin --target $TARGET_TRIPLE $std_flags
-    $RUN_WRAPPER ./target/out/std_example --target $TARGET_TRIPLE
+    $RUST_CMD example/std_example.rs --crate-type bin --target $TARGET_TRIPLE $std_flags
+    $RUN_WRAPPER $cargo_target_dir/std_example --target $TARGET_TRIPLE
 
     echo "[AOT] subslice-patterns-const-eval"
-    $RUSTC example/subslice-patterns-const-eval.rs --crate-type bin $TEST_FLAGS --target $TARGET_TRIPLE
-    $RUN_WRAPPER ./target/out/subslice-patterns-const-eval
+    $RUST_CMD example/subslice-patterns-const-eval.rs --crate-type bin $TEST_FLAGS --target $TARGET_TRIPLE
+    $RUN_WRAPPER $cargo_target_dir/subslice-patterns-const-eval
 
     echo "[AOT] track-caller-attribute"
-    $RUSTC example/track-caller-attribute.rs --crate-type bin $TEST_FLAGS --target $TARGET_TRIPLE
-    $RUN_WRAPPER ./target/out/track-caller-attribute
+    $RUST_CMD example/track-caller-attribute.rs --crate-type bin $TEST_FLAGS --target $TARGET_TRIPLE
+    $RUN_WRAPPER $cargo_target_dir/track-caller-attribute
 
     echo "[BUILD] mod_bench"
-    $RUSTC example/mod_bench.rs --crate-type bin --target $TARGET_TRIPLE
+    $RUST_CMD example/mod_bench.rs --crate-type bin --target $TARGET_TRIPLE
 }
 
 function setup_rustc() {
@@ -208,7 +259,7 @@ function setup_rustc() {
     git clone https://github.com/rust-lang/rust.git || true
     cd rust
     git fetch
-    git checkout $(rustc -V | cut -d' ' -f3 | tr -d '(')
+    git checkout $($RUSTC -V | cut -d' ' -f3 | tr -d '(')
     export RUSTFLAGS=
 
     rm config.toml || true
@@ -219,11 +270,12 @@ change-id = 115898
 [rust]
 codegen-backends = []
 deny-warnings = false
+verbose-tests = true
 
 [build]
 cargo = "$(rustup which cargo)"
 local-rebuild = true
-rustc = "$HOME/.rustup/toolchains/$rust_toolchain-$TARGET_TRIPLE/bin/rustc"
+rustc = "$HOME/.rustup/toolchains/$rust_toolchain-$HOST_TRIPLE/bin/rustc"
 
 [target.x86_64-unknown-linux-gnu]
 llvm-filecheck = "`which FileCheck-10 || which FileCheck-11 || which FileCheck-12 || which FileCheck-13 || which FileCheck-14`"
@@ -232,8 +284,8 @@ llvm-filecheck = "`which FileCheck-10 || which FileCheck-11 || which FileCheck-1
 download-ci-llvm = false
 EOF
 
-    rustc -V | cut -d' ' -f3 | tr -d '('
-    git checkout $(rustc -V | cut -d' ' -f3 | tr -d '(') tests
+    $RUSTC -V | cut -d' ' -f3 | tr -d '('
+    git checkout $($RUSTC -V | cut -d' ' -f3 | tr -d '(') tests
 }
 
 function asm_tests() {
@@ -260,17 +312,17 @@ function test_libcore() {
 #echo "[BENCH COMPILE] mod_bench"
 
 #COMPILE_MOD_BENCH_INLINE="$RUSTC example/mod_bench.rs --crate-type bin -Zmir-opt-level=3 -O --crate-name mod_bench_inline"
-#COMPILE_MOD_BENCH_LLVM_0="rustc example/mod_bench.rs --crate-type bin -Copt-level=0 -o target/out/mod_bench_llvm_0 -Cpanic=abort"
-#COMPILE_MOD_BENCH_LLVM_1="rustc example/mod_bench.rs --crate-type bin -Copt-level=1 -o target/out/mod_bench_llvm_1 -Cpanic=abort"
-#COMPILE_MOD_BENCH_LLVM_2="rustc example/mod_bench.rs --crate-type bin -Copt-level=2 -o target/out/mod_bench_llvm_2 -Cpanic=abort"
-#COMPILE_MOD_BENCH_LLVM_3="rustc example/mod_bench.rs --crate-type bin -Copt-level=3 -o target/out/mod_bench_llvm_3 -Cpanic=abort"
+#COMPILE_MOD_BENCH_LLVM_0="rustc example/mod_bench.rs --crate-type bin -Copt-level=0 -o $cargo_target_dir/mod_bench_llvm_0 -Cpanic=abort"
+#COMPILE_MOD_BENCH_LLVM_1="rustc example/mod_bench.rs --crate-type bin -Copt-level=1 -o $cargo_target_dir/mod_bench_llvm_1 -Cpanic=abort"
+#COMPILE_MOD_BENCH_LLVM_2="rustc example/mod_bench.rs --crate-type bin -Copt-level=2 -o $cargo_target_dir/mod_bench_llvm_2 -Cpanic=abort"
+#COMPILE_MOD_BENCH_LLVM_3="rustc example/mod_bench.rs --crate-type bin -Copt-level=3 -o $cargo_target_dir/mod_bench_llvm_3 -Cpanic=abort"
 
 ## Use 100 runs, because a single compilations doesn't take more than ~150ms, so it isn't very slow
 #hyperfine --runs ${COMPILE_RUNS:-100} "$COMPILE_MOD_BENCH_INLINE" "$COMPILE_MOD_BENCH_LLVM_0" "$COMPILE_MOD_BENCH_LLVM_1" "$COMPILE_MOD_BENCH_LLVM_2" "$COMPILE_MOD_BENCH_LLVM_3"
 
 #echo
 #echo "[BENCH RUN] mod_bench"
-#hyperfine --runs ${RUN_RUNS:-10} ./target/out/mod_bench{,_inline} ./target/out/mod_bench_llvm_*
+#hyperfine --runs ${RUN_RUNS:-10} $cargo_target_dir/mod_bench{,_inline} $cargo_target_dir/mod_bench_llvm_*
 
 function extended_rand_tests() {
     if (( $gcc_master_branch == 0 )); then
@@ -345,15 +397,19 @@ function test_rustc() {
 
     git checkout -- tests/ui/issues/auxiliary/issue-3136-a.rs # contains //~ERROR, but shouldn't be removed
 
-    rm -r tests/ui/{abi*,extern/,unsized-locals/,proc-macro/,threads-sendsync/,thinlto/,borrowck/,chalkify/bugs/,test*,*lto*.rs,consts/const-float-bits-reject-conv.rs,consts/issue-miri-1910.rs} || true
-    rm tests/ui/mir/mir_heavy_promoted.rs # this tests is oom-killed in the CI.
-    for test in $(rg --files-with-matches "thread|lto" tests/ui); do
+    rm -r tests/ui/{abi*,extern/,unsized-locals/,proc-macro/,threads-sendsync/,borrowck/,test*,consts/issue-miri-1910.rs} || true
+    rm tests/ui/mir/mir_heavy_promoted.rs # this test is oom-killed in the CI.
+    # Tests generating errors.
+    rm tests/ui/consts/issue-94675.rs
+    for test in $(rg --files-with-matches "thread" tests/ui); do
       rm $test
     done
-    git checkout tests/ui/lto/auxiliary/dylib.rs
     git checkout tests/ui/type-alias-impl-trait/auxiliary/cross_crate_ice.rs
     git checkout tests/ui/type-alias-impl-trait/auxiliary/cross_crate_ice2.rs
     git checkout tests/ui/macros/rfc-2011-nicer-assert-messages/auxiliary/common.rs
+    git checkout tests/ui/imports/ambiguous-1.rs
+    git checkout tests/ui/imports/ambiguous-4-extern.rs
+    git checkout tests/ui/entry-point/auxiliary/bad_main_functions.rs
 
     RUSTC_ARGS="$TEST_FLAGS -Csymbol-mangling-version=v0 -Zcodegen-backend="$(pwd)"/../target/"$CHANNEL"/librustc_codegen_gcc."$dylib_ext" --sysroot "$(pwd)"/../build_sysroot/sysroot"
 
@@ -387,7 +443,7 @@ function test_rustc() {
     fi
 
     echo "[TEST] rustc test suite"
-    COMPILETEST_FORCE_STAGE0=1 ./x.py test --run always --stage 0 tests/ui/ --rustc-args "$RUSTC_ARGS"
+    COMPILETEST_FORCE_STAGE0=1 ./x.py test --run always --stage 0 tests/ui/ --rustc-args "$RUSTC_ARGS" # --target $TARGET_TRIPLE
 }
 
 function test_failing_rustc() {
diff --git a/compiler/rustc_codegen_gcc/tests/lang_tests_common.rs b/compiler/rustc_codegen_gcc/tests/lang_tests_common.rs
index 06de26f7efc..af0133aad46 100644
--- a/compiler/rustc_codegen_gcc/tests/lang_tests_common.rs
+++ b/compiler/rustc_codegen_gcc/tests/lang_tests_common.rs
@@ -1,7 +1,7 @@
 //! The common code for `tests/lang_tests_*.rs`
 use std::{
     env::{self, current_dir},
-    path::PathBuf,
+    path::{Path, PathBuf},
     process::Command,
 };
 
@@ -23,9 +23,29 @@ pub fn main_inner(profile: Profile) {
     let gcc_path = include_str!("../gcc_path");
     let gcc_path = gcc_path.trim();
     env::set_var("LD_LIBRARY_PATH", gcc_path);
+
+    fn rust_filter(filename: &Path) -> bool {
+        filename.extension().expect("extension").to_str().expect("to_str") == "rs"
+    }
+
+    #[cfg(feature="master")]
+    fn filter(filename: &Path) -> bool {
+        rust_filter(filename)
+    }
+
+    #[cfg(not(feature="master"))]
+    fn filter(filename: &Path) -> bool {
+        if let Some(filename) = filename.to_str() {
+            if filename.ends_with("gep.rs") {
+                return false;
+            }
+        }
+        rust_filter(filename)
+    }
+
     LangTester::new()
         .test_dir("tests/run")
-        .test_file_filter(|path| path.extension().expect("extension").to_str().expect("to_str") == "rs")
+        .test_file_filter(filter)
         .test_extract(|source| {
             let lines =
                 source.lines()
@@ -50,6 +70,19 @@ pub fn main_inner(profile: Profile) {
                 "-o", exe.to_str().expect("to_str"),
                 path.to_str().expect("to_str"),
             ]);
+
+            // TODO(antoyo): find a way to send this via a cli argument.
+            let test_target = std::env::var("CG_GCC_TEST_TARGET");
+            if let Ok(ref target) = test_target {
+                compiler.args(&["--target", &target]);
+                let linker = format!("{}-gcc", target);
+                compiler.args(&[format!("-Clinker={}", linker)]);
+                let mut env_path = std::env::var("PATH").unwrap_or_default();
+                // TODO(antoyo): find a better way to add the PATH necessary locally.
+                env_path = format!("/opt/m68k-unknown-linux-gnu/bin:{}", env_path);
+                compiler.env("PATH", env_path);
+            }
+
             if let Some(flags) = option_env!("TEST_FLAGS") {
                 for flag in flags.split_whitespace() {
                     compiler.arg(&flag);
@@ -65,8 +98,37 @@ pub fn main_inner(profile: Profile) {
                 }
             }
             // Test command 2: run `tempdir/x`.
-            let runtime = Command::new(exe);
-            vec![("Compiler", compiler), ("Run-time", runtime)]
+            if test_target.is_ok() {
+                let vm_parent_dir = std::env::var("CG_GCC_VM_DIR")
+                    .map(|dir| PathBuf::from(dir))
+                    .unwrap_or_else(|_| std::env::current_dir().unwrap());
+                let vm_dir = "vm";
+                let exe_filename = exe.file_name().unwrap();
+                let vm_home_dir = vm_parent_dir.join(vm_dir).join("home");
+                let vm_exe_path = vm_home_dir.join(exe_filename);
+                // FIXME(antoyo): panicking here makes the test pass.
+                let inside_vm_exe_path = PathBuf::from("/home").join(&exe_filename);
+                let mut copy = Command::new("sudo");
+                copy.arg("cp");
+                copy.args(&[&exe, &vm_exe_path]);
+
+                let mut runtime = Command::new("sudo");
+                runtime.args(&["chroot", vm_dir, "qemu-m68k-static"]);
+                runtime.arg(inside_vm_exe_path);
+                runtime.current_dir(vm_parent_dir);
+                vec![
+                    ("Compiler", compiler),
+                    ("Copy", copy),
+                    ("Run-time", runtime),
+                ]
+            }
+            else {
+                let runtime = Command::new(exe);
+                vec![
+                    ("Compiler", compiler),
+                    ("Run-time", runtime),
+                ]
+            }
         })
         .run();
 }
diff --git a/compiler/rustc_codegen_gcc/tests/run/abort1.rs b/compiler/rustc_codegen_gcc/tests/run/abort1.rs
index 25041d93e74..44297e12779 100644
--- a/compiler/rustc_codegen_gcc/tests/run/abort1.rs
+++ b/compiler/rustc_codegen_gcc/tests/run/abort1.rs
@@ -3,7 +3,8 @@
 // Run-time:
 //   status: signal
 
-#![feature(auto_traits, lang_items, no_core, start, intrinsics)]
+#![feature(auto_traits, lang_items, no_core, start, intrinsics, rustc_attrs)]
+#![allow(internal_features)]
 
 #![no_std]
 #![no_core]
diff --git a/compiler/rustc_codegen_gcc/tests/run/abort2.rs b/compiler/rustc_codegen_gcc/tests/run/abort2.rs
index e7443c8dbe5..ce816927123 100644
--- a/compiler/rustc_codegen_gcc/tests/run/abort2.rs
+++ b/compiler/rustc_codegen_gcc/tests/run/abort2.rs
@@ -3,7 +3,8 @@
 // Run-time:
 //   status: signal
 
-#![feature(auto_traits, lang_items, no_core, start, intrinsics)]
+#![feature(auto_traits, lang_items, no_core, start, intrinsics, rustc_attrs)]
+#![allow(internal_features)]
 
 #![no_std]
 #![no_core]
diff --git a/compiler/rustc_codegen_gcc/tests/run/array.rs b/compiler/rustc_codegen_gcc/tests/run/array.rs
index 49b28d98f2f..afd0eed8200 100644
--- a/compiler/rustc_codegen_gcc/tests/run/array.rs
+++ b/compiler/rustc_codegen_gcc/tests/run/array.rs
@@ -7,7 +7,8 @@
 //     5
 //     10
 
-#![feature(arbitrary_self_types, auto_traits, lang_items, no_core, start, intrinsics)]
+#![feature(arbitrary_self_types, auto_traits, lang_items, no_core, start, intrinsics, rustc_attrs)]
+#![allow(internal_features)]
 
 #![no_std]
 #![no_core]
diff --git a/compiler/rustc_codegen_gcc/tests/run/asm.rs b/compiler/rustc_codegen_gcc/tests/run/asm.rs
index 38c1eac7adf..56f2aac3d0a 100644
--- a/compiler/rustc_codegen_gcc/tests/run/asm.rs
+++ b/compiler/rustc_codegen_gcc/tests/run/asm.rs
@@ -5,8 +5,10 @@
 
 #![feature(asm_const)]
 
+#[cfg(target_arch="x86_64")]
 use std::arch::{asm, global_asm};
 
+#[cfg(target_arch="x86_64")]
 global_asm!(
     "
     .global add_asm
@@ -20,6 +22,7 @@ extern "C" {
     fn add_asm(a: i64, b: i64) -> i64;
 }
 
+#[cfg(target_arch="x86_64")]
 pub unsafe fn mem_cpy(dst: *mut u8, src: *const u8, len: usize) {
     asm!(
         "rep movsb",
@@ -30,7 +33,8 @@ pub unsafe fn mem_cpy(dst: *mut u8, src: *const u8, len: usize) {
     );
 }
 
-fn main() {
+#[cfg(target_arch="x86_64")]
+fn asm() {
     unsafe {
         asm!("nop");
     }
@@ -124,7 +128,7 @@ fn main() {
     // check const (ATT syntax)
     let mut x: u64 = 42;
     unsafe {
-        asm!("add {}, {}",
+        asm!("add ${}, {}",
             const 1,
             inout(reg) x,
             options(att_syntax)
@@ -173,3 +177,11 @@ fn main() {
     }
     assert_eq!(array1, array2);
 }
+
+#[cfg(not(target_arch="x86_64"))]
+fn asm() {
+}
+
+fn main() {
+    asm();
+}
diff --git a/compiler/rustc_codegen_gcc/tests/run/assign.rs b/compiler/rustc_codegen_gcc/tests/run/assign.rs
index 427c1a25033..5b0db2da294 100644
--- a/compiler/rustc_codegen_gcc/tests/run/assign.rs
+++ b/compiler/rustc_codegen_gcc/tests/run/assign.rs
@@ -5,8 +5,8 @@
 //     7 8
 //     10
 
-#![allow(unused_attributes)]
-#![feature(auto_traits, lang_items, no_core, start, intrinsics, track_caller)]
+#![allow(internal_features, unused_attributes)]
+#![feature(auto_traits, lang_items, no_core, start, intrinsics, rustc_attrs, track_caller)]
 
 #![no_std]
 #![no_core]
diff --git a/compiler/rustc_codegen_gcc/tests/run/closure.rs b/compiler/rustc_codegen_gcc/tests/run/closure.rs
index 8daa681abf7..4ce528f8680 100644
--- a/compiler/rustc_codegen_gcc/tests/run/closure.rs
+++ b/compiler/rustc_codegen_gcc/tests/run/closure.rs
@@ -9,7 +9,8 @@
 //     Both args: 11
 
 #![feature(arbitrary_self_types, auto_traits, lang_items, no_core, start, intrinsics,
-    unboxed_closures)]
+    unboxed_closures, rustc_attrs)]
+#![allow(internal_features)]
 
 #![no_std]
 #![no_core]
diff --git a/compiler/rustc_codegen_gcc/tests/run/condition.rs b/compiler/rustc_codegen_gcc/tests/run/condition.rs
index b7a13081dea..1b3ae6dc004 100644
--- a/compiler/rustc_codegen_gcc/tests/run/condition.rs
+++ b/compiler/rustc_codegen_gcc/tests/run/condition.rs
@@ -5,7 +5,8 @@
 //   stdout: true
 //     1
 
-#![feature(arbitrary_self_types, auto_traits, lang_items, no_core, start, intrinsics)]
+#![feature(arbitrary_self_types, auto_traits, lang_items, no_core, start, intrinsics, rustc_attrs)]
+#![allow(internal_features)]
 
 #![no_std]
 #![no_core]
diff --git a/compiler/rustc_codegen_gcc/tests/run/empty_main.rs b/compiler/rustc_codegen_gcc/tests/run/empty_main.rs
index c02cfd2a85f..e66a859ad69 100644
--- a/compiler/rustc_codegen_gcc/tests/run/empty_main.rs
+++ b/compiler/rustc_codegen_gcc/tests/run/empty_main.rs
@@ -4,6 +4,7 @@
 //   status: 0
 
 #![feature(auto_traits, lang_items, no_core, start)]
+#![allow(internal_features)]
 
 #![no_std]
 #![no_core]
@@ -34,6 +35,6 @@ pub(crate) unsafe auto trait Freeze {}
  */
 
 #[start]
-fn main(mut argc: isize, _argv: *const *const u8) -> isize {
+fn main(_argc: isize, _argv: *const *const u8) -> isize {
     0
 }
diff --git a/compiler/rustc_codegen_gcc/tests/run/exit.rs b/compiler/rustc_codegen_gcc/tests/run/exit.rs
index 956e53dd4aa..bf1cbeef302 100644
--- a/compiler/rustc_codegen_gcc/tests/run/exit.rs
+++ b/compiler/rustc_codegen_gcc/tests/run/exit.rs
@@ -4,6 +4,7 @@
 //   status: 2
 
 #![feature(auto_traits, lang_items, no_core, start, intrinsics)]
+#![allow(internal_features)]
 
 #![no_std]
 #![no_core]
diff --git a/compiler/rustc_codegen_gcc/tests/run/exit_code.rs b/compiler/rustc_codegen_gcc/tests/run/exit_code.rs
index eeab3520951..be7a233efda 100644
--- a/compiler/rustc_codegen_gcc/tests/run/exit_code.rs
+++ b/compiler/rustc_codegen_gcc/tests/run/exit_code.rs
@@ -4,6 +4,7 @@
 //   status: 1
 
 #![feature(auto_traits, lang_items, no_core, start)]
+#![allow(internal_features)]
 
 #![no_std]
 #![no_core]
diff --git a/compiler/rustc_codegen_gcc/tests/run/fun_ptr.rs b/compiler/rustc_codegen_gcc/tests/run/fun_ptr.rs
index 8a196f774c8..96030359772 100644
--- a/compiler/rustc_codegen_gcc/tests/run/fun_ptr.rs
+++ b/compiler/rustc_codegen_gcc/tests/run/fun_ptr.rs
@@ -4,7 +4,8 @@
 //   status: 0
 //   stdout: 1
 
-#![feature(arbitrary_self_types, auto_traits, lang_items, no_core, start, intrinsics)]
+#![feature(arbitrary_self_types, auto_traits, lang_items, no_core, start, intrinsics, rustc_attrs)]
+#![allow(internal_features)]
 
 #![no_std]
 #![no_core]
diff --git a/compiler/rustc_codegen_gcc/tests/run/gep.rs b/compiler/rustc_codegen_gcc/tests/run/gep.rs
new file mode 100644
index 00000000000..c3d1672cff5
--- /dev/null
+++ b/compiler/rustc_codegen_gcc/tests/run/gep.rs
@@ -0,0 +1,10 @@
+// Compiler:
+//
+// Run-time:
+//   status: 0
+
+fn main() {
+    let mut value = (1, 1);
+    let ptr = &mut value as *mut (i32, i32);
+    println!("{:?}", ptr.wrapping_offset(10));
+}
diff --git a/compiler/rustc_codegen_gcc/tests/run/int_overflow.rs b/compiler/rustc_codegen_gcc/tests/run/int_overflow.rs
index c3fcb3c0a2a..78872159f62 100644
--- a/compiler/rustc_codegen_gcc/tests/run/int_overflow.rs
+++ b/compiler/rustc_codegen_gcc/tests/run/int_overflow.rs
@@ -4,138 +4,20 @@
 //   stdout: Success
 //   status: signal
 
-#![allow(unused_attributes)]
-#![feature(auto_traits, lang_items, no_core, start, intrinsics)]
+fn main() {
+    std::panic::set_hook(Box::new(|_| {
+        println!("Success");
+        std::process::abort();
+    }));
 
-#![no_std]
-#![no_core]
-
-/*
- * Core
- */
-
-// Because we don't have core yet.
-#[lang = "sized"]
-pub trait Sized {}
-
-#[lang = "copy"]
-trait Copy {
-}
-
-impl Copy for isize {}
-impl Copy for *mut i32 {}
-impl Copy for usize {}
-impl Copy for i32 {}
-impl Copy for u8 {}
-impl Copy for i8 {}
-
-#[lang = "receiver"]
-trait Receiver {
-}
-
-#[lang = "freeze"]
-pub(crate) unsafe auto trait Freeze {}
-
-#[lang = "panic_location"]
-struct PanicLocation {
-    file: &'static str,
-    line: u32,
-    column: u32,
-}
-
-mod libc {
-    #[link(name = "c")]
-    extern "C" {
-        pub fn puts(s: *const u8) -> i32;
-        pub fn fflush(stream: *mut i32) -> i32;
-
-        pub static stdout: *mut i32;
-    }
-}
-
-mod intrinsics {
-    extern "rust-intrinsic" {
-        #[rustc_safe_intrinsic]
-        pub fn abort() -> !;
-    }
-}
-
-#[lang = "panic"]
-#[track_caller]
-#[no_mangle]
-pub fn panic(_msg: &'static str) -> ! {
-    unsafe {
-        // Panicking is expected iff overflow checking is enabled.
-        #[cfg(debug_assertions)]
-        libc::puts("Success\0" as *const str as *const u8);
-        libc::fflush(libc::stdout);
-        intrinsics::abort();
-    }
-}
-
-#[lang = "add"]
-trait Add<RHS = Self> {
-    type Output;
-
-    fn add(self, rhs: RHS) -> Self::Output;
-}
-
-impl Add for u8 {
-    type Output = Self;
-
-    fn add(self, rhs: Self) -> Self {
-        self + rhs
-    }
-}
-
-impl Add for i8 {
-    type Output = Self;
-
-    fn add(self, rhs: Self) -> Self {
-        self + rhs
-    }
-}
-
-impl Add for i32 {
-    type Output = Self;
-
-    fn add(self, rhs: Self) -> Self {
-        self + rhs
-    }
-}
-
-impl Add for usize {
-    type Output = Self;
-
-    fn add(self, rhs: Self) -> Self {
-        self + rhs
-    }
-}
-
-impl Add for isize {
-    type Output = Self;
-
-    fn add(self, rhs: Self) -> Self {
-        self + rhs
-    }
-}
-
-/*
- * Code
- */
-
-#[start]
-fn main(mut argc: isize, _argv: *const *const u8) -> isize {
-    let int = 9223372036854775807isize;
-    let int = int + argc;  // overflow
+    let arg_count = std::env::args().count();
+    let int = isize::MAX;
+    let _int = int + arg_count as isize;  // overflow
 
     // If overflow checking is disabled, we should reach here.
     #[cfg(not(debug_assertions))]
     unsafe {
-        libc::puts("Success\0" as *const str as *const u8);
-        libc::fflush(libc::stdout);
-        intrinsics::abort();
+        println!("Success");
+        std::process::abort();
     }
-
-    int
 }
diff --git a/compiler/rustc_codegen_gcc/tests/run/mut_ref.rs b/compiler/rustc_codegen_gcc/tests/run/mut_ref.rs
index 2a2ea8b8bf0..194e55a3dea 100644
--- a/compiler/rustc_codegen_gcc/tests/run/mut_ref.rs
+++ b/compiler/rustc_codegen_gcc/tests/run/mut_ref.rs
@@ -7,8 +7,8 @@
 //     6
 //     11
 
-#![allow(unused_attributes)]
-#![feature(auto_traits, lang_items, no_core, start, intrinsics, track_caller)]
+#![allow(internal_features, unused_attributes)]
+#![feature(auto_traits, lang_items, no_core, start, intrinsics, rustc_attrs, track_caller)]
 
 #![no_std]
 #![no_core]
diff --git a/compiler/rustc_codegen_gcc/tests/run/operations.rs b/compiler/rustc_codegen_gcc/tests/run/operations.rs
index 67b9f241dbb..2d781670873 100644
--- a/compiler/rustc_codegen_gcc/tests/run/operations.rs
+++ b/compiler/rustc_codegen_gcc/tests/run/operations.rs
@@ -5,8 +5,8 @@
 //     39
 //     10
 
-#![allow(unused_attributes)]
-#![feature(auto_traits, lang_items, no_core, start, intrinsics, arbitrary_self_types)]
+#![allow(internal_features, unused_attributes)]
+#![feature(auto_traits, lang_items, no_core, start, intrinsics, arbitrary_self_types, rustc_attrs)]
 
 #![no_std]
 #![no_core]
diff --git a/compiler/rustc_codegen_gcc/tests/run/ptr_cast.rs b/compiler/rustc_codegen_gcc/tests/run/ptr_cast.rs
index da8a8295d56..09d77abe27c 100644
--- a/compiler/rustc_codegen_gcc/tests/run/ptr_cast.rs
+++ b/compiler/rustc_codegen_gcc/tests/run/ptr_cast.rs
@@ -4,7 +4,8 @@
 //   status: 0
 //   stdout: 1
 
-#![feature(arbitrary_self_types, auto_traits, lang_items, no_core, start, intrinsics)]
+#![feature(arbitrary_self_types, auto_traits, lang_items, no_core, start, intrinsics, rustc_attrs)]
+#![allow(internal_features)]
 
 #![no_std]
 #![no_core]
diff --git a/compiler/rustc_codegen_gcc/tests/run/return-tuple.rs b/compiler/rustc_codegen_gcc/tests/run/return-tuple.rs
index 6fa10dca06f..8d40deb8c85 100644
--- a/compiler/rustc_codegen_gcc/tests/run/return-tuple.rs
+++ b/compiler/rustc_codegen_gcc/tests/run/return-tuple.rs
@@ -7,6 +7,7 @@
 //     42
 
 #![feature(auto_traits, lang_items, no_core, start, intrinsics)]
+#![allow(internal_features)]
 
 #![no_std]
 #![no_core]
diff --git a/compiler/rustc_codegen_gcc/tests/run/slice.rs b/compiler/rustc_codegen_gcc/tests/run/slice.rs
index 96f1c4792e5..1262c86c810 100644
--- a/compiler/rustc_codegen_gcc/tests/run/slice.rs
+++ b/compiler/rustc_codegen_gcc/tests/run/slice.rs
@@ -4,7 +4,8 @@
 //   status: 0
 //   stdout: 5
 
-#![feature(arbitrary_self_types, auto_traits, lang_items, no_core, start, intrinsics)]
+#![feature(arbitrary_self_types, auto_traits, lang_items, no_core, start, intrinsics, rustc_attrs)]
+#![allow(internal_features)]
 
 #![no_std]
 #![no_core]
diff --git a/compiler/rustc_codegen_gcc/tests/run/static.rs b/compiler/rustc_codegen_gcc/tests/run/static.rs
index 19201f1df26..0b933754c29 100644
--- a/compiler/rustc_codegen_gcc/tests/run/static.rs
+++ b/compiler/rustc_codegen_gcc/tests/run/static.rs
@@ -9,7 +9,8 @@
 //      12
 //      1
 
-#![feature(auto_traits, lang_items, no_core, start, intrinsics)]
+#![feature(auto_traits, lang_items, no_core, start, intrinsics, rustc_attrs)]
+#![allow(internal_features)]
 
 #![no_std]
 #![no_core]
diff --git a/compiler/rustc_codegen_gcc/tests/run/structs.rs b/compiler/rustc_codegen_gcc/tests/run/structs.rs
index 6c8884855ac..d6455667400 100644
--- a/compiler/rustc_codegen_gcc/tests/run/structs.rs
+++ b/compiler/rustc_codegen_gcc/tests/run/structs.rs
@@ -6,6 +6,7 @@
 //     2
 
 #![feature(auto_traits, lang_items, no_core, start, intrinsics)]
+#![allow(internal_features)]
 
 #![no_std]
 #![no_core]
diff --git a/compiler/rustc_codegen_gcc/tests/run/tuple.rs b/compiler/rustc_codegen_gcc/tests/run/tuple.rs
index 0b670bf2674..8a7d85ae867 100644
--- a/compiler/rustc_codegen_gcc/tests/run/tuple.rs
+++ b/compiler/rustc_codegen_gcc/tests/run/tuple.rs
@@ -5,6 +5,7 @@
 //   stdout: 3
 
 #![feature(auto_traits, lang_items, no_core, start, intrinsics)]
+#![allow(internal_features)]
 
 #![no_std]
 #![no_core]
diff --git a/compiler/rustc_codegen_gcc/tests/run/volatile.rs b/compiler/rustc_codegen_gcc/tests/run/volatile.rs
new file mode 100644
index 00000000000..8b043312593
--- /dev/null
+++ b/compiler/rustc_codegen_gcc/tests/run/volatile.rs
@@ -0,0 +1,26 @@
+// Compiler:
+//
+// Run-time:
+//   status: 0
+
+use std::mem::MaybeUninit;
+
+#[derive(Debug)]
+struct Struct {
+    pointer: *const (),
+    func: unsafe fn(*const ()),
+}
+
+fn func(ptr: *const ()) {
+}
+
+fn main() {
+    let mut x = MaybeUninit::<&Struct>::uninit();
+    x.write(&Struct {
+        pointer: std::ptr::null(),
+        func,
+    });
+    let x = unsafe { x.assume_init() };
+    let value = unsafe { (x as *const Struct).read_volatile() };
+    println!("{:?}", value);
+}
diff --git a/compiler/rustc_codegen_gcc/tools/generate_intrinsics.py b/compiler/rustc_codegen_gcc/tools/generate_intrinsics.py
index 83abe145e64..90fb7bfad27 100644
--- a/compiler/rustc_codegen_gcc/tools/generate_intrinsics.py
+++ b/compiler/rustc_codegen_gcc/tools/generate_intrinsics.py
@@ -46,10 +46,10 @@ def convert_to_string(content):
 
 
 def extract_instrinsics_from_llvm(llvm_path, intrinsics):
-    p = subprocess.Popen(
-        ["llvm-tblgen", "llvm/IR/Intrinsics.td"],
-        cwd=os.path.join(llvm_path, "llvm/include"),
-        stdout=subprocess.PIPE)
+    command = ["llvm-tblgen", "llvm/IR/Intrinsics.td"]
+    cwd = os.path.join(llvm_path, "llvm/include")
+    print("=> Running command `{}` from `{}`".format(command, cwd))
+    p = subprocess.Popen(command, cwd=cwd, stdout=subprocess.PIPE)
     output, err = p.communicate()
     lines = convert_to_string(output).splitlines()
     pos = 0
diff --git a/compiler/rustc_codegen_gcc/y.sh b/compiler/rustc_codegen_gcc/y.sh
new file mode 100755
index 00000000000..188109743e3
--- /dev/null
+++ b/compiler/rustc_codegen_gcc/y.sh
@@ -0,0 +1,8 @@
+#!/usr/bin/env bash
+
+set -e
+echo "[BUILD] build system" 1>&2
+cd build_system
+cargo build --release
+cd ..
+./build_system/target/release/y $@