Submitted By:            Xi Ruoyao <xry111 at xry111 dot site>
Date:                    2026-03-06
Initial Package Version: 1.94.0
Upstream Status:         Applied for master but not 1.94.x
Origin:                  https://github.com/rust-lang/rust/pull/151410.patch
Description:             Fix issues causing test failures and potential
                         code generation issues with LLVM 22.

From bf3ac98d6930ba4e258cf33240c2fe7c99d19eae Mon Sep 17 00:00:00 2001
From: Nikita Popov <npopov@redhat.com>
Date: Tue, 6 Jan 2026 11:51:33 +0100
Subject: [PATCH 1/3] Update amdgpu data layout

This changed in:
https://github.com/llvm/llvm-project/commit/853760bca6aa7a960b154cef8c61f87271870b8a
---
 compiler/rustc_codegen_llvm/src/context.rs                  | 5 +++++
 compiler/rustc_target/src/spec/targets/amdgcn_amd_amdhsa.rs | 2 +-
 2 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs
index 4b2544b7efdf8..4328b15c73f30 100644
--- a/compiler/rustc_codegen_llvm/src/context.rs
+++ b/compiler/rustc_codegen_llvm/src/context.rs
@@ -215,6 +215,11 @@ pub(crate) unsafe fn create_module<'ll>(
             // LLVM 22 updated the ABI alignment for double on AIX: https://github.com/llvm/llvm-project/pull/144673
             target_data_layout = target_data_layout.replace("-f64:32:64", "");
         }
+        if sess.target.arch == Arch::AmdGpu {
+            // LLVM 22 specified ELF mangling in the amdgpu data layout:
+            // https://github.com/llvm/llvm-project/pull/163011
+            target_data_layout = target_data_layout.replace("-m:e", "");
+        }
     }
 
     // Ensure the data-layout values hardcoded remain the defaults.
