diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
index 604c92369e9a2..0eefba177eb06 100644
--- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
@@ -1597,7 +1597,6 @@ bool ProcessGDBRemote::CalculateThreadStopInfo(ThreadGDBRemote *thread) {
// If we have "jstopinfo" then we have stop descriptions for all threads
// that have stop reasons, and if there is no entry for a thread, then it
// has no stop reason.
- thread->GetRegisterContext()->InvalidateIfNeeded(true);
if (!GetThreadStopInfoFromJSON(thread, m_jstopinfo_sp)) {
// If a thread is stopped at a breakpoint site, set that as the stop
// reason even if it hasn't executed the breakpoint instruction yet.
diff --git a/lldb/test/API/macosx/expedited-thread-pcs/Makefile b/lldb/test/API/macosx/expedited-thread-pcs/Makefile
new file mode 100644
index 0000000000000..7799f06e77097
--- /dev/null
+++ b/lldb/test/API/macosx/expedited-thread-pcs/Makefile
@@ -0,0 +1,11 @@
+CXX_SOURCES := main.cpp
+
+.PHONY: build-libfoo
+all: build-libfoo a.out
+
+include Makefile.rules
+
+build-libfoo: foo.c
+ $(MAKE) -f $(MAKEFILE_RULES) \
+ DYLIB_C_SOURCES=foo.c DYLIB_NAME=foo DYLIB_ONLY=YES
+
diff --git a/lldb/test/API/macosx/expedited-thread-pcs/TestExpeditedThreadPCs.py b/lldb/test/API/macosx/expedited-thread-pcs/TestExpeditedThreadPCs.py
new file mode 100644
index 0000000000000..0611907a34b0d
--- /dev/null
+++ b/lldb/test/API/macosx/expedited-thread-pcs/TestExpeditedThreadPCs.py
@@ -0,0 +1,91 @@
+"""Test that the expedited thread pc values are not re-fetched by lldb."""
+
+import subprocess
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+file_index = 0
+
+
+class TestExpeditedThreadPCs(TestBase):
+ NO_DEBUG_INFO_TESTCASE = True
+
+ @skipUnlessDarwin
+ def test_expedited_thread_pcs(self):
+ TestBase.setUp(self)
+
+ global file_index
+ ++file_index
+ logfile = os.path.join(
+ self.getBuildDir(),
+ "packet-log-" + self.getArchitecture() + "-" + str(file_index) + ".txt",
+ )
+ self.runCmd("log enable -f %s gdb-remote packets" % (logfile))
+
+ def cleanup():
+ self.runCmd("log disable gdb-remote packets")
+ if os.path.exists(logfile):
+ os.unlink(logfile)
+
+ self.addTearDownHook(cleanup)
+
+ self.source = "main.cpp"
+ self.build()
+ (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(
+ self, "break here", lldb.SBFileSpec(self.source, False)
+ )
+
+ # verify that libfoo.dylib hasn't loaded yet
+ for m in target.modules:
+ self.assertNotEqual(m.GetFileSpec().GetFilename(), "libfoo.dylib")
+
+ thread.StepInto()
+ thread.StepInto()
+
+ thread.StepInto()
+ thread.StepInto()
+ thread.StepInto()
+
+ # verify that libfoo.dylib has loaded
+ for m in target.modules:
+ if m.GetFileSpec().GetFilename() == "libfoo.dylib":
+ found_libfoo = True
+ self.assertTrue(found_libfoo)
+
+ thread.StepInto()
+ thread.StepInto()
+ thread.StepOver()
+ thread.StepOver()
+ thread.StepOver()
+ thread.StepOver()
+ thread.StepOver()
+ thread.StepOver()
+ thread.StepOver()
+ thread.StepOver()
+ thread.StepOver()
+ thread.StepOver()
+
+ process.Kill()
+
+ # Confirm that we never fetched the pc for any threads during
+ # this debug session.
+ if os.path.exists(logfile):
+ f = open(logfile)
+ lines = f.readlines()
+ num_errors = 0
+ for line in lines:
+ arch = self.getArchitecture()
+ if arch == "arm64" or arch == "arm64_32":
+ #
+ # A fetch of $pc on arm64 looks like
+ # < 22> send packet: $p20;thread:91698e;#70
+ self.assertNotIn("$p20;thread", line)
+ else:
+ #
+ # A fetch of $pc on x86_64 looks like
+ # < 22> send packet: $p10;thread:91889c;#6f
+ self.assertNotIn("$p10;thread", line)
+
+ f.close()
diff --git a/lldb/test/API/macosx/expedited-thread-pcs/foo.c b/lldb/test/API/macosx/expedited-thread-pcs/foo.c
new file mode 100644
index 0000000000000..de1cbc4c4648a
--- /dev/null
+++ b/lldb/test/API/macosx/expedited-thread-pcs/foo.c
@@ -0,0 +1 @@
+int foo() { return 5; }
diff --git a/lldb/test/API/macosx/expedited-thread-pcs/main.cpp b/lldb/test/API/macosx/expedited-thread-pcs/main.cpp
new file mode 100644
index 0000000000000..d77c6793afb6b
--- /dev/null
+++ b/lldb/test/API/macosx/expedited-thread-pcs/main.cpp
@@ -0,0 +1,62 @@
+#include
+#include
+#include
+#include
+
+void f1() {
+ while (1)
+ sleep(1);
+}
+void f2() {
+ while (1)
+ sleep(1);
+}
+void f3() {
+ while (1)
+ sleep(1);
+}
+
+int main() {
+ std::thread t1{f1};
+ std::thread t2{f2};
+ std::thread t3{f3};
+
+ puts("break here");
+
+ void *handle = dlopen("libfoo.dylib", RTLD_LAZY);
+ int (*foo_ptr)() = (int (*)())dlsym(handle, "foo");
+ int c = foo_ptr();
+
+ // clang-format off
+ // multiple function calls on a single source line so 'step'
+ // and 'next' need to do multiple steps of work.
+ puts("1"); puts("2"); puts("3"); puts("4"); puts("5");
+ puts("6"); puts("7"); puts("8"); puts("9"); puts("10");
+ puts("11"); puts("12"); puts("13"); puts("14"); puts("15");
+ puts("16"); puts("17"); puts("18"); puts("19"); puts("20");
+ puts("21"); puts("22"); puts("23"); puts("24"); puts("24");
+ // clang-format on
+ puts("one");
+ puts("two");
+ puts("three");
+ puts("four");
+ puts("five");
+ puts("six");
+ puts("seven");
+ puts("eight");
+ puts("nine");
+ puts("ten");
+ c++;
+ c++;
+ c++;
+ c++;
+ c++;
+ c++;
+ c++;
+ c++;
+ c++;
+ c++;
+ c++;
+ c++;
+ return c;
+}