diff --git a/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs b/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs
index c139f915e6c..c710fcc2c1d 100644
--- a/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs
@@ -3,9 +3,11 @@ use rustc_index::vec::IndexVec;
 use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use rustc_middle::mir;
 use rustc_middle::ty;
+use rustc_middle::ty::layout::LayoutOf;
 use rustc_session::config::DebugInfo;
 use rustc_span::symbol::{kw, Symbol};
 use rustc_span::{BytePos, Span};
+use rustc_target::abi::Abi;
 use rustc_target::abi::Size;
 
 use super::operand::{OperandRef, OperandValue};
@@ -368,21 +370,14 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                         {
                             let arg_index = place.local.index() - 1;
                             if target_is_msvc {
-                                // Rust compiler decomposes every &str or slice argument into two components:
-                                // a pointer to the memory address where the data is stored and a usize representing
-                                // the length of the str (or slice). These components will later be used to reconstruct
-                                // the original argument inside the body of the function that owns it (see the
-                                // definition of debug_introduce_local for more details).
-                                //
-                                // Since the original argument is declared inside a function rather than being passed
-                                // in as an argument, it must be marked as a LocalVariable for MSVC debuggers to visualize
-                                // its data correctly. (See issue #81894 for an in-depth description of the problem).
-                                match *var_ty.kind() {
-                                    ty::Ref(_, inner_type, _) => match *inner_type.kind() {
-                                        ty::Slice(_) | ty::Str => VariableKind::LocalVariable,
-                                        _ => VariableKind::ArgumentVariable(arg_index + 1),
-                                    },
-                                    _ => VariableKind::ArgumentVariable(arg_index + 1),
+                                // ScalarPair parameters are spilled to the stack so they need to
+                                // be marked as a `LocalVariable` for MSVC debuggers to visualize
+                                // their data correctly. (See #81894 & #88625)
+                                let var_ty_layout = self.cx.layout_of(var_ty);
+                                if let Abi::ScalarPair(_, _) = var_ty_layout.abi {
+                                    VariableKind::LocalVariable
+                                } else {
+                                    VariableKind::ArgumentVariable(arg_index + 1)
                                 }
                             } else {
                                 // FIXME(eddyb) shouldn't `ArgumentVariable` indices be
diff --git a/compiler/rustc_codegen_ssa/src/mir/mod.rs b/compiler/rustc_codegen_ssa/src/mir/mod.rs
index 8e3982c72d7..37f5de309ba 100644
--- a/compiler/rustc_codegen_ssa/src/mir/mod.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/mod.rs
@@ -129,6 +129,7 @@ impl<'a, 'tcx, V: CodegenObject> LocalRef<'tcx, V> {
 
 ///////////////////////////////////////////////////////////////////////////
 
+#[instrument(level = "debug", skip(cx))]
 pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
     cx: &'a Bx::CodegenCx,
     instance: Instance<'tcx>,
diff --git a/src/test/debuginfo/msvc-scalarpair-params.rs b/src/test/debuginfo/msvc-scalarpair-params.rs
new file mode 100644
index 00000000000..3846fb42f81
--- /dev/null
+++ b/src/test/debuginfo/msvc-scalarpair-params.rs
@@ -0,0 +1,101 @@
+// only-cdb
+// compile-flags: -g
+
+// cdb-command: g
+
+// cdb-command: dx r1
+// cdb-check:r1               : (0xa..0xc) [Type: core::ops::range::Range<u32>]
+// cdb-command: dx r2
+// cdb-check:r2               : (0x14..0x1e) [Type: core::ops::range::Range<u64>]
+
+// cdb-command: g
+
+// cdb-command: dx r1
+// cdb-check:r1               : (0x9..0x64) [Type: core::ops::range::Range<u32>]
+// cdb-command: dx r2
+// cdb-check:r2               : (0xc..0x5a) [Type: core::ops::range::Range<u64>]
+
+// cdb-command: g
+
+// cdb-command: dx o1
+// cdb-check:o1               : Some [Type: enum$<core::option::Option<u32> >]
+// cdb-check:    [variant]        : Some
+// cdb-check:    [+0x004] __0              : 0x4d2 [Type: [...]]
+// cdb-command: dx o2
+// cdb-check:o2               : Some [Type: enum$<core::option::Option<u64> >]
+// cdb-check:    [variant]        : Some
+// cdb-check:    [+0x008] __0              : 0x162e [Type: unsigned __int64]
+
+// cdb-command: g
+
+// cdb-command: dx t1
+// cdb-check:t1               : (0xa, 0x14) [Type: tuple$<u32,u32>]
+// cdb-check:    [0]              : 0xa [Type: unsigned int]
+// cdb-check:    [1]              : 0x14 [Type: unsigned int]
+// cdb-command: dx t2
+// cdb-check:t2               : (0x1e, 0x28) [Type: tuple$<u64,u64>]
+// cdb-check:    [0]              : 0x1e [Type: unsigned __int64]
+// cdb-check:    [1]              : 0x28 [Type: unsigned __int64]
+
+// cdb-command: g
+
+// cdb-command: dx s
+// cdb-check:s                : "this is a static str" [Type: str]
+// cdb-check:    [len]            : 0x14 [Type: unsigned [...]]
+// cdb-check:    [chars]
+
+// cdb-command: g
+
+// cdb-command: dx s
+// cdb-check:s                : { len=0x5 } [Type: slice$<u8>]
+// cdb-check:    [len]            : 0x5 [Type: unsigned [...]]
+// cdb-check:    [0]              : 0x1 [Type: unsigned char]
+// cdb-check:    [1]              : 0x2 [Type: unsigned char]
+// cdb-check:    [2]              : 0x3 [Type: unsigned char]
+// cdb-check:    [3]              : 0x4 [Type: unsigned char]
+// cdb-check:    [4]              : 0x5 [Type: unsigned char]
+
+use std::ops::Range;
+
+fn range(r1: Range<u32>, r2: Range<u64>) {
+    zzz(); // #break
+}
+
+fn range_mut(mut r1: Range<u32>, mut r2: Range<u64>) {
+    if r1.start == 9 {
+        r1.end = 100;
+    }
+
+    if r2.start == 12 {
+        r2.end = 90;
+    }
+
+    zzz(); // #break
+}
+
+fn option(o1: Option<u32>, o2: Option<u64>) {
+    zzz(); // #break
+}
+
+fn tuple(t1: (u32, u32), t2: (u64, u64)) {
+    zzz(); // #break
+}
+
+fn str(s: &str) {
+    zzz(); // #break
+}
+
+fn slice(s: &[u8]) {
+    zzz(); // #break
+}
+
+fn zzz() { }
+
+fn main() {
+    range(10..12, 20..30);
+    range_mut(9..20, 12..80);
+    option(Some(1234), Some(5678));
+    tuple((10, 20), (30, 40));
+    str("this is a static str");
+    slice(&[1, 2, 3, 4, 5]);
+}