diff --git a/compiler/rustc_target/src/spec/targets/amdgcn_amd_amdhsa.rs b/compiler/rustc_target/src/spec/targets/amdgcn_amd_amdhsa.rs
index 828d853ac65ec..d6a2cfc2aab55 100644
--- a/compiler/rustc_target/src/spec/targets/amdgcn_amd_amdhsa.rs
+++ b/compiler/rustc_target/src/spec/targets/amdgcn_amd_amdhsa.rs
@@ -5,7 +5,7 @@ use crate::spec::{
 pub(crate) fn target() -> Target {
     Target {
         arch: Arch::AmdGpu,
-        data_layout: "e-p:64:64-p1:64:64-p2:32:32-p3:32:32-p4:64:64-p5:32:32-p6:32:32-p7:160:256:256:32-p8:128:128:128:48-p9:192:256:256:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64-S32-A5-G1-ni:7:8:9".into(),
+        data_layout: "e-m:e-p:64:64-p1:64:64-p2:32:32-p3:32:32-p4:64:64-p5:32:32-p6:32:32-p7:160:256:256:32-p8:128:128:128:48-p9:192:256:256:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64-S32-A5-G1-ni:7:8:9".into(),
         llvm_target: "amdgcn-amd-amdhsa".into(),
         metadata: TargetMetadata {
             description: Some("AMD GPU".into()),

From 0be66603ac37474fe884ad1b384510d1ddc37417 Mon Sep 17 00:00:00 2001
From: Nikita Popov <npopov@redhat.com>
Date: Tue, 6 Jan 2026 12:14:36 +0100
Subject: [PATCH 2/3] Avoid passing addrspacecast to lifetime intrinsics

Since LLVM 22 the alloca must be passed directly. Do this by
stripping the addrspacecast if it exists.
---
 compiler/rustc_codegen_llvm/src/builder.rs       |  3 +++
 compiler/rustc_codegen_llvm/src/llvm/ffi.rs      |  1 +
 compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp |  4 ++++
 tests/codegen-llvm/amdgpu-addrspacecast.rs       | 11 ++++++++++-
 4 files changed, 18 insertions(+), 1 deletion(-)

diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs
index 557ae7b0333e3..9379faf1156fc 100644
--- a/compiler/rustc_codegen_llvm/src/builder.rs
+++ b/compiler/rustc_codegen_llvm/src/builder.rs
@@ -1788,6 +1788,9 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
         }
 
         if crate::llvm_util::get_version() >= (22, 0, 0) {
+            // LLVM 22 requires the lifetime intrinsic to act directly on the alloca,
+            // there can't be an addrspacecast in between.
+            let ptr = unsafe { llvm::LLVMRustStripPointerCasts(ptr) };
             self.call_intrinsic(intrinsic, &[self.val_ty(ptr)], &[ptr]);
         } else {
             self.call_intrinsic(intrinsic, &[self.val_ty(ptr)], &[self.cx.const_u64(size), ptr]);
diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
index c535fade9c040..a3d4e9f9d32a2 100644
--- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
@@ -1967,6 +1967,7 @@ unsafe extern "C" {
         Metadata: &'a Metadata,
     );
     pub(crate) fn LLVMRustIsNonGVFunctionPointerTy(Val: &Value) -> bool;
+    pub(crate) fn LLVMRustStripPointerCasts<'a>(Val: &'a Value) -> &'a Value;
 
     // Operations on scalar constants
     pub(crate) fn LLVMRustConstIntGetZExtValue(ConstantVal: &ConstantInt, Value: &mut u64) -> bool;
diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
index 336d589740362..599f79d011989 100644
--- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
@@ -1760,6 +1760,10 @@ extern "C" bool LLVMRustIsNonGVFunctionPointerTy(LLVMValueRef V) {
   return false;
 }
 
+extern "C" LLVMValueRef LLVMRustStripPointerCasts(LLVMValueRef V) {
+  return wrap(unwrap(V)->stripPointerCasts());
+}
+
 extern "C" bool LLVMRustLLVMHasZlibCompression() {
   return llvm::compression::zlib::isAvailable();
 }
diff --git a/tests/codegen-llvm/amdgpu-addrspacecast.rs b/tests/codegen-llvm/amdgpu-addrspacecast.rs
index 16a0c276ac0ed..144565f7e28ca 100644
--- a/tests/codegen-llvm/amdgpu-addrspacecast.rs
+++ b/tests/codegen-llvm/amdgpu-addrspacecast.rs
@@ -1,16 +1,25 @@
 // Check that pointers are casted to addrspace(0) before they are used
 
-//@ compile-flags: --crate-type=rlib --target=amdgcn-amd-amdhsa -Ctarget-cpu=gfx900
+//@ compile-flags: --crate-type=rlib --target=amdgcn-amd-amdhsa -Ctarget-cpu=gfx900 -O
 //@ needs-llvm-components: amdgpu
 //@ add-minicore
+//@ revisions: LLVM21 LLVM22
+//@ [LLVM21] max-llvm-major-version: 21
+//@ [LLVM22] min-llvm-version: 22
 #![feature(no_core)]
 #![no_core]
 
 extern crate minicore;
 
+// Make sure that on LLVM 22, the alloca is passed directly to the lifetime intrinsics,
+// not the addrspacecast.
+
 // CHECK-LABEL: @ref_of_local
 // CHECK: [[alloca:%[0-9]]] = alloca
 // CHECK: %i = addrspacecast ptr addrspace(5) [[alloca]] to ptr
+// LLVM22: call void @llvm.lifetime.start.p5(ptr addrspace(5) [[alloca]])
+// CHECK: call void %f(ptr{{.*}}%i)
+// LLVM22: call void @llvm.lifetime.end.p5(ptr addrspace(5) [[alloca]])
 #[no_mangle]
 pub fn ref_of_local(f: fn(&i32)) {
     let i = 0;

From 08da3685eddca11092fecab35c053843e02df0aa Mon Sep 17 00:00:00 2001
From: Nikita Popov <npopov@redhat.com>
Date: Fri, 9 Jan 2026 14:56:11 +0100
Subject: [PATCH 3/3] Don't use evex512 with LLVM 22

As Intel has walked back on the existence of AVX 10.1-256, LLVM
no longer uses evex512 and avx-10.n-512 are now avx-10.n instead,
so we can skip all the special handling on LLVM 22.
---
 compiler/rustc_codegen_llvm/src/llvm_util.rs | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs
index 63f820dc29184..fbb582fe86018 100644
--- a/compiler/rustc_codegen_llvm/src/llvm_util.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs
@@ -287,12 +287,12 @@ pub(crate) fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> Option<LLVMFea
                 "cmpxchg16b" => Some(LLVMFeature::new("cx16")),
                 "lahfsahf" => Some(LLVMFeature::new("sahf")),
                 // Enable the evex512 target feature if an avx512 target feature is enabled.
-                s if s.starts_with("avx512") => Some(LLVMFeature::with_dependencies(
+                s if s.starts_with("avx512") && major < 22 => Some(LLVMFeature::with_dependencies(
                     s,
                     smallvec![TargetFeatureFoldStrength::EnableOnly("evex512")],
                 )),
-                "avx10.1" => Some(LLVMFeature::new("avx10.1-512")),
-                "avx10.2" => Some(LLVMFeature::new("avx10.2-512")),
+                "avx10.1" if major < 22 => Some(LLVMFeature::new("avx10.1-512")),
+                "avx10.2" if major < 22 => Some(LLVMFeature::new("avx10.2-512")),
                 "apxf" => Some(LLVMFeature::with_dependencies(
                     "egpr",
                     smallvec![
