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/Cargo.lock10
-rw-r--r--compiler/rustc_codegen_gcc/Cargo.toml3
-rw-r--r--compiler/rustc_codegen_gcc/build_system/build_sysroot/Cargo.toml1
-rw-r--r--compiler/rustc_codegen_gcc/build_system/src/abi_test.rs65
-rw-r--r--compiler/rustc_codegen_gcc/build_system/src/main.rs8
-rw-r--r--compiler/rustc_codegen_gcc/build_system/src/test.rs37
-rw-r--r--compiler/rustc_codegen_gcc/example/mini_core_hello_world.rs9
-rw-r--r--compiler/rustc_codegen_gcc/patches/0001-Pin-compiler_builtins-to-0.1.160.patch39
-rw-r--r--compiler/rustc_codegen_gcc/patches/tests/0001-Workaround-to-make-a-run-make-test-pass.patch25
-rw-r--r--compiler/rustc_codegen_gcc/rust-toolchain2
-rw-r--r--compiler/rustc_codegen_gcc/src/abi.rs4
-rw-r--r--compiler/rustc_codegen_gcc/src/allocator.rs44
-rw-r--r--compiler/rustc_codegen_gcc/src/back/lto.rs15
-rw-r--r--compiler/rustc_codegen_gcc/src/back/write.rs4
-rw-r--r--compiler/rustc_codegen_gcc/src/builder.rs101
-rw-r--r--compiler/rustc_codegen_gcc/src/common.rs37
-rw-r--r--compiler/rustc_codegen_gcc/src/consts.rs4
-rw-r--r--compiler/rustc_codegen_gcc/src/context.rs38
-rw-r--r--compiler/rustc_codegen_gcc/src/debuginfo.rs6
-rw-r--r--compiler/rustc_codegen_gcc/src/declare.rs5
-rw-r--r--compiler/rustc_codegen_gcc/src/intrinsic/archs.rs124
-rw-r--r--compiler/rustc_codegen_gcc/src/intrinsic/llvm.rs37
-rw-r--r--compiler/rustc_codegen_gcc/src/intrinsic/mod.rs27
-rw-r--r--compiler/rustc_codegen_gcc/src/intrinsic/simd.rs9
-rw-r--r--compiler/rustc_codegen_gcc/src/lib.rs41
-rw-r--r--compiler/rustc_codegen_gcc/tests/failing-ui-tests.txt1
-rw-r--r--compiler/rustc_codegen_gcc/tools/generate_intrinsics.py12
27 files changed, 362 insertions, 346 deletions
diff --git a/compiler/rustc_codegen_gcc/Cargo.lock b/compiler/rustc_codegen_gcc/Cargo.lock
index b20c181a8cb..7f35c1a80bd 100644
--- a/compiler/rustc_codegen_gcc/Cargo.lock
+++ b/compiler/rustc_codegen_gcc/Cargo.lock
@@ -144,6 +144,15 @@ dependencies = [
 ]
 
 [[package]]
+name = "object"
+version = "0.37.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "03fd943161069e1768b4b3d050890ba48730e590f57e56d4aa04e7e090e61b4a"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
 name = "once_cell"
 version = "1.20.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -179,6 +188,7 @@ dependencies = [
  "boml",
  "gccjit",
  "lang_tester",
+ "object",
  "tempfile",
 ]
 
diff --git a/compiler/rustc_codegen_gcc/Cargo.toml b/compiler/rustc_codegen_gcc/Cargo.toml
index c284e3f060b..193348d1ef6 100644
--- a/compiler/rustc_codegen_gcc/Cargo.toml
+++ b/compiler/rustc_codegen_gcc/Cargo.toml
@@ -22,6 +22,8 @@ master = ["gccjit/master"]
 default = ["master"]
 
 [dependencies]
+object = { version = "0.37.0", default-features = false, features = ["std", "read"] }
+tempfile = "3.20"
 gccjit = "2.7"
 #gccjit = { git = "https://github.com/rust-lang/gccjit.rs" }
 
@@ -31,7 +33,6 @@ gccjit = "2.7"
 [dev-dependencies]
 boml = "0.3.1"
 lang_tester = "0.8.0"
-tempfile = "3.20"
 
 [profile.dev]
 # By compiling dependencies with optimizations, performing tests gets much faster.
diff --git a/compiler/rustc_codegen_gcc/build_system/build_sysroot/Cargo.toml b/compiler/rustc_codegen_gcc/build_system/build_sysroot/Cargo.toml
index 931f6097abc..29a3bcec304 100644
--- a/compiler/rustc_codegen_gcc/build_system/build_sysroot/Cargo.toml
+++ b/compiler/rustc_codegen_gcc/build_system/build_sysroot/Cargo.toml
@@ -6,6 +6,7 @@ resolver = "2"
 
 [dependencies]
 core = { path = "./sysroot_src/library/core" }
+compiler_builtins = { path = "./sysroot_src/library/compiler-builtins/compiler-builtins" }
 alloc = { path = "./sysroot_src/library/alloc" }
 std = { path = "./sysroot_src/library/std", features = ["panic_unwind", "backtrace"] }
 test = { path = "./sysroot_src/library/test" }
diff --git a/compiler/rustc_codegen_gcc/build_system/src/abi_test.rs b/compiler/rustc_codegen_gcc/build_system/src/abi_test.rs
new file mode 100644
index 00000000000..3c1531be27a
--- /dev/null
+++ b/compiler/rustc_codegen_gcc/build_system/src/abi_test.rs
@@ -0,0 +1,65 @@
+use std::ffi::OsStr;
+use std::path::Path;
+
+use crate::utils::run_command_with_output;
+
+fn show_usage() {
+    println!(
+        r#"
+`abi-test` command help:
+    --help                 : Show this help"#
+    );
+}
+
+pub fn run() -> Result<(), String> {
+    let mut args = std::env::args().skip(2);
+    // FractalFir: In the future, I'd like to add some more subcommands / options.
+    // So, this loop ought to stay for that purpose. It should also stay as a while loop(to parse args)
+    #[allow(clippy::never_loop, clippy::while_let_on_iterator)]
+    while let Some(arg) = args.next() {
+        match arg.as_str() {
+            "--help" => {
+                show_usage();
+                return Ok(());
+            }
+            _ => return Err(format!("Unknown option {arg:?}")),
+        }
+    }
+    // Ensure that we have a cloned version of abi-cafe on hand.
+    crate::utils::git_clone(
+        "https://github.com/Gankra/abi-cafe.git",
+        Some("clones/abi-cafe".as_ref()),
+        true,
+    )
+    .map_err(|err| (format!("Git clone failed with message: {err:?}!")))?;
+    // Configure abi-cafe to use the exact same rustc version we use - this is crucial.
+    // Otherwise, the concept of ABI compatibility becomes meanignless.
+    std::fs::copy("rust-toolchain", "clones/abi-cafe/rust-toolchain")
+        .expect("Could not copy toolchain configs!");
+    // Get the backend path.
+    // We will use the *debug* build of the backend - it has more checks enabled.
+    let backend_path = std::path::absolute("target/debug/librustc_codegen_gcc.so").unwrap();
+    let backend_arg = format!("--add-rustc-codegen-backend=cg_gcc:{}", backend_path.display());
+    // Run ABI cafe using cargo.
+    let cmd: &[&dyn AsRef<OsStr>] = &[
+        &"cargo",
+        &"run",
+        &"--release",
+        &"--",
+        &backend_arg,
+        // Test rust-LLVM to Rust-GCC calls
+        &"--pairs",
+        &"rustc_calls_cg_gcc",
+        &"--pairs",
+        &"cg_gcc_calls_rustc",
+        // Test Rust-GCC to C calls
+        &"--pairs",
+        &"cg_gcc_calls_c",
+        &"--pairs",
+        &"c_calls_cg_gcc",
+    ];
+    // Run ABI cafe.
+    run_command_with_output(cmd, Some(Path::new("clones/abi-cafe")))?;
+
+    Ok(())
+}
diff --git a/compiler/rustc_codegen_gcc/build_system/src/main.rs b/compiler/rustc_codegen_gcc/build_system/src/main.rs
index 078a4726ba8..ae975c94fff 100644
--- a/compiler/rustc_codegen_gcc/build_system/src/main.rs
+++ b/compiler/rustc_codegen_gcc/build_system/src/main.rs
@@ -1,5 +1,6 @@
 use std::{env, process};
 
+mod abi_test;
 mod build;
 mod clean;
 mod clone_gcc;
@@ -12,7 +13,6 @@ mod rust_tools;
 mod rustc_info;
 mod test;
 mod utils;
-
 const BUILD_DIR: &str = "build";
 
 macro_rules! arg_error {
@@ -44,7 +44,8 @@ Commands:
         info      : Displays information about the build environment and project configuration.
         clone-gcc : Clones the GCC compiler from a specified source.
         fmt       : Runs rustfmt
-        fuzz      : Fuzzes `cg_gcc` using rustlantis"
+        fuzz      : Fuzzes `cg_gcc` using rustlantis
+        abi-test   : Runs the abi-cafe test suite on the codegen, checking for ABI compatibility with LLVM"
     );
 }
 
@@ -59,6 +60,7 @@ pub enum Command {
     Info,
     Fmt,
     Fuzz,
+    AbiTest,
 }
 
 fn main() {
@@ -77,6 +79,7 @@ fn main() {
         Some("test") => Command::Test,
         Some("info") => Command::Info,
         Some("clone-gcc") => Command::CloneGcc,
+        Some("abi-test") => Command::AbiTest,
         Some("fmt") => Command::Fmt,
         Some("fuzz") => Command::Fuzz,
         Some("--help") => {
@@ -102,6 +105,7 @@ fn main() {
         Command::CloneGcc => clone_gcc::run(),
         Command::Fmt => fmt::run(),
         Command::Fuzz => fuzz::run(),
+        Command::AbiTest => abi_test::run(),
     } {
         eprintln!("Command failed to run: {e}");
         process::exit(1);
diff --git a/compiler/rustc_codegen_gcc/build_system/src/test.rs b/compiler/rustc_codegen_gcc/build_system/src/test.rs
index bcaab0fb526..cbb0f949383 100644
--- a/compiler/rustc_codegen_gcc/build_system/src/test.rs
+++ b/compiler/rustc_codegen_gcc/build_system/src/test.rs
@@ -9,8 +9,8 @@ use crate::build;
 use crate::config::{Channel, ConfigInfo};
 use crate::utils::{
     create_dir, get_sysroot_dir, get_toolchain, git_clone, git_clone_root_dir, remove_file,
-    run_command, run_command_with_env, run_command_with_output, run_command_with_output_and_env,
-    rustc_version_info, split_args, walk_dir,
+    run_command, run_command_with_env, run_command_with_output_and_env, rustc_version_info,
+    split_args, walk_dir,
 };
 
 type Env = HashMap<String, String>;
@@ -485,30 +485,6 @@ fn setup_rustc(env: &mut Env, args: &TestArg) -> Result<PathBuf, String> {
         run_command_with_output_and_env(&[&"git", &"checkout"], rust_dir, Some(env))?;
     }
 
-    let mut patches = Vec::new();
-    walk_dir(
-        "patches/tests",
-        &mut |_| Ok(()),
-        &mut |file_path: &Path| {
-            patches.push(file_path.to_path_buf());
-            Ok(())
-        },
-        false,
-    )?;
-    patches.sort();
-    // TODO: remove duplication with prepare.rs by creating a apply_patch function in the utils
-    // module.
-    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], rust_dir)?;
-        run_command_with_output(&[&"git", &"add", &"-A"], rust_dir)?;
-        run_command_with_output(
-            &[&"git", &"commit", &"--no-gpg-sign", &"-m", &format!("Patch {}", path.display())],
-            rust_dir,
-        )?;
-    }
-
     let cargo = String::from_utf8(
         run_command_with_env(&[&"rustup", &"which", &"cargo"], rust_dir, Some(env))?.stdout,
     )
@@ -738,14 +714,7 @@ fn test_libcore(env: &Env, args: &TestArg) -> Result<(), String> {
     let path = get_sysroot_dir().join("sysroot_src/library/coretests");
     let _ = remove_dir_all(path.join("target"));
     // TODO(antoyo): run in release mode when we fix the failures.
-    // TODO(antoyo): remove the --skip f16::test_total_cmp when this issue is fixed:
-    // https://github.com/rust-lang/rust/issues/141503
-    run_cargo_command(
-        &[&"test", &"--", &"--skip", &"f16::test_total_cmp"],
-        Some(&path),
-        env,
-        args,
-    )?;
+    run_cargo_command(&[&"test"], Some(&path), env, args)?;
     Ok(())
 }
 
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 c3bd62e5897..6b6f71edaf8 100644
--- a/compiler/rustc_codegen_gcc/example/mini_core_hello_world.rs
+++ b/compiler/rustc_codegen_gcc/example/mini_core_hello_world.rs
@@ -6,6 +6,7 @@
 )]
 #![no_core]
 #![allow(dead_code, internal_features, non_camel_case_types)]
+#![rustfmt::skip]
 
 extern crate mini_core;
 
@@ -197,10 +198,10 @@ fn main() {
         assert_eq!(intrinsics::align_of::<u16>() as u8, 2);
         assert_eq!(intrinsics::align_of_val(&a) as u8, intrinsics::align_of::<&str>() as u8);
 
-        assert!(!intrinsics::needs_drop::<u8>());
-        assert!(!intrinsics::needs_drop::<[u8]>());
-        assert!(intrinsics::needs_drop::<NoisyDrop>());
-        assert!(intrinsics::needs_drop::<NoisyDropUnsized>());
+        assert!(!const { intrinsics::needs_drop::<u8>() });
+        assert!(!const { intrinsics::needs_drop::<[u8]>() });
+        assert!(const { intrinsics::needs_drop::<NoisyDrop>() });
+        assert!(const { intrinsics::needs_drop::<NoisyDropUnsized>() });
 
         Unique {
             pointer: 0 as *const &str,
diff --git a/compiler/rustc_codegen_gcc/patches/0001-Pin-compiler_builtins-to-0.1.160.patch b/compiler/rustc_codegen_gcc/patches/0001-Pin-compiler_builtins-to-0.1.160.patch
deleted file mode 100644
index 39266e081ed..00000000000
--- a/compiler/rustc_codegen_gcc/patches/0001-Pin-compiler_builtins-to-0.1.160.patch
+++ /dev/null
@@ -1,39 +0,0 @@
-From cdb3d407740e4f15c3746051f8ba89b8e74e99d3 Mon Sep 17 00:00:00 2001
-From: None <none@example.com>
-Date: Fri, 30 May 2025 13:46:22 -0400
-Subject: [PATCH] Pin compiler_builtins to 0.1.160
-
----
- library/alloc/Cargo.toml | 2 +-
- library/std/Cargo.toml   | 2 +-
- 2 files changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/library/alloc/Cargo.toml b/library/alloc/Cargo.toml
-index 9d0d957..365c9dc 100644
---- a/library/alloc/Cargo.toml
-+++ b/library/alloc/Cargo.toml
-@@ -16,7 +16,7 @@ bench = false
- 
- [dependencies]
- core = { path = "../core", public = true }
--compiler_builtins = { version = "=0.1.159", features = ['rustc-dep-of-std'] }
-+compiler_builtins = { version = "=0.1.160", features = ['rustc-dep-of-std'] }
- 
- [features]
- compiler-builtins-mem = ['compiler_builtins/mem']
-diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml
-index 4ff4895..31371f0 100644
---- a/library/std/Cargo.toml
-+++ b/library/std/Cargo.toml
-@@ -18,7 +18,7 @@ cfg-if = { version = "1.0", features = ['rustc-dep-of-std'] }
- panic_unwind = { path = "../panic_unwind", optional = true }
- panic_abort = { path = "../panic_abort" }
- core = { path = "../core", public = true }
--compiler_builtins = { version = "=0.1.159" }
-+compiler_builtins = { version = "=0.1.160" }
- unwind = { path = "../unwind" }
- hashbrown = { version = "0.15", default-features = false, features = [
-     'rustc-dep-of-std',
--- 
-2.49.0
-
diff --git a/compiler/rustc_codegen_gcc/patches/tests/0001-Workaround-to-make-a-run-make-test-pass.patch b/compiler/rustc_codegen_gcc/patches/tests/0001-Workaround-to-make-a-run-make-test-pass.patch
deleted file mode 100644
index a329d09a95e..00000000000
--- a/compiler/rustc_codegen_gcc/patches/tests/0001-Workaround-to-make-a-run-make-test-pass.patch
+++ /dev/null
@@ -1,25 +0,0 @@
-From a131c69e54b5c02fe3b517e8f3ad23d4f784ffc8 Mon Sep 17 00:00:00 2001
-From: Antoni Boucher <bouanto@zoho.com>
-Date: Fri, 13 Jun 2025 20:25:33 -0400
-Subject: [PATCH] Workaround to make a run-make test pass
-
----
- tests/run-make/linker-warning/rmake.rs | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/tests/run-make/linker-warning/rmake.rs b/tests/run-make/linker-warning/rmake.rs
-index bc21739fefc..0946a7e2a48 100644
---- a/tests/run-make/linker-warning/rmake.rs
-+++ b/tests/run-make/linker-warning/rmake.rs
-@@ -55,7 +55,7 @@ fn main() {
-         diff()
-             .expected_file("short-error.txt")
-             .actual_text("(linker error)", out.stderr())
--            .normalize(r#"/rustc[^/]*/"#, "/rustc/")
-+            .normalize(r#"/tmp/rustc[^/]*/"#, "/tmp/rustc/")
-             .normalize(
-                 regex::escape(run_make_support::build_root().to_str().unwrap()),
-                 "/build-root",
--- 
-2.49.0
-
diff --git a/compiler/rustc_codegen_gcc/rust-toolchain b/compiler/rustc_codegen_gcc/rust-toolchain
index bafe497a2a2..bccbc6cd2c5 100644
--- a/compiler/rustc_codegen_gcc/rust-toolchain
+++ b/compiler/rustc_codegen_gcc/rust-toolchain
@@ -1,3 +1,3 @@
 [toolchain]
-channel = "nightly-2025-05-21"
+channel = "nightly-2025-06-28"
 components = ["rust-src", "rustc-dev", "llvm-tools-preview"]
diff --git a/compiler/rustc_codegen_gcc/src/abi.rs b/compiler/rustc_codegen_gcc/src/abi.rs
index 08f3d281904..0b359f1c5c8 100644
--- a/compiler/rustc_codegen_gcc/src/abi.rs
+++ b/compiler/rustc_codegen_gcc/src/abi.rs
@@ -1,7 +1,9 @@
 #[cfg(feature = "master")]
 use gccjit::FnAttribute;
 use gccjit::{ToLValue, ToRValue, Type};
-use rustc_abi::{ArmCall, CanonAbi, InterruptKind, Reg, RegKind, X86Call};
+#[cfg(feature = "master")]
+use rustc_abi::{ArmCall, CanonAbi, InterruptKind, X86Call};
+use rustc_abi::{Reg, RegKind};
 use rustc_codegen_ssa::traits::{AbiBuilderMethods, BaseTypeCodegenMethods};
 use rustc_data_structures::fx::FxHashSet;
 use rustc_middle::bug;
diff --git a/compiler/rustc_codegen_gcc/src/allocator.rs b/compiler/rustc_codegen_gcc/src/allocator.rs
index cf8aa500c77..0d8dc93274f 100644
--- a/compiler/rustc_codegen_gcc/src/allocator.rs
+++ b/compiler/rustc_codegen_gcc/src/allocator.rs
@@ -1,6 +1,6 @@
-use gccjit::{Context, FunctionType, GlobalKind, ToRValue, Type};
 #[cfg(feature = "master")]
-use gccjit::{FnAttribute, VarAttribute};
+use gccjit::FnAttribute;
+use gccjit::{Context, FunctionType, RValue, ToRValue, Type};
 use rustc_ast::expand::allocator::{
     ALLOCATOR_METHODS, AllocatorKind, AllocatorTy, NO_ALLOC_SHIM_IS_UNSTABLE,
     alloc_error_handler_name, default_fn_name, global_fn_name,
@@ -71,15 +71,13 @@ pub(crate) unsafe fn codegen(
         None,
     );
 
-    let name = mangle_internal_symbol(tcx, OomStrategy::SYMBOL);
-    let global = context.new_global(None, GlobalKind::Exported, i8, name);
-    #[cfg(feature = "master")]
-    global.add_attribute(VarAttribute::Visibility(symbol_visibility_to_gcc(
-        tcx.sess.default_visibility(),
-    )));
-    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);
+    create_const_value_function(
+        tcx,
+        context,
+        &mangle_internal_symbol(tcx, OomStrategy::SYMBOL),
+        i8,
+        context.new_rvalue_from_int(i8, tcx.sess.opts.unstable_opts.oom.should_panic() as i32),
+    );
 
     create_wrapper_function(
         tcx,
@@ -91,6 +89,30 @@ pub(crate) unsafe fn codegen(
     );
 }
 
+fn create_const_value_function(
+    tcx: TyCtxt<'_>,
+    context: &Context<'_>,
+    name: &str,
+    output: Type<'_>,
+    value: RValue<'_>,
+) {
+    let func = context.new_function(None, FunctionType::Exported, output, &[], name, false);
+
+    #[cfg(feature = "master")]
+    func.add_attribute(FnAttribute::Visibility(symbol_visibility_to_gcc(
+        tcx.sess.default_visibility(),
+    )));
+
+    func.add_attribute(FnAttribute::AlwaysInline);
+
+    if tcx.sess.must_emit_unwind_tables() {
+        // TODO(antoyo): emit unwind tables.
+    }
+
+    let block = func.new_block("entry");
+    block.end_with_return(None, value);
+}
+
 fn create_wrapper_function(
     tcx: TyCtxt<'_>,
     context: &Context<'_>,
diff --git a/compiler/rustc_codegen_gcc/src/back/lto.rs b/compiler/rustc_codegen_gcc/src/back/lto.rs
index 10fce860b77..e554dd2500b 100644
--- a/compiler/rustc_codegen_gcc/src/back/lto.rs
+++ b/compiler/rustc_codegen_gcc/src/back/lto.rs
@@ -24,7 +24,7 @@ use std::sync::Arc;
 
 use gccjit::{Context, OutputKind};
 use object::read::archive::ArchiveFile;
-use rustc_codegen_ssa::back::lto::{LtoModuleCodegen, SerializedModule, ThinModule, ThinShared};
+use rustc_codegen_ssa::back::lto::{SerializedModule, ThinModule, ThinShared};
 use rustc_codegen_ssa::back::symbol_export;
 use rustc_codegen_ssa::back::write::{CodegenContext, FatLtoInput};
 use rustc_codegen_ssa::traits::*;
@@ -176,7 +176,7 @@ pub(crate) fn run_fat(
     cgcx: &CodegenContext<GccCodegenBackend>,
     modules: Vec<FatLtoInput<GccCodegenBackend>>,
     cached_modules: Vec<(SerializedModule<ModuleBuffer>, WorkProduct)>,
-) -> Result<LtoModuleCodegen<GccCodegenBackend>, FatalError> {
+) -> Result<ModuleCodegen<GccContext>, FatalError> {
     let dcx = cgcx.create_dcx();
     let dcx = dcx.handle();
     let lto_data = prepare_lto(cgcx, dcx)?;
@@ -201,7 +201,7 @@ fn fat_lto(
     mut serialized_modules: Vec<(SerializedModule<ModuleBuffer>, CString)>,
     tmp_path: TempDir,
     //symbols_below_threshold: &[String],
-) -> Result<LtoModuleCodegen<GccCodegenBackend>, FatalError> {
+) -> Result<ModuleCodegen<GccContext>, FatalError> {
     let _timer = cgcx.prof.generic_activity("GCC_fat_lto_build_monolithic_module");
     info!("going for a fat lto");
 
@@ -334,7 +334,7 @@ fn fat_lto(
     // of now.
     module.module_llvm.temp_dir = Some(tmp_path);
 
-    Ok(LtoModuleCodegen::Fat(module))
+    Ok(module)
 }
 
 pub struct ModuleBuffer(PathBuf);
@@ -358,7 +358,7 @@ pub(crate) fn run_thin(
     cgcx: &CodegenContext<GccCodegenBackend>,
     modules: Vec<(String, ThinBuffer)>,
     cached_modules: Vec<(SerializedModule<ModuleBuffer>, WorkProduct)>,
-) -> Result<(Vec<LtoModuleCodegen<GccCodegenBackend>>, Vec<WorkProduct>), FatalError> {
+) -> Result<(Vec<ThinModule<GccCodegenBackend>>, Vec<WorkProduct>), FatalError> {
     let dcx = cgcx.create_dcx();
     let dcx = dcx.handle();
     let lto_data = prepare_lto(cgcx, dcx)?;
@@ -427,7 +427,7 @@ fn thin_lto(
     tmp_path: TempDir,
     cached_modules: Vec<(SerializedModule<ModuleBuffer>, WorkProduct)>,
     //_symbols_below_threshold: &[String],
-) -> Result<(Vec<LtoModuleCodegen<GccCodegenBackend>>, Vec<WorkProduct>), FatalError> {
+) -> Result<(Vec<ThinModule<GccCodegenBackend>>, Vec<WorkProduct>), FatalError> {
     let _timer = cgcx.prof.generic_activity("LLVM_thin_lto_global_analysis");
     info!("going for that thin, thin LTO");
 
@@ -573,8 +573,7 @@ fn thin_lto(
         }*/
 
         info!(" - {}: re-compiled", module_name);
-        opt_jobs
-            .push(LtoModuleCodegen::Thin(ThinModule { shared: shared.clone(), idx: module_index }));
+        opt_jobs.push(ThinModule { shared: shared.clone(), idx: module_index });
     }
 
     // Save the current ThinLTO import information for the next compilation
diff --git a/compiler/rustc_codegen_gcc/src/back/write.rs b/compiler/rustc_codegen_gcc/src/back/write.rs
index d03d063bdac..113abe70805 100644
--- a/compiler/rustc_codegen_gcc/src/back/write.rs
+++ b/compiler/rustc_codegen_gcc/src/back/write.rs
@@ -16,10 +16,12 @@ use crate::{GccCodegenBackend, GccContext};
 
 pub(crate) fn codegen(
     cgcx: &CodegenContext<GccCodegenBackend>,
-    dcx: DiagCtxtHandle<'_>,
     module: ModuleCodegen<GccContext>,
     config: &ModuleConfig,
 ) -> Result<CompiledModule, FatalError> {
+    let dcx = cgcx.create_dcx();
+    let dcx = dcx.handle();
+
     let _timer = cgcx.prof.generic_activity_with_arg("GCC_module_codegen", &*module.name);
     {
         let context = &module.module_llvm.context;
diff --git a/compiler/rustc_codegen_gcc/src/builder.rs b/compiler/rustc_codegen_gcc/src/builder.rs
index a2e34d1f8fb..28d1ec7d895 100644
--- a/compiler/rustc_codegen_gcc/src/builder.rs
+++ b/compiler/rustc_codegen_gcc/src/builder.rs
@@ -520,8 +520,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
         self.block
     }
 
-    fn append_block(cx: &'a CodegenCx<'gcc, 'tcx>, func: RValue<'gcc>, name: &str) -> Block<'gcc> {
-        let func = cx.rvalue_as_function(func);
+    fn append_block(_: &'a CodegenCx<'gcc, 'tcx>, func: Function<'gcc>, name: &str) -> Block<'gcc> {
         func.new_block(name)
     }
 
@@ -539,11 +538,6 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
     }
 
     fn ret(&mut self, mut value: RValue<'gcc>) {
-        if self.structs_as_pointer.borrow().contains(&value) {
-            // NOTE: hack to workaround a limitation of the rustc API: see comment on
-            // CodegenCx.structs_as_pointer
-            value = value.dereference(self.location).to_rvalue();
-        }
         let expected_return_type = self.current_func().get_return_type();
         if !expected_return_type.is_compatible_with(value.get_type()) {
             // NOTE: due to opaque pointers now being used, we need to cast here.
@@ -701,7 +695,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
         let a = self.gcc_int_cast(a, a_type);
         let b_type = b.get_type().to_unsigned(self);
         let b = self.gcc_int_cast(b, b_type);
-        a / b
+        self.gcc_udiv(a, b)
     }
 
     fn sdiv(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
@@ -713,8 +707,8 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
         // FIXME(antoyo): rustc_codegen_ssa::mir::intrinsic uses different types for a and b but they
         // should be the same.
         let typ = a.get_type().to_signed(self);
-        let b = self.context.new_cast(self.location, b, typ);
-        a / b
+        let b = self.gcc_int_cast(b, typ);
+        self.gcc_sdiv(a, b)
     }
 
     fn fdiv(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
@@ -782,6 +776,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
                 return self.context.new_call(self.location, fmod, &[a, b]);
             }
             TypeKind::FP128 => {
+                // TODO(antoyo): use get_simple_function_f128_2args.
                 let f128_type = self.type_f128();
                 let fmodf128 = self.context.new_function(
                     None,
@@ -931,29 +926,39 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
             .get_address(self.location)
     }
 
-    fn dynamic_alloca(&mut self, _len: RValue<'gcc>, _align: Align) -> RValue<'gcc> {
-        unimplemented!();
-    }
-
     fn load(&mut self, pointee_ty: Type<'gcc>, ptr: RValue<'gcc>, align: Align) -> RValue<'gcc> {
         let block = self.llbb();
         let function = block.get_function();
+        // NOTE(FractalFir): In some cases, we *should* skip the call to get_aligned.
+        // For example, calling `get_aligned` on a i8 is pointless(since it can only be 1 aligned)
+        // Calling get_aligned on a `u128`/`i128` causes the attribute to become "stacked"
+        //
+        // From GCCs perspective:
+        // __int128_t  __attribute__((aligned(16)))  __attribute__((aligned(16)))
+        // and:
+        // __int128_t  __attribute__((aligned(16)))
+        // are 2 distinct, incompatible types.
+        //
+        // So, we skip the call to `get_aligned` in such a case. *Ideally*, we could do this for all the types,
+        // but the GCC APIs to facilitate this just aren't quite there yet.
+
+        // This checks that we only skip `get_aligned` on 128 bit ints if they have the correct alignment.
+        // Otherwise, this may be an under-aligned load, so we will still call get_aligned.
+        let mut can_skip_align = (pointee_ty == self.cx.u128_type
+            || pointee_ty == self.cx.i128_type)
+            && align == self.int128_align;
+        // We can skip the call to `get_aligned` for byte-sized types with alignment of 1.
+        can_skip_align = can_skip_align
+            || (pointee_ty == self.cx.u8_type || pointee_ty == self.cx.i8_type)
+                && align.bytes() == 1;
+        // Skip the call to `get_aligned` when possible.
+        let aligned_type =
+            if can_skip_align { pointee_ty } else { pointee_ty.get_aligned(align.bytes()) };
+
+        let ptr = self.context.new_cast(self.location, ptr, aligned_type.make_pointer());
         // NOTE: instead of returning the dereference here, we have to assign it to a variable in
         // the current basic block. Otherwise, it could be used in another basic block, causing a
         // dereference after a drop, for instance.
-        // FIXME(antoyo): this check that we don't call get_aligned() a second time on a type.
-        // Ideally, we shouldn't need to do this check.
-        // FractalFir: the `align == self.int128_align` check ensures we *do* call `get_aligned` if
-        // the alignment of a `u128`/`i128` is not the one mandated by the ABI. This ensures we handle
-        // under-aligned loads correctly.
-        let aligned_type = if (pointee_ty == self.cx.u128_type || pointee_ty == self.cx.i128_type)
-            && align == self.int128_align
-        {
-            pointee_ty
-        } else {
-            pointee_ty.get_aligned(align.bytes())
-        };
-        let ptr = self.context.new_cast(self.location, ptr, aligned_type.make_pointer());
         let deref = ptr.dereference(self.location).to_rvalue();
         let loaded_value = function.new_local(
             self.location,
@@ -1488,16 +1493,6 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
             element.get_address(self.location)
         } else if value_type.dyncast_vector().is_some() {
             panic!();
-        } else if let Some(pointer_type) = value_type.get_pointee() {
-            if let Some(struct_type) = pointer_type.is_struct() {
-                // NOTE: hack to workaround a limitation of the rustc API: see comment on
-                // CodegenCx.structs_as_pointer
-                aggregate_value
-                    .dereference_field(self.location, struct_type.get_field(idx as i32))
-                    .to_rvalue()
-            } else {
-                panic!("Unexpected type {:?}", value_type);
-            }
         } else if let Some(struct_type) = value_type.is_struct() {
             aggregate_value
                 .access_field(self.location, struct_type.get_field(idx as i32))
@@ -1517,21 +1512,18 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
         assert_eq!(idx as usize as u64, idx);
         let value_type = aggregate_value.get_type();
 
+        let new_val = self.current_func().new_local(None, value_type, "aggregate_value");
+        self.block.add_assignment(None, new_val, aggregate_value);
+
         let lvalue = if value_type.dyncast_array().is_some() {
             let index = self
                 .context
                 .new_rvalue_from_long(self.u64_type, i64::try_from(idx).expect("i64::try_from"));
-            self.context.new_array_access(self.location, aggregate_value, index)
+            self.context.new_array_access(self.location, new_val, index)
         } else if value_type.dyncast_vector().is_some() {
             panic!();
-        } else if let Some(pointer_type) = value_type.get_pointee() {
-            if let Some(struct_type) = pointer_type.is_struct() {
-                // NOTE: hack to workaround a limitation of the rustc API: see comment on
-                // CodegenCx.structs_as_pointer
-                aggregate_value.dereference_field(self.location, struct_type.get_field(idx as i32))
-            } else {
-                panic!("Unexpected type {:?}", value_type);
-            }
+        } else if let Some(struct_type) = value_type.is_struct() {
+            new_val.access_field(None, struct_type.get_field(idx as i32))
         } else {
             panic!("Unexpected type {:?}", value_type);
         };
@@ -1548,19 +1540,16 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
 
         self.llbb().add_assignment(self.location, lvalue, value);
 
-        aggregate_value
+        new_val.to_rvalue()
     }
 
-    fn set_personality_fn(&mut self, _personality: RValue<'gcc>) {
+    fn set_personality_fn(&mut self, _personality: Function<'gcc>) {
         #[cfg(feature = "master")]
-        {
-            let personality = self.rvalue_as_function(_personality);
-            self.current_func().set_personality_function(personality);
-        }
+        self.current_func().set_personality_function(_personality);
     }
 
     #[cfg(feature = "master")]
-    fn cleanup_landing_pad(&mut self, pers_fn: RValue<'gcc>) -> (RValue<'gcc>, RValue<'gcc>) {
+    fn cleanup_landing_pad(&mut self, pers_fn: Function<'gcc>) -> (RValue<'gcc>, RValue<'gcc>) {
         self.set_personality_fn(pers_fn);
 
         // NOTE: insert the current block in a variable so that a later call to invoke knows to
@@ -1581,7 +1570,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
     }
 
     #[cfg(not(feature = "master"))]
-    fn cleanup_landing_pad(&mut self, _pers_fn: RValue<'gcc>) -> (RValue<'gcc>, RValue<'gcc>) {
+    fn cleanup_landing_pad(&mut self, _pers_fn: Function<'gcc>) -> (RValue<'gcc>, RValue<'gcc>) {
         let value1 = self
             .current_func()
             .new_local(self.location, self.u8_type.make_pointer(), "landing_pad0")
@@ -1591,9 +1580,9 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
         (value1, value2)
     }
 
-    fn filter_landing_pad(&mut self, pers_fn: RValue<'gcc>) -> (RValue<'gcc>, RValue<'gcc>) {
+    fn filter_landing_pad(&mut self, pers_fn: Function<'gcc>) {
         // TODO(antoyo): generate the correct landing pad
-        self.cleanup_landing_pad(pers_fn)
+        self.cleanup_landing_pad(pers_fn);
     }
 
     #[cfg(feature = "master")]
diff --git a/compiler/rustc_codegen_gcc/src/common.rs b/compiler/rustc_codegen_gcc/src/common.rs
index 58ff2f1f8f0..28848ca6184 100644
--- a/compiler/rustc_codegen_gcc/src/common.rs
+++ b/compiler/rustc_codegen_gcc/src/common.rs
@@ -1,7 +1,6 @@
 use gccjit::{LValue, RValue, ToRValue, Type};
-use rustc_abi as abi;
-use rustc_abi::HasDataLayout;
 use rustc_abi::Primitive::Pointer;
+use rustc_abi::{self as abi, HasDataLayout};
 use rustc_codegen_ssa::traits::{
     BaseTypeCodegenMethods, ConstCodegenMethods, MiscCodegenMethods, StaticCodegenMethods,
 };
@@ -117,15 +116,7 @@ impl<'gcc, 'tcx> ConstCodegenMethods for CodegenCx<'gcc, 'tcx> {
 
     fn const_undef(&self, typ: Type<'gcc>) -> RValue<'gcc> {
         let local = self.current_func.borrow().expect("func").new_local(None, typ, "undefined");
-        if typ.is_struct().is_some() {
-            // NOTE: hack to workaround a limitation of the rustc API: see comment on
-            // CodegenCx.structs_as_pointer
-            let pointer = local.get_address(None);
-            self.structs_as_pointer.borrow_mut().insert(pointer);
-            pointer
-        } else {
-            local.to_rvalue()
-        }
+        local.to_rvalue()
     }
 
     fn const_poison(&self, typ: Type<'gcc>) -> RValue<'gcc> {
@@ -170,7 +161,7 @@ impl<'gcc, 'tcx> ConstCodegenMethods for CodegenCx<'gcc, 'tcx> {
     }
 
     fn const_usize(&self, i: u64) -> RValue<'gcc> {
-        let bit_size = self.data_layout().pointer_size.bits();
+        let bit_size = self.data_layout().pointer_size().bits();
         if bit_size < 64 {
             // make sure it doesn't overflow
             assert!(i < (1 << bit_size));
@@ -234,19 +225,6 @@ impl<'gcc, 'tcx> ConstCodegenMethods for CodegenCx<'gcc, 'tcx> {
         match cv {
             Scalar::Int(int) => {
                 let data = int.to_bits(layout.size(self));
-
-                // FIXME(antoyo): there's some issues with using the u128 code that follows, so hard-code
-                // the paths for floating-point values.
-                // TODO: Remove this code?
-                /*if ty == self.float_type {
-                    return self
-                        .context
-                        .new_rvalue_from_double(ty, f32::from_bits(data as u32) as f64);
-                }
-                if ty == self.double_type {
-                    return self.context.new_rvalue_from_double(ty, f64::from_bits(data as u64));
-                }*/
-
                 let value = self.const_uint_big(self.type_ix(bitsize), data);
                 let bytesize = layout.size(self).bytes();
                 if bitsize > 1 && ty.is_integral() && bytesize as u32 == ty.get_size() {
@@ -261,7 +239,7 @@ impl<'gcc, 'tcx> ConstCodegenMethods for CodegenCx<'gcc, 'tcx> {
                 }
             }
             Scalar::Ptr(ptr, _size) => {
-                let (prov, offset) = ptr.into_parts(); // we know the `offset` is relative
+                let (prov, offset) = ptr.prov_and_relative_offset();
                 let alloc_id = prov.alloc_id();
                 let base_addr = match self.tcx.global_alloc(alloc_id) {
                     GlobalAlloc::Memory(alloc) => {
@@ -303,6 +281,13 @@ impl<'gcc, 'tcx> ConstCodegenMethods for CodegenCx<'gcc, 'tcx> {
                         let init = self.const_data_from_alloc(alloc);
                         self.static_addr_of(init, alloc.inner().align, None)
                     }
+                    GlobalAlloc::TypeId { .. } => {
+                        let val = self.const_usize(offset.bytes());
+                        // This is still a variable of pointer type, even though we only use the provenance
+                        // of that pointer in CTFE and Miri. But to make LLVM's type system happy,
+                        // we need an int-to-ptr cast here (it doesn't matter at all which provenance that picks).
+                        return self.context.new_cast(None, val, ty);
+                    }
                     GlobalAlloc::Static(def_id) => {
                         assert!(self.tcx.is_static(def_id));
                         self.get_static(def_id).get_address(None)
diff --git a/compiler/rustc_codegen_gcc/src/consts.rs b/compiler/rustc_codegen_gcc/src/consts.rs
index b43f9b24c6a..c04c75e1b11 100644
--- a/compiler/rustc_codegen_gcc/src/consts.rs
+++ b/compiler/rustc_codegen_gcc/src/consts.rs
@@ -294,7 +294,7 @@ pub(crate) fn const_alloc_to_gcc_uncached<'gcc>(
     let alloc = alloc.inner();
     let mut llvals = Vec::with_capacity(alloc.provenance().ptrs().len() + 1);
     let dl = cx.data_layout();
-    let pointer_size = dl.pointer_size.bytes() as usize;
+    let pointer_size = dl.pointer_size().bytes() as usize;
 
     let mut next_offset = 0;
     for &(offset, prov) in alloc.provenance().ptrs().iter() {
@@ -331,7 +331,7 @@ pub(crate) fn const_alloc_to_gcc_uncached<'gcc>(
             ),
             abi::Scalar::Initialized {
                 value: Primitive::Pointer(address_space),
-                valid_range: WrappingRange::full(dl.pointer_size),
+                valid_range: WrappingRange::full(dl.pointer_size()),
             },
             cx.type_i8p_ext(address_space),
         ));
diff --git a/compiler/rustc_codegen_gcc/src/context.rs b/compiler/rustc_codegen_gcc/src/context.rs
index ff141ad365b..665cf22ddba 100644
--- a/compiler/rustc_codegen_gcc/src/context.rs
+++ b/compiler/rustc_codegen_gcc/src/context.rs
@@ -118,19 +118,12 @@ pub struct CodegenCx<'gcc, 'tcx> {
     /// A counter that is used for generating local symbol names
     local_gen_sym_counter: Cell<usize>,
 
-    eh_personality: Cell<Option<RValue<'gcc>>>,
+    eh_personality: Cell<Option<Function<'gcc>>>,
     #[cfg(feature = "master")]
     pub rust_try_fn: Cell<Option<(Type<'gcc>, Function<'gcc>)>>,
 
     pub pointee_infos: RefCell<FxHashMap<(Ty<'tcx>, Size), Option<PointeeInfo>>>,
 
-    /// NOTE: a hack is used because the rustc API is not suitable to libgccjit and as such,
-    /// `const_undef()` returns struct as pointer so that they can later be assigned a value.
-    /// As such, this set remembers which of these pointers were returned by this function so that
-    /// they can be dereferenced later.
-    /// FIXME(antoyo): fix the rustc API to avoid having this hack.
-    pub structs_as_pointer: RefCell<FxHashSet<RValue<'gcc>>>,
-
     #[cfg(feature = "master")]
     pub cleanup_blocks: RefCell<FxHashSet<Block<'gcc>>>,
     /// The alignment of a u128/i128 type.
@@ -155,6 +148,13 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
                 .layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(rust_type))
                 .unwrap();
             let align = layout.align.abi.bytes();
+            // For types with size 1, the alignment can be 1 and only 1
+            // So, we can skip the call to ``get_aligned`.
+            // In the future, we can add a GCC API to query the type align,
+            // and call `get_aligned` if and only if that differs from Rust's expectations.
+            if layout.size.bytes() == 1 {
+                return context.new_c_type(ctype);
+            }
             #[cfg(feature = "master")]
             {
                 context.new_c_type(ctype).get_aligned(align)
@@ -296,7 +296,6 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
             #[cfg(feature = "master")]
             rust_try_fn: Cell::new(None),
             pointee_infos: Default::default(),
-            structs_as_pointer: Default::default(),
             #[cfg(feature = "master")]
             cleanup_blocks: Default::default(),
         };
@@ -373,8 +372,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
 impl<'gcc, 'tcx> BackendTypes for CodegenCx<'gcc, 'tcx> {
     type Value = RValue<'gcc>;
     type Metadata = RValue<'gcc>;
-    // TODO(antoyo): change to Function<'gcc>.
-    type Function = RValue<'gcc>;
+    type Function = Function<'gcc>;
 
     type BasicBlock = Block<'gcc>;
     type Type = Type<'gcc>;
@@ -392,11 +390,10 @@ impl<'gcc, 'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
         &self.vtables
     }
 
-    fn get_fn(&self, instance: Instance<'tcx>) -> RValue<'gcc> {
+    fn get_fn(&self, instance: Instance<'tcx>) -> Function<'gcc> {
         let func = get_fn(self, instance);
         *self.current_func.borrow_mut() = Some(func);
-        // FIXME(antoyo): this is a wrong cast. That requires changing the compiler API.
-        unsafe { std::mem::transmute(func) }
+        func
     }
 
     fn get_fn_addr(&self, instance: Instance<'tcx>) -> RValue<'gcc> {
@@ -420,7 +417,7 @@ impl<'gcc, 'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
         ptr
     }
 
-    fn eh_personality(&self) -> RValue<'gcc> {
+    fn eh_personality(&self) -> Function<'gcc> {
         // The exception handling personality function.
         //
         // If our compilation unit has the `eh_personality` lang item somewhere
@@ -458,9 +455,7 @@ impl<'gcc, 'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
                 let symbol_name = tcx.symbol_name(instance).name;
                 let fn_abi = self.fn_abi_of_instance(instance, ty::List::empty());
                 self.linkage.set(FunctionType::Extern);
-                let func = self.declare_fn(symbol_name, fn_abi);
-                let func: RValue<'gcc> = unsafe { std::mem::transmute(func) };
-                func
+                self.declare_fn(symbol_name, fn_abi)
             }
             _ => {
                 let name = if wants_msvc_seh(self.sess()) {
@@ -468,8 +463,7 @@ impl<'gcc, 'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
                 } else {
                     "rust_eh_personality"
                 };
-                let func = self.declare_func(name, self.type_i32(), &[], true);
-                unsafe { std::mem::transmute::<Function<'gcc>, RValue<'gcc>>(func) }
+                self.declare_func(name, self.type_i32(), &[], true)
             }
         };
         // TODO(antoyo): apply target cpu attributes.
@@ -481,11 +475,11 @@ impl<'gcc, 'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
         self.tcx.sess
     }
 
-    fn set_frame_pointer_type(&self, _llfn: RValue<'gcc>) {
+    fn set_frame_pointer_type(&self, _llfn: Function<'gcc>) {
         // TODO(antoyo)
     }
 
-    fn apply_target_cpu_attr(&self, _llfn: RValue<'gcc>) {
+    fn apply_target_cpu_attr(&self, _llfn: Function<'gcc>) {
         // TODO(antoyo)
     }
 
diff --git a/compiler/rustc_codegen_gcc/src/debuginfo.rs b/compiler/rustc_codegen_gcc/src/debuginfo.rs
index 3a265fbc64f..4c8585192a1 100644
--- a/compiler/rustc_codegen_gcc/src/debuginfo.rs
+++ b/compiler/rustc_codegen_gcc/src/debuginfo.rs
@@ -1,7 +1,7 @@
 use std::ops::Range;
 use std::sync::Arc;
 
-use gccjit::{Location, RValue};
+use gccjit::{Function, Location, RValue};
 use rustc_abi::Size;
 use rustc_codegen_ssa::mir::debuginfo::{DebugScope, FunctionDebugContext, VariableKind};
 use rustc_codegen_ssa::traits::{DebugInfoBuilderMethods, DebugInfoCodegenMethods};
@@ -221,7 +221,7 @@ impl<'gcc, 'tcx> DebugInfoCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
         &self,
         instance: Instance<'tcx>,
         fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
-        llfn: RValue<'gcc>,
+        llfn: Function<'gcc>,
         mir: &mir::Body<'tcx>,
     ) -> Option<FunctionDebugContext<'tcx, Self::DIScope, Self::DILocation>> {
         if self.sess().opts.debuginfo == DebugInfo::None {
@@ -272,7 +272,7 @@ impl<'gcc, 'tcx> DebugInfoCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
         &self,
         _instance: Instance<'tcx>,
         _fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
-        _maybe_definition_llfn: Option<RValue<'gcc>>,
+        _maybe_definition_llfn: Option<Function<'gcc>>,
     ) -> Self::DIScope {
         // TODO(antoyo): implement.
     }
diff --git a/compiler/rustc_codegen_gcc/src/declare.rs b/compiler/rustc_codegen_gcc/src/declare.rs
index bed82073e2c..691fd8729e3 100644
--- a/compiler/rustc_codegen_gcc/src/declare.rs
+++ b/compiler/rustc_codegen_gcc/src/declare.rs
@@ -94,7 +94,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
         _fn_type: Type<'gcc>,
         #[cfg(feature = "master")] callconv: Option<FnAttribute<'gcc>>,
         #[cfg(not(feature = "master"))] callconv: Option<()>,
-    ) -> RValue<'gcc> {
+    ) -> Function<'gcc> {
         // TODO(antoyo): use the fn_type parameter.
         let const_string = self.context.new_type::<u8>().make_pointer().make_pointer();
         let return_type = self.type_i32();
@@ -111,8 +111,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
         // NOTE: it is needed to set the current_func here as well, because get_fn() is not called
         // for the main function.
         *self.current_func.borrow_mut() = Some(func);
-        // FIXME(antoyo): this is a wrong cast. That requires changing the compiler API.
-        unsafe { std::mem::transmute(func) }
+        func
     }
 
     pub fn declare_fn(&self, name: &str, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> Function<'gcc> {
diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/archs.rs b/compiler/rustc_codegen_gcc/src/intrinsic/archs.rs
index f0352c5e6e5..915ed875e32 100644
--- a/compiler/rustc_codegen_gcc/src/intrinsic/archs.rs
+++ b/compiler/rustc_codegen_gcc/src/intrinsic/archs.rs
@@ -1,9 +1,9 @@
 // File generated by `rustc_codegen_gcc/tools/generate_intrinsics.py`
 // DO NOT EDIT IT!
 /// Translate a given LLVM intrinsic name to an equivalent GCC one.
-fn map_arch_intrinsic(name: &str) -> &str {
-    let Some(name) = name.strip_prefix("llvm.") else {
-        unimplemented!("***** unsupported LLVM intrinsic {}", name)
+fn map_arch_intrinsic(full_name: &str) -> &'static str {
+    let Some(name) = full_name.strip_prefix("llvm.") else {
+        unimplemented!("***** unsupported LLVM intrinsic {}", full_name)
     };
     let Some((arch, name)) = name.split_once('.') else {
         unimplemented!("***** unsupported LLVM intrinsic {}", name)
@@ -11,7 +11,7 @@ fn map_arch_intrinsic(name: &str) -> &str {
     match arch {
         "AMDGPU" => {
             #[allow(non_snake_case)]
-            fn AMDGPU(name: &str) -> &str {
+            fn AMDGPU(name: &str, full_name: &str) -> &'static str {
                 match name {
                     // AMDGPU
                     "div.fixup.f32" => "__builtin_amdgpu_div_fixup",
@@ -42,14 +42,14 @@ fn map_arch_intrinsic(name: &str) -> &str {
                     "trig.preop.f64" => "__builtin_amdgpu_trig_preop",
                     "trig.preop.v2f64" => "__builtin_amdgpu_trig_preop",
                     "trig.preop.v4f32" => "__builtin_amdgpu_trig_preop",
-                    _ => unimplemented!("***** unsupported LLVM intrinsic {}", name),
+                    _ => unimplemented!("***** unsupported LLVM intrinsic {full_name}"),
                 }
             }
-            AMDGPU(name)
+            AMDGPU(name, full_name)
         }
         "aarch64" => {
             #[allow(non_snake_case)]
-            fn aarch64(name: &str) -> &str {
+            fn aarch64(name: &str, full_name: &str) -> &'static str {
                 match name {
                     // aarch64
                     "chkfeat" => "__builtin_arm_chkfeat",
@@ -75,14 +75,14 @@ fn map_arch_intrinsic(name: &str) -> &str {
                     "tcommit" => "__builtin_arm_tcommit",
                     "tstart" => "__builtin_arm_tstart",
                     "ttest" => "__builtin_arm_ttest",
-                    _ => unimplemented!("***** unsupported LLVM intrinsic {}", name),
+                    _ => unimplemented!("***** unsupported LLVM intrinsic {full_name}"),
                 }
             }
-            aarch64(name)
+            aarch64(name, full_name)
         }
         "amdgcn" => {
             #[allow(non_snake_case)]
-            fn amdgcn(name: &str) -> &str {
+            fn amdgcn(name: &str, full_name: &str) -> &'static str {
                 match name {
                     // amdgcn
                     "alignbyte" => "__builtin_amdgcn_alignbyte",
@@ -99,6 +99,8 @@ fn map_arch_intrinsic(name: &str) -> &str {
                     "cvt.f32.fp8" => "__builtin_amdgcn_cvt_f32_fp8",
                     "cvt.off.f32.i4" => "__builtin_amdgcn_cvt_off_f32_i4",
                     "cvt.pk.bf8.f32" => "__builtin_amdgcn_cvt_pk_bf8_f32",
+                    "cvt.pk.f16.bf8" => "__builtin_amdgcn_cvt_pk_f16_bf8",
+                    "cvt.pk.f16.fp8" => "__builtin_amdgcn_cvt_pk_f16_fp8",
                     "cvt.pk.f32.bf8" => "__builtin_amdgcn_cvt_pk_f32_bf8",
                     "cvt.pk.f32.fp8" => "__builtin_amdgcn_cvt_pk_f32_fp8",
                     "cvt.pk.fp8.f32" => "__builtin_amdgcn_cvt_pk_fp8_f32",
@@ -292,6 +294,7 @@ fn map_arch_intrinsic(name: &str) -> &str {
                     "s.sendmsg" => "__builtin_amdgcn_s_sendmsg",
                     "s.sendmsghalt" => "__builtin_amdgcn_s_sendmsghalt",
                     "s.setprio" => "__builtin_amdgcn_s_setprio",
+                    "s.setprio.inc.wg" => "__builtin_amdgcn_s_setprio_inc_wg",
                     "s.setreg" => "__builtin_amdgcn_s_setreg",
                     "s.sleep" => "__builtin_amdgcn_s_sleep",
                     "s.sleep.var" => "__builtin_amdgcn_s_sleep_var",
@@ -356,14 +359,14 @@ fn map_arch_intrinsic(name: &str) -> &str {
                     "workitem.id.x" => "__builtin_amdgcn_workitem_id_x",
                     "workitem.id.y" => "__builtin_amdgcn_workitem_id_y",
                     "workitem.id.z" => "__builtin_amdgcn_workitem_id_z",
-                    _ => unimplemented!("***** unsupported LLVM intrinsic {}", name),
+                    _ => unimplemented!("***** unsupported LLVM intrinsic {full_name}"),
                 }
             }
-            amdgcn(name)
+            amdgcn(name, full_name)
         }
         "arm" => {
             #[allow(non_snake_case)]
-            fn arm(name: &str) -> &str {
+            fn arm(name: &str, full_name: &str) -> &'static str {
                 match name {
                     // arm
                     "cdp" => "__builtin_arm_cdp",
@@ -465,14 +468,14 @@ fn map_arch_intrinsic(name: &str) -> &str {
                     "usub8" => "__builtin_arm_usub8",
                     "uxtab16" => "__builtin_arm_uxtab16",
                     "uxtb16" => "__builtin_arm_uxtb16",
-                    _ => unimplemented!("***** unsupported LLVM intrinsic {}", name),
+                    _ => unimplemented!("***** unsupported LLVM intrinsic {full_name}"),
                 }
             }
-            arm(name)
+            arm(name, full_name)
         }
         "bpf" => {
             #[allow(non_snake_case)]
-            fn bpf(name: &str) -> &str {
+            fn bpf(name: &str, full_name: &str) -> &'static str {
                 match name {
                     // bpf
                     "btf.type.id" => "__builtin_bpf_btf_type_id",
@@ -487,25 +490,25 @@ fn map_arch_intrinsic(name: &str) -> &str {
                     "preserve.field.info" => "__builtin_bpf_preserve_field_info",
                     "preserve.type.info" => "__builtin_bpf_preserve_type_info",
                     "pseudo" => "__builtin_bpf_pseudo",
-                    _ => unimplemented!("***** unsupported LLVM intrinsic {}", name),
+                    _ => unimplemented!("***** unsupported LLVM intrinsic {full_name}"),
                 }
             }
-            bpf(name)
+            bpf(name, full_name)
         }
         "cuda" => {
             #[allow(non_snake_case)]
-            fn cuda(name: &str) -> &str {
+            fn cuda(name: &str, full_name: &str) -> &'static str {
                 match name {
                     // cuda
                     "syncthreads" => "__syncthreads",
-                    _ => unimplemented!("***** unsupported LLVM intrinsic {}", name),
+                    _ => unimplemented!("***** unsupported LLVM intrinsic {full_name}"),
                 }
             }
-            cuda(name)
+            cuda(name, full_name)
         }
         "hexagon" => {
             #[allow(non_snake_case)]
-            fn hexagon(name: &str) -> &str {
+            fn hexagon(name: &str, full_name: &str) -> &'static str {
                 match name {
                     // hexagon
                     "A2.abs" => "__builtin_HEXAGON_A2_abs",
@@ -2479,14 +2482,14 @@ fn map_arch_intrinsic(name: &str) -> &str {
                     "prefetch" => "__builtin_HEXAGON_prefetch",
                     "vmemcpy" => "__builtin_hexagon_vmemcpy",
                     "vmemset" => "__builtin_hexagon_vmemset",
-                    _ => unimplemented!("***** unsupported LLVM intrinsic {}", name),
+                    _ => unimplemented!("***** unsupported LLVM intrinsic {full_name}"),
                 }
             }
-            hexagon(name)
+            hexagon(name, full_name)
         }
         "loongarch" => {
             #[allow(non_snake_case)]
-            fn loongarch(name: &str) -> &str {
+            fn loongarch(name: &str, full_name: &str) -> &'static str {
                 match name {
                     // loongarch
                     "asrtgt.d" => "__builtin_loongarch_asrtgt_d",
@@ -3988,14 +3991,14 @@ fn map_arch_intrinsic(name: &str) -> &str {
                     "movfcsr2gr" => "__builtin_loongarch_movfcsr2gr",
                     "movgr2fcsr" => "__builtin_loongarch_movgr2fcsr",
                     "syscall" => "__builtin_loongarch_syscall",
-                    _ => unimplemented!("***** unsupported LLVM intrinsic {}", name),
+                    _ => unimplemented!("***** unsupported LLVM intrinsic {full_name}"),
                 }
             }
-            loongarch(name)
+            loongarch(name, full_name)
         }
         "mips" => {
             #[allow(non_snake_case)]
-            fn mips(name: &str) -> &str {
+            fn mips(name: &str, full_name: &str) -> &'static str {
                 match name {
                     // mips
                     "absq.s.ph" => "__builtin_mips_absq_s_ph",
@@ -4669,14 +4672,14 @@ fn map_arch_intrinsic(name: &str) -> &str {
                     "wrdsp" => "__builtin_mips_wrdsp",
                     "xor.v" => "__builtin_msa_xor_v",
                     "xori.b" => "__builtin_msa_xori_b",
-                    _ => unimplemented!("***** unsupported LLVM intrinsic {}", name),
+                    _ => unimplemented!("***** unsupported LLVM intrinsic {full_name}"),
                 }
             }
-            mips(name)
+            mips(name, full_name)
         }
         "nvvm" => {
             #[allow(non_snake_case)]
-            fn nvvm(name: &str) -> &str {
+            fn nvvm(name: &str, full_name: &str) -> &'static str {
                 match name {
                     // nvvm
                     "abs.i" => "__nvvm_abs_i",
@@ -5024,6 +5027,7 @@ fn map_arch_intrinsic(name: &str) -> &str {
                     "nanosleep" => "__nvvm_nanosleep",
                     "neg.bf16" => "__nvvm_neg_bf16",
                     "neg.bf16x2" => "__nvvm_neg_bf16x2",
+                    "pm.event.mask" => "__nvvm_pm_event_mask",
                     "popc.i" => "__nvvm_popc_i",
                     "popc.ll" => "__nvvm_popc_ll",
                     "prmt" => "__nvvm_prmt",
@@ -5448,14 +5452,14 @@ fn map_arch_intrinsic(name: &str) -> &str {
                     "vote.ballot.sync" => "__nvvm_vote_ballot_sync",
                     "vote.uni" => "__nvvm_vote_uni",
                     "vote.uni.sync" => "__nvvm_vote_uni_sync",
-                    _ => unimplemented!("***** unsupported LLVM intrinsic {}", name),
+                    _ => unimplemented!("***** unsupported LLVM intrinsic {full_name}"),
                 }
             }
-            nvvm(name)
+            nvvm(name, full_name)
         }
         "ppc" => {
             #[allow(non_snake_case)]
-            fn ppc(name: &str) -> &str {
+            fn ppc(name: &str, full_name: &str) -> &'static str {
                 match name {
                     // ppc
                     "addex" => "__builtin_ppc_addex",
@@ -5842,7 +5846,10 @@ fn map_arch_intrinsic(name: &str) -> &str {
                     "mulhdu" => "__builtin_ppc_mulhdu",
                     "mulhw" => "__builtin_ppc_mulhw",
                     "mulhwu" => "__builtin_ppc_mulhwu",
+                    "national2packed" => "__builtin_ppc_national2packed",
                     "pack.longdouble" => "__builtin_pack_longdouble",
+                    "packed2national" => "__builtin_ppc_packed2national",
+                    "packed2zoned" => "__builtin_ppc_packed2zoned",
                     "pdepd" => "__builtin_pdepd",
                     "pextd" => "__builtin_pextd",
                     "qpx.qvfabs" => "__builtin_qpx_qvfabs",
@@ -6035,14 +6042,15 @@ fn map_arch_intrinsic(name: &str) -> &str {
                     "vsx.xxinsertw" => "__builtin_vsx_xxinsertw",
                     "vsx.xxleqv" => "__builtin_vsx_xxleqv",
                     "vsx.xxpermx" => "__builtin_vsx_xxpermx",
-                    _ => unimplemented!("***** unsupported LLVM intrinsic {}", name),
+                    "zoned2packed" => "__builtin_ppc_zoned2packed",
+                    _ => unimplemented!("***** unsupported LLVM intrinsic {full_name}"),
                 }
             }
-            ppc(name)
+            ppc(name, full_name)
         }
         "ptx" => {
             #[allow(non_snake_case)]
-            fn ptx(name: &str) -> &str {
+            fn ptx(name: &str, full_name: &str) -> &'static str {
                 match name {
                     // ptx
                     "bar.sync" => "__builtin_ptx_bar_sync",
@@ -6063,14 +6071,14 @@ fn map_arch_intrinsic(name: &str) -> &str {
                     "read.pm3" => "__builtin_ptx_read_pm3",
                     "read.smid" => "__builtin_ptx_read_smid",
                     "read.warpid" => "__builtin_ptx_read_warpid",
-                    _ => unimplemented!("***** unsupported LLVM intrinsic {}", name),
+                    _ => unimplemented!("***** unsupported LLVM intrinsic {full_name}"),
                 }
             }
-            ptx(name)
+            ptx(name, full_name)
         }
         "r600" => {
             #[allow(non_snake_case)]
-            fn r600(name: &str) -> &str {
+            fn r600(name: &str, full_name: &str) -> &'static str {
                 match name {
                     // r600
                     "group.barrier" => "__builtin_r600_group_barrier",
@@ -6088,14 +6096,14 @@ fn map_arch_intrinsic(name: &str) -> &str {
                     "read.tidig.x" => "__builtin_r600_read_tidig_x",
                     "read.tidig.y" => "__builtin_r600_read_tidig_y",
                     "read.tidig.z" => "__builtin_r600_read_tidig_z",
-                    _ => unimplemented!("***** unsupported LLVM intrinsic {}", name),
+                    _ => unimplemented!("***** unsupported LLVM intrinsic {full_name}"),
                 }
             }
-            r600(name)
+            r600(name, full_name)
         }
         "riscv" => {
             #[allow(non_snake_case)]
-            fn riscv(name: &str) -> &str {
+            fn riscv(name: &str, full_name: &str) -> &'static str {
                 match name {
                     // riscv
                     "aes32dsi" => "__builtin_riscv_aes32dsi",
@@ -6119,14 +6127,14 @@ fn map_arch_intrinsic(name: &str) -> &str {
                     "sha512sum0r" => "__builtin_riscv_sha512sum0r",
                     "sha512sum1" => "__builtin_riscv_sha512sum1",
                     "sha512sum1r" => "__builtin_riscv_sha512sum1r",
-                    _ => unimplemented!("***** unsupported LLVM intrinsic {}", name),
+                    _ => unimplemented!("***** unsupported LLVM intrinsic {full_name}"),
                 }
             }
-            riscv(name)
+            riscv(name, full_name)
         }
         "s390" => {
             #[allow(non_snake_case)]
-            fn s390(name: &str) -> &str {
+            fn s390(name: &str, full_name: &str) -> &'static str {
                 match name {
                     // s390
                     "bdepg" => "__builtin_s390_bdepg",
@@ -6313,14 +6321,14 @@ fn map_arch_intrinsic(name: &str) -> &str {
                     "vupllf" => "__builtin_s390_vupllf",
                     "vupllg" => "__builtin_s390_vupllg",
                     "vupllh" => "__builtin_s390_vupllh",
-                    _ => unimplemented!("***** unsupported LLVM intrinsic {}", name),
+                    _ => unimplemented!("***** unsupported LLVM intrinsic {full_name}"),
                 }
             }
-            s390(name)
+            s390(name, full_name)
         }
         "ve" => {
             #[allow(non_snake_case)]
-            fn ve(name: &str) -> &str {
+            fn ve(name: &str, full_name: &str) -> &'static str {
                 match name {
                     // ve
                     "vl.andm.MMM" => "__builtin_ve_vl_andm_MMM",
@@ -7586,14 +7594,14 @@ fn map_arch_intrinsic(name: &str) -> &str {
                     "vl.vxor.vvvvl" => "__builtin_ve_vl_vxor_vvvvl",
                     "vl.xorm.MMM" => "__builtin_ve_vl_xorm_MMM",
                     "vl.xorm.mmm" => "__builtin_ve_vl_xorm_mmm",
-                    _ => unimplemented!("***** unsupported LLVM intrinsic {}", name),
+                    _ => unimplemented!("***** unsupported LLVM intrinsic {full_name}"),
                 }
             }
-            ve(name)
+            ve(name, full_name)
         }
         "x86" => {
             #[allow(non_snake_case)]
-            fn x86(name: &str) -> &str {
+            fn x86(name: &str, full_name: &str) -> &'static str {
                 match name {
                     // x86
                     "aadd32" => "__builtin_ia32_aadd32",
@@ -10154,25 +10162,25 @@ fn map_arch_intrinsic(name: &str) -> &str {
                     "xresldtrk" => "__builtin_ia32_xresldtrk",
                     "xsusldtrk" => "__builtin_ia32_xsusldtrk",
                     "xtest" => "__builtin_ia32_xtest",
-                    _ => unimplemented!("***** unsupported LLVM intrinsic {}", name),
+                    _ => unimplemented!("***** unsupported LLVM intrinsic {full_name}"),
                 }
             }
-            x86(name)
+            x86(name, full_name)
         }
         "xcore" => {
             #[allow(non_snake_case)]
-            fn xcore(name: &str) -> &str {
+            fn xcore(name: &str, full_name: &str) -> &'static str {
                 match name {
                     // xcore
                     "bitrev" => "__builtin_bitrev",
                     "getid" => "__builtin_getid",
                     "getps" => "__builtin_getps",
                     "setps" => "__builtin_setps",
-                    _ => unimplemented!("***** unsupported LLVM intrinsic {}", name),
+                    _ => unimplemented!("***** unsupported LLVM intrinsic {full_name}"),
                 }
             }
-            xcore(name)
+            xcore(name, full_name)
         }
-        _ => unimplemented!("***** unsupported LLVM intrinsic {}", name),
+        _ => unimplemented!("***** unsupported LLVM architecture {arch}, intrinsic:{full_name}"),
     }
 }
diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/llvm.rs b/compiler/rustc_codegen_gcc/src/intrinsic/llvm.rs
index 0b77694f115..39dba28b24c 100644
--- a/compiler/rustc_codegen_gcc/src/intrinsic/llvm.rs
+++ b/compiler/rustc_codegen_gcc/src/intrinsic/llvm.rs
@@ -648,6 +648,11 @@ pub fn adjust_intrinsic_arguments<'a, 'b, 'gcc, 'tcx>(
                 new_args.push(handle);
                 args = new_args.into();
             }
+            "__builtin_ia32_rdtscp" => {
+                let result = builder.current_func().new_local(None, builder.u32_type, "result");
+                let new_args = vec![result.get_address(None).to_rvalue()];
+                args = new_args.into();
+            }
             _ => (),
         }
     } else {
@@ -764,6 +769,14 @@ pub fn adjust_intrinsic_arguments<'a, 'b, 'gcc, 'tcx>(
                 new_args.swap(0, 1);
                 args = new_args.into();
             }
+            "__builtin_ia32_dpps256" => {
+                let mut new_args = args.to_vec();
+                // NOTE: without this cast to u8 (and it needs to be a u8 to fix the issue), we
+                // would get the following error:
+                // the last argument must be an 8-bit immediate
+                new_args[2] = builder.context.new_cast(None, new_args[2], builder.cx.type_u8());
+                args = new_args.into();
+            }
             _ => (),
         }
     }
@@ -935,6 +948,19 @@ pub fn adjust_intrinsic_return_value<'a, 'gcc, 'tcx>(
             );
             return_value = result.to_rvalue();
         }
+        "__builtin_ia32_rdtscp" => {
+            let field1 = builder.context.new_field(None, return_value.get_type(), "rdtscpField1");
+            let return2 = args[0].dereference(None).to_rvalue();
+            let field2 = builder.context.new_field(None, return2.get_type(), "rdtscpField2");
+            let struct_type =
+                builder.context.new_struct_type(None, "rdtscpResult", &[field1, field2]);
+            return_value = builder.context.new_struct_constructor(
+                None,
+                struct_type.as_type(),
+                None,
+                &[return_value, return2],
+            );
+        }
         _ => (),
     }
 
@@ -1529,6 +1555,17 @@ pub fn intrinsic<'gcc, 'tcx>(name: &str, cx: &CodegenCx<'gcc, 'tcx>) -> Function
         "llvm.x86.aesdecwide128kl" => "__builtin_ia32_aesdecwide128kl_u8",
         "llvm.x86.aesencwide256kl" => "__builtin_ia32_aesencwide256kl_u8",
         "llvm.x86.aesdecwide256kl" => "__builtin_ia32_aesdecwide256kl_u8",
+        "llvm.x86.avx512.uitofp.round.v8f16.v8i16" => "__builtin_ia32_vcvtuw2ph128_mask",
+        "llvm.x86.avx512.uitofp.round.v16f16.v16i16" => "__builtin_ia32_vcvtuw2ph256_mask",
+        "llvm.x86.avx512.uitofp.round.v32f16.v32i16" => "__builtin_ia32_vcvtuw2ph512_mask_round",
+        "llvm.x86.avx512.uitofp.round.v8f16.v8i32" => "__builtin_ia32_vcvtudq2ph256_mask",
+        "llvm.x86.avx512.uitofp.round.v16f16.v16i32" => "__builtin_ia32_vcvtudq2ph512_mask_round",
+        "llvm.x86.avx512.uitofp.round.v8f16.v8i64" => "__builtin_ia32_vcvtuqq2ph512_mask_round",
+        "llvm.x86.avx512.uitofp.round.v8f64.v8i64" => "__builtin_ia32_cvtuqq2pd512_mask",
+        "llvm.x86.avx512.uitofp.round.v2f64.v2i64" => "__builtin_ia32_cvtuqq2pd128_mask",
+        "llvm.x86.avx512.uitofp.round.v4f64.v4i64" => "__builtin_ia32_cvtuqq2pd256_mask",
+        "llvm.x86.avx512.uitofp.round.v8f32.v8i64" => "__builtin_ia32_cvtuqq2ps512_mask",
+        "llvm.x86.avx512.uitofp.round.v4f32.v4i64" => "__builtin_ia32_cvtuqq2ps256_mask",
 
         // TODO: support the tile builtins:
         "llvm.x86.ldtilecfg" => "__builtin_trap",
diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs
index 09132c34aae..0753ac1aeb8 100644
--- a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs
+++ b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs
@@ -4,7 +4,9 @@ mod simd;
 #[cfg(feature = "master")]
 use std::iter;
 
-use gccjit::{ComparisonOp, Function, FunctionType, RValue, ToRValue, Type, UnaryOp};
+#[cfg(feature = "master")]
+use gccjit::Type;
+use gccjit::{ComparisonOp, Function, FunctionType, RValue, ToRValue, UnaryOp};
 #[cfg(feature = "master")]
 use rustc_abi::ExternAbi;
 use rustc_abi::{BackendRepr, HasDataLayout};
@@ -112,7 +114,6 @@ fn get_simple_intrinsic<'gcc, 'tcx>(
         }
         sym::copysignf32 => "copysignf",
         sym::copysignf64 => "copysign",
-        sym::copysignf128 => "copysignl",
         sym::floorf32 => "floorf",
         sym::floorf64 => "floor",
         sym::ceilf32 => "ceilf",
@@ -236,6 +237,7 @@ fn get_simple_function_f128_2args<'gcc, 'tcx>(
     let func_name = match name {
         sym::maxnumf128 => "fmaxf128",
         sym::minnumf128 => "fminf128",
+        sym::copysignf128 => "copysignf128",
         _ => return None,
     };
     Some(cx.context.new_function(
@@ -259,6 +261,7 @@ fn f16_builtin<'gcc, 'tcx>(
     let f32_type = cx.type_f32();
     let builtin_name = match name {
         sym::ceilf16 => "__builtin_ceilf",
+        sym::copysignf16 => "__builtin_copysignf",
         sym::floorf16 => "__builtin_floorf",
         sym::fmaf16 => "fmaf",
         sym::maxnumf16 => "__builtin_fmaxf",
@@ -300,6 +303,8 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc
         let fn_args = instance.args;
 
         let simple = get_simple_intrinsic(self, name);
+        // TODO(antoyo): Only call get_simple_function_f128 and get_simple_function_f128_2args when
+        // it is the symbols for the supported f128 builtins.
         let simple_func = get_simple_function(self, name)
             .or_else(|| get_simple_function_f128(self, name))
             .or_else(|| get_simple_function_f128_2args(self, name));
@@ -326,6 +331,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc
                 )
             }
             sym::ceilf16
+            | sym::copysignf16
             | sym::floorf16
             | sym::fmaf16
             | sym::maxnumf16
@@ -441,7 +447,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc
                 match int_type_width_signed(args[0].layout.ty, self) {
                     Some((width, signed)) => match name {
                         sym::ctlz | sym::cttz => {
-                            let func = self.current_func.borrow().expect("func");
+                            let func = self.current_func();
                             let then_block = func.new_block("then");
                             let else_block = func.new_block("else");
                             let after_block = func.new_block("after");
@@ -535,7 +541,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc
                         // For rusty ABIs, small aggregates are actually passed
                         // as `RegKind::Integer` (see `FnAbi::adjust_for_abi`),
                         // so we re-use that same threshold here.
-                        layout.size() <= self.data_layout().pointer_size * 2
+                        layout.size() <= self.data_layout().pointer_size() * 2
                     }
                 };
 
@@ -1109,7 +1115,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
         // for (int counter = 0; value != 0; counter++) {
         //     value &= value - 1;
         // }
-        let func = self.current_func.borrow().expect("func");
+        let func = self.current_func();
         let loop_head = func.new_block("head");
         let loop_body = func.new_block("body");
         let loop_tail = func.new_block("tail");
@@ -1188,7 +1194,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
         let result_type = lhs.get_type();
         if signed {
             // Based on algorithm from: https://stackoverflow.com/a/56531252/389119
-            let func = self.current_func.borrow().expect("func");
+            let func = self.current_func();
             let res = func.new_local(self.location, result_type, "saturating_sum");
             let supports_native_type = self.is_native_int_type(result_type);
             let overflow = if supports_native_type {
@@ -1259,7 +1265,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
         let result_type = lhs.get_type();
         if signed {
             // Based on algorithm from: https://stackoverflow.com/a/56531252/389119
-            let func = self.current_func.borrow().expect("func");
+            let func = self.current_func();
             let res = func.new_local(self.location, result_type, "saturating_diff");
             let supports_native_type = self.is_native_int_type(result_type);
             let overflow = if supports_native_type {
@@ -1483,10 +1489,9 @@ fn gen_fn<'a, 'gcc, 'tcx>(
     // FIXME(eddyb) find a nicer way to do this.
     cx.linkage.set(FunctionType::Internal);
     let func = cx.declare_fn(name, fn_abi);
-    let func_val = unsafe { std::mem::transmute::<Function<'gcc>, RValue<'gcc>>(func) };
-    cx.set_frame_pointer_type(func_val);
-    cx.apply_target_cpu_attr(func_val);
-    let block = Builder::append_block(cx, func_val, "entry-block");
+    cx.set_frame_pointer_type(func);
+    cx.apply_target_cpu_attr(func);
+    let block = Builder::append_block(cx, func, "entry-block");
     let bx = Builder::build(cx, block);
     codegen(bx);
     (return_type, func)
diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs b/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs
index 6f6bc93b8b2..350915a277e 100644
--- a/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs
+++ b/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs
@@ -61,7 +61,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
         let (len, _) = args[1].layout.ty.simd_size_and_type(bx.tcx());
 
         let expected_int_bits = (len.max(8) - 1).next_power_of_two();
-        let expected_bytes = len / 8 + ((len % 8 > 0) as u64);
+        let expected_bytes = len / 8 + ((!len.is_multiple_of(8)) as u64);
 
         let mask_ty = args[0].layout.ty;
         let mut mask = match *mask_ty.kind() {
@@ -676,7 +676,8 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
         let elem_type = vector_type.get_element_type();
 
         let expected_int_bits = in_len.max(8);
-        let expected_bytes = expected_int_bits / 8 + ((expected_int_bits % 8 > 0) as u64);
+        let expected_bytes =
+            expected_int_bits / 8 + ((!expected_int_bits.is_multiple_of(8)) as u64);
 
         // FIXME(antoyo): that's not going to work for masks bigger than 128 bits.
         let result_type = bx.type_ix(expected_int_bits);
@@ -779,6 +780,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
             sym::simd_fsin => "sin",
             sym::simd_fsqrt => "sqrt",
             sym::simd_round => "round",
+            sym::simd_round_ties_even => "rint",
             sym::simd_trunc => "trunc",
             _ => return_error!(InvalidMonomorphization::UnrecognizedIntrinsic { span, name }),
         };
@@ -826,6 +828,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
             | sym::simd_fsin
             | sym::simd_fsqrt
             | sym::simd_round
+            | sym::simd_round_ties_even
             | sym::simd_trunc
     ) {
         return simd_simple_float_intrinsic(name, in_elem, in_ty, in_len, bx, span, args);
@@ -1181,7 +1184,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
         let lhs = args[0].immediate();
         let rhs = args[1].immediate();
         let is_add = name == sym::simd_saturating_add;
-        let ptr_bits = bx.tcx().data_layout.pointer_size.bits() as _;
+        let ptr_bits = bx.tcx().data_layout.pointer_size().bits() as _;
         let (signed, elem_width, elem_ty) = match *in_elem.kind() {
             ty::Int(i) => (true, i.bit_width().unwrap_or(ptr_bits) / 8, bx.cx.type_int_from_ty(i)),
             ty::Uint(i) => {
diff --git a/compiler/rustc_codegen_gcc/src/lib.rs b/compiler/rustc_codegen_gcc/src/lib.rs
index a912678ef2a..d81bcc59775 100644
--- a/compiler/rustc_codegen_gcc/src/lib.rs
+++ b/compiler/rustc_codegen_gcc/src/lib.rs
@@ -19,19 +19,15 @@
 #![doc(rust_logo)]
 #![feature(rustdoc_internals)]
 #![feature(rustc_private)]
-#![allow(broken_intra_doc_links)]
 #![recursion_limit = "256"]
 #![warn(rust_2018_idioms)]
 #![warn(unused_lifetimes)]
 #![deny(clippy::pattern_type_mismatch)]
 #![allow(clippy::needless_lifetimes, clippy::uninlined_format_args)]
 
-// Some "regular" crates we want to share with rustc
-extern crate object;
+// These crates are pulled from the sysroot because they are part of
+// rustc's public API, so we need to ensure version compatibility.
 extern crate smallvec;
-// FIXME(antoyo): clippy bug: remove the #[allow] when it's fixed.
-#[allow(unused_extern_crates)]
-extern crate tempfile;
 #[macro_use]
 extern crate tracing;
 
@@ -97,7 +93,7 @@ use gccjit::{CType, Context, OptimizationLevel};
 use gccjit::{TargetInfo, Version};
 use rustc_ast::expand::allocator::AllocatorKind;
 use rustc_ast::expand::autodiff_attrs::AutoDiffItem;
-use rustc_codegen_ssa::back::lto::{LtoModuleCodegen, SerializedModule, ThinModule};
+use rustc_codegen_ssa::back::lto::{SerializedModule, ThinModule};
 use rustc_codegen_ssa::back::write::{
     CodegenContext, FatLtoInput, ModuleConfig, TargetMachineFactoryFn,
 };
@@ -357,11 +353,16 @@ impl WriteBackendMethods for GccCodegenBackend {
     type ThinData = ThinData;
     type ThinBuffer = ThinBuffer;
 
-    fn run_fat_lto(
+    fn run_and_optimize_fat_lto(
         cgcx: &CodegenContext<Self>,
         modules: Vec<FatLtoInput<Self>>,
         cached_modules: Vec<(SerializedModule<Self::ModuleBuffer>, WorkProduct)>,
-    ) -> Result<LtoModuleCodegen<Self>, FatalError> {
+        diff_fncs: Vec<AutoDiffItem>,
+    ) -> Result<ModuleCodegen<Self::Module>, FatalError> {
+        if !diff_fncs.is_empty() {
+            unimplemented!();
+        }
+
         back::lto::run_fat(cgcx, modules, cached_modules)
     }
 
@@ -369,7 +370,7 @@ impl WriteBackendMethods for GccCodegenBackend {
         cgcx: &CodegenContext<Self>,
         modules: Vec<(String, Self::ThinBuffer)>,
         cached_modules: Vec<(SerializedModule<Self::ModuleBuffer>, WorkProduct)>,
-    ) -> Result<(Vec<LtoModuleCodegen<Self>>, Vec<WorkProduct>), FatalError> {
+    ) -> Result<(Vec<ThinModule<Self>>, Vec<WorkProduct>), FatalError> {
         back::lto::run_thin(cgcx, modules, cached_modules)
     }
 
@@ -391,14 +392,6 @@ impl WriteBackendMethods for GccCodegenBackend {
         Ok(())
     }
 
-    fn optimize_fat(
-        _cgcx: &CodegenContext<Self>,
-        _module: &mut ModuleCodegen<Self::Module>,
-    ) -> Result<(), FatalError> {
-        // TODO(antoyo)
-        Ok(())
-    }
-
     fn optimize_thin(
         cgcx: &CodegenContext<Self>,
         thin: ThinModule<Self>,
@@ -408,11 +401,10 @@ impl WriteBackendMethods for GccCodegenBackend {
 
     fn codegen(
         cgcx: &CodegenContext<Self>,
-        dcx: DiagCtxtHandle<'_>,
         module: ModuleCodegen<Self::Module>,
         config: &ModuleConfig,
     ) -> Result<CompiledModule, FatalError> {
-        back::write::codegen(cgcx, dcx, module, config)
+        back::write::codegen(cgcx, module, config)
     }
 
     fn prepare_thin(
@@ -433,15 +425,6 @@ impl WriteBackendMethods for GccCodegenBackend {
     ) -> Result<ModuleCodegen<Self::Module>, FatalError> {
         back::write::link(cgcx, dcx, modules)
     }
-
-    fn autodiff(
-        _cgcx: &CodegenContext<Self>,
-        _module: &ModuleCodegen<Self::Module>,
-        _diff_functions: Vec<AutoDiffItem>,
-        _config: &ModuleConfig,
-    ) -> Result<(), FatalError> {
-        unimplemented!()
-    }
 }
 
 /// This is the entrypoint for a hot plugged rustc_codegen_gccjit
diff --git a/compiler/rustc_codegen_gcc/tests/failing-ui-tests.txt b/compiler/rustc_codegen_gcc/tests/failing-ui-tests.txt
index d931f0d3b5e..544d0bfc710 100644
--- a/compiler/rustc_codegen_gcc/tests/failing-ui-tests.txt
+++ b/compiler/rustc_codegen_gcc/tests/failing-ui-tests.txt
@@ -9,6 +9,7 @@ tests/ui/iterators/iter-sum-overflow-debug.rs
 tests/ui/iterators/iter-sum-overflow-overflow-checks.rs
 tests/ui/mir/mir_drop_order.rs
 tests/ui/mir/mir_let_chains_drop_order.rs
+tests/ui/mir/mir_match_guard_let_chains_drop_order.rs
 tests/ui/oom_unwind.rs
 tests/ui/panic-runtime/abort-link-to-unwinding-crates.rs
 tests/ui/panic-runtime/abort.rs
diff --git a/compiler/rustc_codegen_gcc/tools/generate_intrinsics.py b/compiler/rustc_codegen_gcc/tools/generate_intrinsics.py
index ed0ebf00719..88927f39b93 100644
--- a/compiler/rustc_codegen_gcc/tools/generate_intrinsics.py
+++ b/compiler/rustc_codegen_gcc/tools/generate_intrinsics.py
@@ -176,14 +176,14 @@ def update_intrinsics(llvm_path, llvmint, llvmint2):
         out.write("// File generated by `rustc_codegen_gcc/tools/generate_intrinsics.py`\n")
         out.write("// DO NOT EDIT IT!\n")
         out.write("/// Translate a given LLVM intrinsic name to an equivalent GCC one.\n")
-        out.write("fn map_arch_intrinsic(name:&str)->&str{\n")
-        out.write('let Some(name) = name.strip_prefix("llvm.") else { unimplemented!("***** unsupported LLVM intrinsic {}", name) };\n')
+        out.write("fn map_arch_intrinsic(full_name:&str)->&'static str{\n")
+        out.write('let Some(name) = full_name.strip_prefix("llvm.") else { unimplemented!("***** unsupported LLVM intrinsic {}", full_name) };\n')
         out.write('let Some((arch, name)) = name.split_once(\'.\') else { unimplemented!("***** unsupported LLVM intrinsic {}", name) };\n')
         out.write("match arch {\n")
         for arch in archs:
             if len(intrinsics[arch]) == 0:
                 continue
-            out.write("\"{}\" => {{ #[allow(non_snake_case)] fn {}(name: &str) -> &str {{ match name {{".format(arch,arch))
+            out.write("\"{}\" => {{ #[allow(non_snake_case)] fn {}(name: &str,full_name:&str) -> &'static str {{ match name {{".format(arch,arch))
             intrinsics[arch].sort(key=lambda x: (x[0], x[2]))
             out.write('    // {}\n'.format(arch))
             for entry in intrinsics[arch]:
@@ -196,9 +196,9 @@ def update_intrinsics(llvm_path, llvmint, llvmint2):
                     out.write('    // [INVALID CONVERSION]: "{}" => "{}",\n'.format(llvm_name, entry[1]))
                 else:
                     out.write('    "{}" => "{}",\n'.format(llvm_name, entry[1]))
-            out.write('    _ => unimplemented!("***** unsupported LLVM intrinsic {}", name),\n')
-            out.write("}} }} {}(name) }}\n,".format(arch))
-        out.write('    _ => unimplemented!("***** unsupported LLVM architecture {}", name),\n')
+            out.write('    _ => unimplemented!("***** unsupported LLVM intrinsic {full_name}"),\n')
+            out.write("}} }} {}(name,full_name) }}\n,".format(arch))
+        out.write('    _ => unimplemented!("***** unsupported LLVM architecture {arch}, intrinsic:{full_name}"),\n')
         out.write("}\n}")
     subprocess.call(["rustfmt", output_file])
     print("Done!")