[llvm-branch-commits] [llvm] b235617 - Merge branch 'main' into revert-201373-users/mizvekov/get-template-inst-args

via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Fri Jun 5 09:27:35 PDT 2026


Author: Hans Wennborg
Date: 2026-06-05T18:27:10+02:00
New Revision: b235617112039202675221d5f450b67994428cca

URL: https://github.com/llvm/llvm-project/commit/b235617112039202675221d5f450b67994428cca
DIFF: https://github.com/llvm/llvm-project/commit/b235617112039202675221d5f450b67994428cca.diff

LOG: Merge branch 'main' into revert-201373-users/mizvekov/get-template-inst-args

Added: 
    lldb/source/Plugins/Process/Windows/Common/IOHandlerProcessSTDIOWindows.cpp
    lldb/source/Plugins/Process/Windows/Common/IOHandlerProcessSTDIOWindows.h
    llvm/test/CodeGen/SPIRV/debug-info/debug-type-function-int-string-dedup.ll
    llvm/test/CodeGen/SPIRV/debug-info/debug-type-function-multi-scalar-params.ll
    llvm/test/CodeGen/SPIRV/debug-info/debug-type-function-omit.ll
    llvm/test/CodeGen/SPIRV/debug-info/debug-type-function-pointer-debug-none-base.ll
    llvm/test/CodeGen/SPIRV/debug-info/debug-type-function-pointer-param.ll
    llvm/test/CodeGen/SPIRV/debug-info/debug-type-function-scalar-returns.ll
    llvm/test/CodeGen/SPIRV/debug-info/debug-type-function-subroutine-type-flags.ll
    llvm/test/CodeGen/SPIRV/debug-info/debug-type-function-void-prototypes.ll
    llvm/test/CodeGen/SPIRV/debug-info/debug-type-pointer-composite-pointee.ll
    llvm/test/tools/llubi/call_unknown.ll

Modified: 
    clang/include/clang/Options/Options.td
    clang/test/Driver/objc-constant-literals.m
    lldb/source/Plugins/Process/Windows/Common/CMakeLists.txt
    lldb/source/Plugins/Process/Windows/Common/ProcessWindows.cpp
    lldb/source/Plugins/Process/Windows/Common/ProcessWindows.h
    lldb/test/API/tools/lldb-server/TestGdbRemote_qThreadStopInfo.py
    llvm/cmake/modules/HandleLLVMOptions.cmake
    llvm/lib/Target/AArch64/AArch64InstrInfo.td
    llvm/lib/Target/AArch64/GISel/AArch64RegisterBankInfo.cpp
    llvm/lib/Target/AMDGPU/MIMGInstructions.td
    llvm/lib/Target/SPIRV/SPIRVNonSemanticDebugHandler.cpp
    llvm/lib/Target/SPIRV/SPIRVNonSemanticDebugHandler.h
    llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp
    llvm/test/CodeGen/AArch64/arm64-arith-saturating.ll
    llvm/test/CodeGen/AArch64/fp-conversion-to-tbl.ll
    llvm/test/CodeGen/AArch64/pr164181.ll
    llvm/test/CodeGen/AArch64/sitofp-to-tbl.ll
    llvm/test/CodeGen/AArch64/trunc-to-tbl.ll
    llvm/test/CodeGen/X86/mbp-false-cfg-break.ll
    llvm/test/MC/AMDGPU/gfx1250_asm_vimage.s
    llvm/test/MC/AMDGPU/gfx1250_asm_vimage_err.s
    llvm/test/MC/Disassembler/AMDGPU/gfx1250_dasm_vimage.txt
    llvm/test/Transforms/InstCombine/ptr-replace-alloca.ll
    llvm/test/Transforms/LoopStrengthReduce/X86/pr62660-normalization-failure.ll
    llvm/tools/llubi/lib/Interpreter.cpp

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/Options/Options.td b/clang/include/clang/Options/Options.td
index 281ccc9614b58..4fd892e58df86 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -2138,7 +2138,7 @@ defm objc_constant_literals : BoolFOption<"objc-constant-literals",
   LangOpts<"ObjCConstantLiterals">, DefaultFalse,
   PosFlag<SetTrue, [], [CC1Option], "Enable">,
   NegFlag<SetFalse, [], [], "Disable">,
-  BothFlags<[], [ClangOption], " compile-time constant ObjC literals">>;
+  BothFlags<[NoArgumentUnused], [ClangOption], " compile-time constant ObjC literals">>;
 def fconstant_array_class_EQ : Joined<["-"], "fconstant-array-class=">, Group<f_Group>,
   Visibility<[ClangOption, CC1Option]>,
   MarshallingInfoString<LangOpts<"ObjCConstantArrayClass">>;
@@ -3820,17 +3820,17 @@ defm constant_nsnumber_literals : BoolFOption<"constant-nsnumber-literals",
   LangOpts<"ConstantNSNumberLiterals">, DefaultFalse,
   PosFlag<SetTrue, [], [CC1Option], "Enable">,
   NegFlag<SetFalse, [], [], "Disable">,
-  BothFlags<[], [ClangOption], " compile-time constant NSNumber literals">>;
+  BothFlags<[NoArgumentUnused], [ClangOption], " compile-time constant NSNumber literals">>;
 defm constant_nsarray_literals : BoolFOption<"constant-nsarray-literals",
   LangOpts<"ConstantNSArrayLiterals">, DefaultFalse,
   PosFlag<SetTrue, [], [CC1Option], "Enable">,
   NegFlag<SetFalse, [], [], "Disable">,
-  BothFlags<[], [ClangOption], " compile-time constant NSArray literals">>;
+  BothFlags<[NoArgumentUnused], [ClangOption], " compile-time constant NSArray literals">>;
 defm constant_nsdictionary_literals : BoolFOption<"constant-nsdictionary-literals",
   LangOpts<"ConstantNSDictionaryLiterals">, DefaultFalse,
   PosFlag<SetTrue, [], [CC1Option], "Enable">,
   NegFlag<SetFalse, [], [], "Disable">,
-  BothFlags<[], [ClangOption], " compile-time constant NSDictionary literals">>;
+  BothFlags<[NoArgumentUnused], [ClangOption], " compile-time constant NSDictionary literals">>;
 def fno_common : Flag<["-"], "fno-common">, Group<f_Group>,
   Visibility<[ClangOption, CC1Option]>,
     HelpText<"Compile common globals like normal definitions">;

diff  --git a/clang/test/Driver/objc-constant-literals.m b/clang/test/Driver/objc-constant-literals.m
index 7903028d00541..aec39918d5feb 100644
--- a/clang/test/Driver/objc-constant-literals.m
+++ b/clang/test/Driver/objc-constant-literals.m
@@ -19,3 +19,32 @@
 // DISABLED-NOT: -fconstant-nsnumber-literals
 // DISABLED-NOT: -fconstant-nsarray-literals
 // DISABLED-NOT: -fconstant-nsdictionary-literals
+
+// The constant literal flags are Objective-C only. A build system may still
+// pass them uniformly to non-ObjC inputs (e.g. assembly files via a shared
+// response file); they carry NoArgumentUnused so they don't trigger
+// -Wunused-command-line-argument under -Werror.
+// RUN: %clang -target arm64-apple-macosx11 -Werror \
+// RUN:   -fobjc-constant-literals -fconstant-nsnumber-literals \
+// RUN:   -fconstant-nsarray-literals -fconstant-nsdictionary-literals \
+// RUN:   -x assembler -c %s -o /dev/null 2>&1 \
+// RUN:   | FileCheck %s --check-prefix=IGNORED --allow-empty
+// RUN: %clang -target arm64-apple-macosx11 -Werror \
+// RUN:   -fno-objc-constant-literals -fno-constant-nsnumber-literals \
+// RUN:   -fno-constant-nsarray-literals -fno-constant-nsdictionary-literals \
+// RUN:   -x assembler -c %s -o /dev/null 2>&1 \
+// RUN:   | FileCheck %s --check-prefix=IGNORED --allow-empty
+
+// IGNORED-NOT: argument unused during compilation
+// IGNORED-NOT: -fobjc-constant-literals
+// IGNORED-NOT: -fconstant-nsnumber-literals
+// IGNORED-NOT: -fconstant-nsarray-literals
+// IGNORED-NOT: -fconstant-nsdictionary-literals
+
+// The same flags must also be ignored (and not forwarded to cc1) when compiling
+// non-ObjC C/C++ inputs.
+// RUN: %clang -target arm64-apple-macosx11 -Werror \
+// RUN:   -fobjc-constant-literals -fconstant-nsnumber-literals \
+// RUN:   -fconstant-nsarray-literals -fconstant-nsdictionary-literals \
+// RUN:   -x c++ -c %s -o /dev/null 2>&1 \
+// RUN:   | FileCheck %s --check-prefix=IGNORED --allow-empty

diff  --git a/lldb/source/Plugins/Process/Windows/Common/CMakeLists.txt b/lldb/source/Plugins/Process/Windows/Common/CMakeLists.txt
index 9854b79fbb8d6..bd076d5d64df1 100644
--- a/lldb/source/Plugins/Process/Windows/Common/CMakeLists.txt
+++ b/lldb/source/Plugins/Process/Windows/Common/CMakeLists.txt
@@ -1,5 +1,6 @@
 
 add_lldb_library(lldbPluginProcessWindowsCommon PLUGIN
+  IOHandlerProcessSTDIOWindows.cpp
   DebuggerThread.cpp
   LocalDebugDelegate.cpp
   NativeProcessWindows.cpp

diff  --git a/lldb/source/Plugins/Process/Windows/Common/IOHandlerProcessSTDIOWindows.cpp b/lldb/source/Plugins/Process/Windows/Common/IOHandlerProcessSTDIOWindows.cpp
new file mode 100644
index 0000000000000..2b9ab9ce0812b
--- /dev/null
+++ b/lldb/source/Plugins/Process/Windows/Common/IOHandlerProcessSTDIOWindows.cpp
@@ -0,0 +1,172 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "IOHandlerProcessSTDIOWindows.h"
+
+#include "lldb/Host/windows/windows.h"
+#include "lldb/Utility/LLDBLog.h"
+#include "lldb/Utility/Log.h"
+#include "lldb/Utility/State.h"
+
+using namespace lldb_private;
+
+IOHandlerProcessSTDIOWindows::IOHandlerProcessSTDIOWindows(Process *process)
+    : IOHandler(process->GetTarget().GetDebugger(), IOHandler::Type::ProcessIO),
+      m_process(process),
+      m_read_file(GetInputFD(), File::eOpenOptionReadOnly, false),
+      m_interrupt_event(
+          CreateEvent(/*lpEventAttributes=*/nullptr, /*bManualReset=*/FALSE,
+                      /*bInitialState=*/FALSE, /*lpName=*/nullptr)) {}
+
+IOHandlerProcessSTDIOWindows::~IOHandlerProcessSTDIOWindows() {
+  if (m_interrupt_event != INVALID_HANDLE_VALUE)
+    ::CloseHandle(m_interrupt_event);
+}
+
+void IOHandlerProcessSTDIOWindows::SetIsRunning(bool running) {
+  std::lock_guard<std::mutex> guard(m_mutex);
+  SetIsDone(!running);
+  m_is_running = running;
+}
+
+/// Peek the console for input. If it has any, drain the pipe until text input
+/// is found or the pipe is empty.
+///
+/// \param hStdin
+///     The handle to the standard input's pipe.
+///
+/// \return
+///     true if the pipe has text input.
+llvm::Expected<bool>
+IOHandlerProcessSTDIOWindows::ConsoleHasTextInput(const HANDLE hStdin) {
+  // Check if there are already characters buffered. Pressing enter counts as
+  // 2 characters '\r\n' and only one of them is a keyDown event.
+  DWORD bytesAvailable = 0;
+  if (PeekNamedPipe(hStdin, nullptr, 0, nullptr, &bytesAvailable, nullptr)) {
+    if (bytesAvailable > 0)
+      return true;
+  }
+
+  while (true) {
+    INPUT_RECORD inputRecord;
+    DWORD numRead = 0;
+    if (!PeekConsoleInput(hStdin, &inputRecord, 1, &numRead))
+      return llvm::createStringError("failed to peek standard input");
+
+    if (numRead == 0)
+      return false;
+
+    if (inputRecord.EventType == KEY_EVENT &&
+        inputRecord.Event.KeyEvent.bKeyDown &&
+        inputRecord.Event.KeyEvent.uChar.AsciiChar != 0)
+      return true;
+
+    if (!ReadConsoleInput(hStdin, &inputRecord, 1, &numRead))
+      return llvm::createStringError("failed to read standard input");
+  }
+}
+
+void IOHandlerProcessSTDIOWindows::Run() {
+  if (!m_read_file.IsValid()) {
+    SetIsDone(true);
+    return;
+  }
+
+  SetIsDone(false);
+  SetIsRunning(true);
+
+  HANDLE hStdin = m_read_file.GetWaitableHandle();
+  HANDLE waitHandles[2] = {hStdin, m_interrupt_event};
+
+  DWORD consoleMode;
+  bool isConsole = GetConsoleMode(hStdin, &consoleMode) != 0;
+  // With ENABLE_LINE_INPUT, ReadFile returns only when a carriage return is
+  // read. This will block lldb in ReadFile until the user hits enter. Save
+  // the previous console mode to restore it later and remove
+  // ENABLE_LINE_INPUT.
+  DWORD oldConsoleMode = consoleMode;
+  SetConsoleMode(hStdin, consoleMode & ~ENABLE_LINE_INPUT & ~ENABLE_ECHO_INPUT);
+
+  while (true) {
+    {
+      std::lock_guard<std::mutex> guard(m_mutex);
+      if (GetIsDone())
+        goto exit_loop;
+    }
+
+    DWORD result = WaitForMultipleObjects(2, waitHandles, FALSE, INFINITE);
+    switch (result) {
+    case WAIT_FAILED:
+      goto exit_loop;
+    case WAIT_OBJECT_0: {
+      if (isConsole) {
+        auto hasInputOrErr = ConsoleHasTextInput(hStdin);
+        if (!hasInputOrErr) {
+          Log *log = GetLog(LLDBLog::Process);
+          LLDB_LOG_ERROR(log, hasInputOrErr.takeError(),
+                         "failed to process debuggee's IO: {0}");
+          goto exit_loop;
+        }
+
+        // If no text input is ready, go back to waiting.
+        if (!*hasInputOrErr)
+          continue;
+      }
+
+      char ch = 0;
+      DWORD read = 0;
+      if (!ReadFile(hStdin, &ch, 1, &read, nullptr) || read != 1)
+        goto exit_loop;
+
+      Status err;
+      m_process->PutSTDIN(&ch, 1, err);
+      if (err.Fail())
+        goto exit_loop;
+      break;
+    }
+    case WAIT_OBJECT_0 + 1: {
+      ControlOp op = m_pending_op.exchange(eControlOpNone);
+      if (op == eControlOpQuit)
+        goto exit_loop;
+      if (op == eControlOpInterrupt &&
+          StateIsRunningState(m_process->GetState()))
+        m_process->SendAsyncInterrupt();
+      break;
+    }
+    default:
+      goto exit_loop;
+    }
+  }
+
+exit_loop:;
+  SetIsRunning(false);
+  SetIsDone(true);
+  SetConsoleMode(hStdin, oldConsoleMode);
+}
+
+void IOHandlerProcessSTDIOWindows::Cancel() {
+  std::lock_guard<std::mutex> guard(m_mutex);
+  SetIsDone(true);
+  if (m_is_running) {
+    m_pending_op.store(eControlOpQuit);
+    ::SetEvent(m_interrupt_event);
+  }
+}
+
+bool IOHandlerProcessSTDIOWindows::Interrupt() {
+  if (m_active) {
+    m_pending_op.store(eControlOpInterrupt);
+    ::SetEvent(m_interrupt_event);
+    return true;
+  }
+  if (StateIsRunningState(m_process->GetState())) {
+    m_process->SendAsyncInterrupt();
+    return true;
+  }
+  return false;
+}

diff  --git a/lldb/source/Plugins/Process/Windows/Common/IOHandlerProcessSTDIOWindows.h b/lldb/source/Plugins/Process/Windows/Common/IOHandlerProcessSTDIOWindows.h
new file mode 100644
index 0000000000000..79a414eeda12f
--- /dev/null
+++ b/lldb/source/Plugins/Process/Windows/Common/IOHandlerProcessSTDIOWindows.h
@@ -0,0 +1,63 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LIBLLDB_PLUGINS_PROCESS_WINDOWS_COMMON_IO_HANDLER_PROCESS_STDIO_WINDOWS_H_
+#define LIBLLDB_PLUGINS_PROCESS_WINDOWS_COMMON_IO_HANDLER_PROCESS_STDIO_WINDOWS_H_
+
+#include "lldb/Core/IOHandler.h"
+#include "lldb/Host/File.h"
+#include "lldb/Target/Process.h"
+
+using HANDLE = void *;
+
+using namespace lldb_private;
+
+class IOHandlerProcessSTDIOWindows : public IOHandler {
+public:
+  IOHandlerProcessSTDIOWindows(Process *process);
+
+  ~IOHandlerProcessSTDIOWindows() override;
+
+  void SetIsRunning(bool running);
+
+  /// Peek the console for input. If it has any, drain the pipe until text input
+  /// is found or the pipe is empty.
+  ///
+  /// \param hStdin
+  ///     The handle to the standard input's pipe.
+  ///
+  /// \return
+  ///     true if the pipe has text input.
+  llvm::Expected<bool> ConsoleHasTextInput(const HANDLE hStdin);
+
+  void Run() override;
+
+  void Cancel() override;
+
+  bool Interrupt() override;
+
+  void GotEOF() override {}
+
+private:
+  enum ControlOp : char {
+    eControlOpQuit = 'q',
+    eControlOpInterrupt = 'i',
+    eControlOpNone = 0,
+  };
+
+  Process *m_process;
+  /// Read from this file (usually actual STDIN for LLDB)
+  NativeFile m_read_file;
+  HANDLE m_interrupt_event =
+      reinterpret_cast<HANDLE>(static_cast<intptr_t>(-1));
+  std::atomic<ControlOp> m_pending_op{eControlOpNone};
+  std::mutex m_mutex;
+  bool m_is_running = false;
+};
+
+#endif // LIBLLDB_PLUGINS_PROCESS_WINDOWS_COMMON_IO_HANDLER_PROCESS_STDIO_WINDOWS_H_

diff  --git a/lldb/source/Plugins/Process/Windows/Common/ProcessWindows.cpp b/lldb/source/Plugins/Process/Windows/Common/ProcessWindows.cpp
index 9a273463792ce..941c25e9ecb77 100644
--- a/lldb/source/Plugins/Process/Windows/Common/ProcessWindows.cpp
+++ b/lldb/source/Plugins/Process/Windows/Common/ProcessWindows.cpp
@@ -44,6 +44,7 @@
 #include "DebuggerThread.h"
 #include "ExceptionRecord.h"
 #include "ForwardDecl.h"
+#include "IOHandlerProcessSTDIOWindows.h"
 #include "LocalDebugDelegate.h"
 #include "ProcessWindowsLog.h"
 #include "TargetThreadWindows.h"
@@ -1084,184 +1085,15 @@ Status ProcessWindows::DisableWatchpoint(WatchpointSP wp_sp, bool notify) {
   return error;
 }
 
-class IOHandlerProcessSTDIOWindows : public IOHandler {
-public:
-  IOHandlerProcessSTDIOWindows(Process *process, HANDLE conpty_input)
-      : IOHandler(process->GetTarget().GetDebugger(),
-                  IOHandler::Type::ProcessIO),
-        m_process(process),
-        m_read_file(GetInputFD(), File::eOpenOptionReadOnly, false),
-        m_write_file(conpty_input),
-        m_interrupt_event(
-            CreateEvent(/*lpEventAttributes=*/nullptr, /*bManualReset=*/FALSE,
-                        /*bInitialState=*/FALSE, /*lpName=*/nullptr)) {}
-
-  ~IOHandlerProcessSTDIOWindows() override {
-    if (m_interrupt_event != INVALID_HANDLE_VALUE)
-      ::CloseHandle(m_interrupt_event);
+size_t ProcessWindows::PutSTDIN(const char *src, size_t src_len,
+                                Status &error) {
+  if (!m_stdio_communication.IsConnected()) {
+    error = Status::FromErrorString("stdin not connected");
+    return 0;
   }
-
-  void SetIsRunning(bool running) {
-    std::lock_guard<std::mutex> guard(m_mutex);
-    SetIsDone(!running);
-    m_is_running = running;
-  }
-
-  /// Peek the console for input. If it has any, drain the pipe until text input
-  /// is found or the pipe is empty.
-  ///
-  /// \param hStdin
-  ///     The handle to the standard input's pipe.
-  ///
-  /// \return
-  ///     true if the pipe has text input.
-  llvm::Expected<bool> ConsoleHasTextInput(const HANDLE hStdin) {
-    // Check if there are already characters buffered. Pressing enter counts as
-    // 2 characters '\r\n' and only one of them is a keyDown event.
-    DWORD bytesAvailable = 0;
-    if (PeekNamedPipe(hStdin, nullptr, 0, nullptr, &bytesAvailable, nullptr)) {
-      if (bytesAvailable > 0)
-        return true;
-    }
-
-    while (true) {
-      INPUT_RECORD inputRecord;
-      DWORD numRead = 0;
-      if (!PeekConsoleInput(hStdin, &inputRecord, 1, &numRead))
-        return llvm::createStringError("failed to peek standard input");
-
-      if (numRead == 0)
-        return false;
-
-      if (inputRecord.EventType == KEY_EVENT &&
-          inputRecord.Event.KeyEvent.bKeyDown &&
-          inputRecord.Event.KeyEvent.uChar.AsciiChar != 0)
-        return true;
-
-      if (!ReadConsoleInput(hStdin, &inputRecord, 1, &numRead))
-        return llvm::createStringError("failed to read standard input");
-    }
-  }
-
-  void Run() override {
-    if (!m_read_file.IsValid() || m_write_file == INVALID_HANDLE_VALUE) {
-      SetIsDone(true);
-      return;
-    }
-
-    SetIsDone(false);
-    SetIsRunning(true);
-
-    HANDLE hStdin = m_read_file.GetWaitableHandle();
-    HANDLE waitHandles[2] = {hStdin, m_interrupt_event};
-
-    DWORD consoleMode;
-    bool isConsole = GetConsoleMode(hStdin, &consoleMode) != 0;
-    // With ENABLE_LINE_INPUT, ReadFile returns only when a carriage return is
-    // read. This will block lldb in ReadFile until the user hits enter. Save
-    // the previous console mode to restore it later and remove
-    // ENABLE_LINE_INPUT.
-    DWORD oldConsoleMode = consoleMode;
-    SetConsoleMode(hStdin,
-                   consoleMode & ~ENABLE_LINE_INPUT & ~ENABLE_ECHO_INPUT);
-
-    while (true) {
-      {
-        std::lock_guard<std::mutex> guard(m_mutex);
-        if (GetIsDone())
-          goto exit_loop;
-      }
-
-      DWORD result = WaitForMultipleObjects(2, waitHandles, FALSE, INFINITE);
-      switch (result) {
-      case WAIT_FAILED:
-        goto exit_loop;
-      case WAIT_OBJECT_0: {
-        if (isConsole) {
-          auto hasInputOrErr = ConsoleHasTextInput(hStdin);
-          if (!hasInputOrErr) {
-            Log *log = GetLog(WindowsLog::Process);
-            LLDB_LOG_ERROR(log, hasInputOrErr.takeError(),
-                           "failed to process debuggee's IO: {0}");
-            goto exit_loop;
-          }
-
-          // If no text input is ready, go back to waiting.
-          if (!*hasInputOrErr)
-            continue;
-        }
-
-        char ch = 0;
-        DWORD read = 0;
-        if (!ReadFile(hStdin, &ch, 1, &read, nullptr) || read != 1)
-          goto exit_loop;
-
-        DWORD written = 0;
-        if (!WriteFile(m_write_file, &ch, 1, &written, nullptr) || written != 1)
-          goto exit_loop;
-        break;
-      }
-      case WAIT_OBJECT_0 + 1: {
-        ControlOp op = m_pending_op.exchange(eControlOpNone);
-        if (op == eControlOpQuit)
-          goto exit_loop;
-        if (op == eControlOpInterrupt &&
-            StateIsRunningState(m_process->GetState()))
-          m_process->SendAsyncInterrupt();
-        break;
-      }
-      default:
-        goto exit_loop;
-      }
-    }
-
-  exit_loop:;
-    SetIsRunning(false);
-    SetIsDone(true);
-    SetConsoleMode(hStdin, oldConsoleMode);
-  }
-
-  void Cancel() override {
-    std::lock_guard<std::mutex> guard(m_mutex);
-    SetIsDone(true);
-    if (m_is_running) {
-      m_pending_op.store(eControlOpQuit);
-      ::SetEvent(m_interrupt_event);
-    }
-  }
-
-  bool Interrupt() override {
-    if (m_active) {
-      m_pending_op.store(eControlOpInterrupt);
-      ::SetEvent(m_interrupt_event);
-      return true;
-    }
-    if (StateIsRunningState(m_process->GetState())) {
-      m_process->SendAsyncInterrupt();
-      return true;
-    }
-    return false;
-  }
-
-  void GotEOF() override {}
-
-private:
-  enum ControlOp : char {
-    eControlOpQuit = 'q',
-    eControlOpInterrupt = 'i',
-    eControlOpNone = 0,
-  };
-
-  Process *m_process;
-  /// Read from this file (usually actual STDIN for LLDB)
-  NativeFile m_read_file;
-  /// Write to this file (usually the primary pty for getting io to debuggee)
-  HANDLE m_write_file = INVALID_HANDLE_VALUE;
-  HANDLE m_interrupt_event = INVALID_HANDLE_VALUE;
-  std::atomic<ControlOp> m_pending_op{eControlOpNone};
-  std::mutex m_mutex;
-  bool m_is_running = false;
-};
+  ConnectionStatus status;
+  return m_stdio_communication.WriteAll(src, src_len, status, &error);
+}
 
 void ProcessWindows::SetPseudoConsoleHandle() {
   if (m_pty == nullptr)
@@ -1277,8 +1109,8 @@ void ProcessWindows::SetPseudoConsoleHandle() {
     {
       std::lock_guard<std::mutex> guard(m_process_input_reader_mutex);
       if (!m_process_input_reader)
-        m_process_input_reader = std::make_shared<IOHandlerProcessSTDIOWindows>(
-            this, m_pty->GetSTDINHandle());
+        m_process_input_reader =
+            std::make_shared<IOHandlerProcessSTDIOWindows>(this);
     }
   }
 }

diff  --git a/lldb/source/Plugins/Process/Windows/Common/ProcessWindows.h b/lldb/source/Plugins/Process/Windows/Common/ProcessWindows.h
index da35ae923dcee..677ade4971eed 100644
--- a/lldb/source/Plugins/Process/Windows/Common/ProcessWindows.h
+++ b/lldb/source/Plugins/Process/Windows/Common/ProcessWindows.h
@@ -113,6 +113,8 @@ class ProcessWindows : public Process, public ProcessDebugger {
   /// buffered in the ConPTY/pipe to the process's STDOUT cache.
   void DrainProcessStdout();
 
+  size_t PutSTDIN(const char *src, size_t src_len, Status &error) override;
+
   ProcessWindows(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp);
 
   Status DoGetMemoryRegionInfo(lldb::addr_t vm_addr,

diff  --git a/lldb/test/API/tools/lldb-server/TestGdbRemote_qThreadStopInfo.py b/lldb/test/API/tools/lldb-server/TestGdbRemote_qThreadStopInfo.py
index 957404f257f15..d373b60c8b7d3 100644
--- a/lldb/test/API/tools/lldb-server/TestGdbRemote_qThreadStopInfo.py
+++ b/lldb/test/API/tools/lldb-server/TestGdbRemote_qThreadStopInfo.py
@@ -66,7 +66,6 @@ def test_qThreadStopInfo_works_for_multiple_threads(self):
 
     @expectedFailureAll(oslist=["freebsd"], bugnumber="llvm.org/pr48418")
     @expectedFailureNetBSD
-    @expectedFailureAll(oslist=["windows"])  # Output forwarding not implemented
     def test_qThreadStopInfo_only_reports_one_thread_stop_reason_during_interrupt(self):
         self.build()
         self.set_inferior_startup_launch()

diff  --git a/llvm/cmake/modules/HandleLLVMOptions.cmake b/llvm/cmake/modules/HandleLLVMOptions.cmake
index 75bd8ed11e1ba..e14fd9e931810 100644
--- a/llvm/cmake/modules/HandleLLVMOptions.cmake
+++ b/llvm/cmake/modules/HandleLLVMOptions.cmake
@@ -700,7 +700,8 @@ if( MSVC )
     has_msvc_incremental_no_flag("${CMAKE_MODULE_LINKER_FLAGS_${uppercase_CMAKE_BUILD_TYPE}} ${CMAKE_MODULE_LINKER_FLAGS}" NO_INCR_MODULE)
     has_msvc_incremental_no_flag("${CMAKE_SHARED_LINKER_FLAGS_${uppercase_CMAKE_BUILD_TYPE}} ${CMAKE_SHARED_LINKER_FLAGS}" NO_INCR_SHARED)
     if (NO_INCR_EXE AND NO_INCR_MODULE AND NO_INCR_SHARED)
-      append("/Brepro" CMAKE_C_FLAGS CMAKE_CXX_FLAGS)
+      # The /Brepro flag in `clang-cl` omits the timestamp for .obj files while the linker flag omits the timestamp for .exe and .dll files.
+      append("/Brepro" CMAKE_C_FLAGS CMAKE_CXX_FLAGS CMAKE_EXE_LINKER_FLAGS CMAKE_MODULE_LINKER_FLAGS CMAKE_SHARED_LINKER_FLAGS)
     else()
       message(WARNING "/Brepro not compatible with /INCREMENTAL linking - builds will be non-deterministic")
     endif()

diff  --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.td b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
index 151cbd9bc5a7c..200808665c93e 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
@@ -6696,8 +6696,13 @@ defm UQXTN  : SIMDTwoScalarMixedBHS<1, 0b10100, "uqxtn", int_aarch64_neon_scalar
 defm USQADD : SIMDTwoScalarBHSDTied< 1, 0b00011, "usqadd", AArch64usqadd,
                                     int_aarch64_neon_usqadd>;
 
+// Scalar i32 -> i64 extend
 def : Pat<(i32 (int_aarch64_neon_scalar_uqxtn (i64 FPR64:$Rn))),
           (i32 (UQXTNv1i32 FPR64:$Rn))>;
+def : Pat<(i32 (int_aarch64_neon_scalar_sqxtn (i64 FPR64:$Rn))),
+          (i32 (SQXTNv1i32 FPR64:$Rn))>;
+def : Pat<(i32 (int_aarch64_neon_scalar_sqxtun (i64 FPR64:$Rn))),
+          (i32 (SQXTUNv1i32 FPR64:$Rn))>;
 
 // ssub_sat(0, R) -> sqneg(R)
 def : Pat<(v16i8 (ssubsat immAllZerosV, V128:$reg)),

diff  --git a/llvm/lib/Target/AArch64/GISel/AArch64RegisterBankInfo.cpp b/llvm/lib/Target/AArch64/GISel/AArch64RegisterBankInfo.cpp
index ee9e57e705750..4767493e107b4 100644
--- a/llvm/lib/Target/AArch64/GISel/AArch64RegisterBankInfo.cpp
+++ b/llvm/lib/Target/AArch64/GISel/AArch64RegisterBankInfo.cpp
@@ -654,6 +654,8 @@ static bool isFPIntrinsic(const MachineRegisterInfo &MRI,
   case Intrinsic::aarch64_neon_sqneg:
   case Intrinsic::aarch64_neon_sqabs:
   case Intrinsic::aarch64_neon_scalar_uqxtn:
+  case Intrinsic::aarch64_neon_scalar_sqxtn:
+  case Intrinsic::aarch64_neon_scalar_sqxtun:
   case Intrinsic::aarch64_crypto_sha1h:
   case Intrinsic::aarch64_crypto_sha1c:
   case Intrinsic::aarch64_crypto_sha1p:

diff  --git a/llvm/lib/Target/AMDGPU/MIMGInstructions.td b/llvm/lib/Target/AMDGPU/MIMGInstructions.td
index 0f31697f15688..90764c1a7850b 100644
--- a/llvm/lib/Target/AMDGPU/MIMGInstructions.td
+++ b/llvm/lib/Target/AMDGPU/MIMGInstructions.td
@@ -2183,8 +2183,8 @@ class VIMAGE_TENSOR_Pseudo<string opName, bit _UpTo2D = 0> :
 
   bit UpTo2D = _UpTo2D;
   let InOperandList = !if(UpTo2D, (ins SReg_128_XNULL:$vaddr0, SReg_256_XNULL:$vaddr1, R128A16:$r128, CPol:$cpol),
-                                      (ins SReg_128_XNULL:$vaddr0, SReg_256_XNULL:$vaddr1, SReg_128_XNULL:$vaddr2,
-                                       SReg_128_XNULL:$vaddr3, R128A16:$r128, CPol:$cpol));
+                                      (ins SReg_128_XNULL:$vaddr0, SReg_256_XNULL:$vaddr1, SReg_128:$vaddr2,
+                                       SReg_128:$vaddr3, R128A16:$r128, CPol:$cpol));
   string AsmOperands = " $vaddr0, $vaddr1"#!if(UpTo2D, "", ", $vaddr2, $vaddr3")#"$r128$cpol";
 }
 

diff  --git a/llvm/lib/Target/SPIRV/SPIRVNonSemanticDebugHandler.cpp b/llvm/lib/Target/SPIRV/SPIRVNonSemanticDebugHandler.cpp
index a6c647eddcd04..de2dc8d17a4ad 100644
--- a/llvm/lib/Target/SPIRV/SPIRVNonSemanticDebugHandler.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVNonSemanticDebugHandler.cpp
@@ -14,15 +14,126 @@
 #include "llvm/ADT/SmallVectorExtras.h"
 #include "llvm/BinaryFormat/Dwarf.h"
 #include "llvm/CodeGen/AsmPrinter.h"
+#include "llvm/IR/DebugInfo.h"
 #include "llvm/IR/DebugInfoMetadata.h"
-#include "llvm/IR/DebugProgramInstruction.h"
 #include "llvm/IR/Module.h"
 #include "llvm/MC/MCInst.h"
 #include "llvm/MC/MCStreamer.h"
+#include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/Path.h"
+#include <cassert>
 
 using namespace llvm;
 
+namespace {
+
+/// Partition \p Ty into \p BasicTypes, \p PointerTypes, and \p SubroutineTypes
+/// for NSDI emission. Used when iterating DebugInfoFinder.types(); each DI
+/// node is seen once, so no recursion into pointer bases. Other composites and
+/// non-pointer derived kinds are ignored because they are not yet supported.
+/// Only types that are supported (later used) are partitioned.
+static void
+partitionTypes(const DIType *Ty, SmallVector<const DIBasicType *> &BasicTypes,
+               SmallVector<const DIDerivedType *> &PointerTypes,
+               SmallVector<const DISubroutineType *> &SubroutineTypes) {
+  if (const auto *BT = dyn_cast<DIBasicType>(Ty)) {
+    BasicTypes.push_back(BT);
+    return;
+  }
+  if (const auto *ST = dyn_cast<DISubroutineType>(Ty)) {
+    SubroutineTypes.push_back(ST);
+    return;
+  }
+  const auto *DT = dyn_cast<DIDerivedType>(Ty);
+  if (DT && DT->getTag() == dwarf::DW_TAG_pointer_type)
+    PointerTypes.push_back(DT);
+}
+
+enum : uint32_t {
+  NSDIFlagIsProtected = 1u << 0,
+  NSDIFlagIsPrivate = 1u << 1,
+  NSDIFlagIsPublic = NSDIFlagIsPrivate | NSDIFlagIsProtected,
+  NSDIFlagIsLocal = 1u << 2,
+  NSDIFlagIsDefinition = 1u << 3,
+  NSDIFlagFwdDecl = 1u << 4,
+  NSDIFlagArtificial = 1u << 5,
+  NSDIFlagExplicit = 1u << 6,
+  NSDIFlagPrototyped = 1u << 7,
+  NSDIFlagObjectPointer = 1u << 8,
+  NSDIFlagStaticMember = 1u << 9,
+  NSDIFlagIndirectVariable = 1u << 10,
+  NSDIFlagLValueReference = 1u << 11,
+  NSDIFlagRValueReference = 1u << 12,
+  NSDIFlagIsOptimized = 1u << 13,
+  NSDIFlagIsEnumClass = 1u << 14,
+  NSDIFlagTypePassByValue = 1u << 15,
+  NSDIFlagTypePassByReference = 1u << 16,
+  NSDIFlagUnknownPhysicalLayout = 1u << 17,
+};
+
+static uint32_t mapDIFlagsToNonSemantic(DINode::DIFlags DFlags) {
+  uint32_t Flags = 0;
+  if ((DFlags & DINode::FlagAccessibility) == DINode::FlagPublic)
+    Flags |= NSDIFlagIsPublic;
+  if ((DFlags & DINode::FlagAccessibility) == DINode::FlagProtected)
+    Flags |= NSDIFlagIsProtected;
+  if ((DFlags & DINode::FlagAccessibility) == DINode::FlagPrivate)
+    Flags |= NSDIFlagIsPrivate;
+  if (DFlags & DINode::FlagFwdDecl)
+    Flags |= NSDIFlagFwdDecl;
+  if (DFlags & DINode::FlagArtificial)
+    Flags |= NSDIFlagArtificial;
+  if (DFlags & DINode::FlagExplicit)
+    Flags |= NSDIFlagExplicit;
+  if (DFlags & DINode::FlagPrototyped)
+    Flags |= NSDIFlagPrototyped;
+  if (DFlags & DINode::FlagObjectPointer)
+    Flags |= NSDIFlagObjectPointer;
+  if (DFlags & DINode::FlagStaticMember)
+    Flags |= NSDIFlagStaticMember;
+  if (DFlags & DINode::FlagLValueReference)
+    Flags |= NSDIFlagLValueReference;
+  if (DFlags & DINode::FlagRValueReference)
+    Flags |= NSDIFlagRValueReference;
+  if (DFlags & DINode::FlagTypePassByValue)
+    Flags |= NSDIFlagTypePassByValue;
+  if (DFlags & DINode::FlagTypePassByReference)
+    Flags |= NSDIFlagTypePassByReference;
+  if (DFlags & DINode::FlagEnumClass)
+    Flags |= NSDIFlagIsEnumClass;
+  return Flags;
+}
+
+static uint32_t transDebugFlags(const DINode *DN) {
+  uint32_t Flags = 0;
+  if (const auto *GV = dyn_cast<DIGlobalVariable>(DN)) {
+    if (GV->isLocalToUnit())
+      Flags |= NSDIFlagIsLocal;
+    if (GV->isDefinition())
+      Flags |= NSDIFlagIsDefinition;
+  }
+  if (const auto *SP = dyn_cast<DISubprogram>(DN)) {
+    if (SP->isLocalToUnit())
+      Flags |= NSDIFlagIsLocal;
+    if (SP->isOptimized())
+      Flags |= NSDIFlagIsOptimized;
+    if (SP->isDefinition())
+      Flags |= NSDIFlagIsDefinition;
+    Flags |= mapDIFlagsToNonSemantic(SP->getFlags());
+  }
+  if (DN->getTag() == dwarf::DW_TAG_reference_type)
+    Flags |= NSDIFlagLValueReference;
+  if (DN->getTag() == dwarf::DW_TAG_rvalue_reference_type)
+    Flags |= NSDIFlagRValueReference;
+  if (const auto *Ty = dyn_cast<DIType>(DN))
+    Flags |= mapDIFlagsToNonSemantic(Ty->getFlags());
+  if (const auto *LV = dyn_cast<DILocalVariable>(DN))
+    Flags |= mapDIFlagsToNonSemantic(LV->getFlags());
+  return Flags;
+}
+
+} // namespace
+
 SPIRVNonSemanticDebugHandler::SPIRVNonSemanticDebugHandler(AsmPrinter &AP)
     : DebugHandlerBase(&AP) {}
 
@@ -58,6 +169,22 @@ void SPIRVNonSemanticDebugHandler::beginModule(Module *M) {
   if (!Asm)
     return;
 
+  CompileUnits.clear();
+  BasicTypes.clear();
+  PointerTypes.clear();
+  SubroutineTypes.clear();
+  DebugTypeRegs.clear();
+  OpStringContentCache.clear();
+  I32ConstantCache.clear();
+  DebugTypeFunctionCache.clear();
+  GlobalDIEmitted = false;
+#ifndef NDEBUG
+  NonSemanticOpStringsSectionEmitted = false;
+#endif
+  CachedDebugInfoNoneReg = MCRegister();
+  CachedOpTypeVoidReg = MCRegister();
+  CachedOpTypeInt32Reg = MCRegister();
+
   // Collect compile-unit info: file paths and source languages.
   for (const DICompileUnit *CU : M->debug_compile_units()) {
     const DIFile *File = CU->getFile();
@@ -87,27 +214,12 @@ void SPIRVNonSemanticDebugHandler::beginModule(Module *M) {
     }
   }
 
-  // Collect basic and pointer types referenced by debug variable records.
-  for (const auto &F : *M) {
-    for (const auto &BB : F) {
-      for (const auto &I : BB) {
-        for (const DbgVariableRecord &DVR :
-             filterDbgVars(I.getDbgRecordRange())) {
-          const DIType *Ty = DVR.getVariable()->getType();
-          if (const auto *BT = dyn_cast<DIBasicType>(Ty)) {
-            BasicTypes.insert(BT);
-          } else if (const auto *DT = dyn_cast<DIDerivedType>(Ty)) {
-            if (DT->getTag() == dwarf::DW_TAG_pointer_type) {
-              PointerTypes.insert(DT);
-              if (const auto *BT =
-                      dyn_cast_or_null<DIBasicType>(DT->getBaseType()))
-                BasicTypes.insert(BT);
-            }
-          }
-        }
-      }
-    }
-  }
+  // Find all debug info types that may be referenced by NSDI instructions.
+  DebugInfoFinder Finder;
+  Finder.processModule(*M);
+  llvm::for_each(Finder.types(), [&](DIType *Ty) {
+    partitionTypes(Ty, BasicTypes, PointerTypes, SubroutineTypes);
+  });
 }
 
 void SPIRVNonSemanticDebugHandler::prepareModuleOutput(
@@ -145,6 +257,31 @@ SPIRVNonSemanticDebugHandler::emitOpString(StringRef S,
   return Reg;
 }
 
+void SPIRVNonSemanticDebugHandler::emitOpStringIfNew(
+    StringRef S, SPIRV::ModuleAnalysisInfo &MAI) {
+#ifndef NDEBUG
+  assert(!NonSemanticOpStringsSectionEmitted &&
+         "emitOpStringIfNew is only valid while emitting SPIR-V section 7");
+#endif
+  auto [It, Inserted] = OpStringContentCache.try_emplace(S, MCRegister());
+  if (!Inserted)
+    return;
+
+  It->second = emitOpString(S, MAI);
+}
+
+MCRegister SPIRVNonSemanticDebugHandler::getCachedOpStringReg(StringRef S) {
+#ifndef NDEBUG
+  assert(NonSemanticOpStringsSectionEmitted &&
+         "getCachedOpStringReg requires emitNonSemanticDebugStrings() first");
+#endif
+  auto It = OpStringContentCache.find(S);
+  assert(It != OpStringContentCache.end() &&
+         "NSDI OpString missing from cache; emitNonSemanticDebugStrings must "
+         "cache every string used in section 10");
+  return It->second;
+}
+
 MCRegister SPIRVNonSemanticDebugHandler::emitOpConstantI32(
     uint32_t Value, MCRegister I32TypeReg, SPIRV::ModuleAnalysisInfo &MAI) {
   auto [It, Inserted] = I32ConstantCache.try_emplace(Value);
@@ -179,6 +316,34 @@ MCRegister SPIRVNonSemanticDebugHandler::emitExtInst(
   return Reg;
 }
 
+MCRegister SPIRVNonSemanticDebugHandler::getOrEmitDebugTypeFunction(
+    ArrayRef<MCRegister> Ops, MCRegister VoidTypeReg, MCRegister ExtInstSetReg,
+    SPIRV::ModuleAnalysisInfo &MAI) {
+  auto [It, Inserted] =
+      DebugTypeFunctionCache.try_emplace(SmallVector<MCRegister, 8>(Ops));
+  if (!Inserted)
+    return It->second;
+
+  MCRegister Reg = emitExtInst(SPIRV::NonSemanticExtInst::DebugTypeFunction,
+                               VoidTypeReg, ExtInstSetReg, Ops, MAI);
+  It->second = Reg;
+  return Reg;
+}
+
+MCRegister SPIRVNonSemanticDebugHandler::getOrEmitOpTypeVoidReg(
+    SPIRV::ModuleAnalysisInfo &MAI) {
+  if (!CachedOpTypeVoidReg.isValid())
+    CachedOpTypeVoidReg = findOrEmitOpTypeVoid(MAI);
+  return CachedOpTypeVoidReg;
+}
+
+MCRegister SPIRVNonSemanticDebugHandler::getOrEmitOpTypeInt32Reg(
+    SPIRV::ModuleAnalysisInfo &MAI) {
+  if (!CachedOpTypeInt32Reg.isValid())
+    CachedOpTypeInt32Reg = findOrEmitOpTypeInt32(MAI);
+  return CachedOpTypeInt32Reg;
+}
+
 MCRegister SPIRVNonSemanticDebugHandler::findOrEmitOpTypeVoid(
     SPIRV::ModuleAnalysisInfo &MAI) {
   for (const MachineInstr *MI : MAI.getMSInstrs(SPIRV::MB_TypeConstVars)) {
@@ -210,15 +375,18 @@ MCRegister SPIRVNonSemanticDebugHandler::findOrEmitOpTypeInt32(
   return Reg;
 }
 
-void SPIRVNonSemanticDebugHandler::emitDebugTypePointer(
-    const DIDerivedType *PT, MCRegister VoidTypeReg, MCRegister I32TypeReg,
-    MCRegister ExtInstSetReg, MCRegister I32ZeroReg,
-    const DenseMap<const DIBasicType *, MCRegister> &BasicTypeRegs,
+std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugTypePointer(
+    const DIDerivedType *PT, MCRegister ExtInstSetReg,
     SPIRV::ModuleAnalysisInfo &MAI) {
   // A DWARF address space is required to determine the SPIR-V storage class.
   // Skip pointer types that do not carry one.
   if (!PT->getDWARFAddressSpace().has_value())
-    return;
+    return std::nullopt;
+
+  MCRegister VoidTypeReg = getOrEmitOpTypeVoidReg(MAI);
+  MCRegister I32TypeReg = getOrEmitOpTypeInt32Reg(MAI);
+  MCRegister DebugTypePointerFlagsReg =
+      emitOpConstantI32(transDebugFlags(PT), I32TypeReg, MAI);
 
   // For SPIR-V targets, Clang sets DwarfAddressSpace to the LLVM IR address
   // space, which addressSpaceToStorageClass expects.
@@ -227,22 +395,69 @@ void SPIRVNonSemanticDebugHandler::emitDebugTypePointer(
       addressSpaceToStorageClass(PT->getDWARFAddressSpace().value(), ST),
       I32TypeReg, MAI);
 
-  if (const auto *BaseType = dyn_cast_or_null<DIBasicType>(PT->getBaseType())) {
-    auto BTIt = BasicTypeRegs.find(BaseType);
-    if (BTIt != BasicTypeRegs.end())
-      emitExtInst(SPIRV::NonSemanticExtInst::DebugTypePointer, VoidTypeReg,
-                  ExtInstSetReg, {BTIt->second, StorageClassReg, I32ZeroReg},
-                  MAI);
+  if (const DIType *BaseTy = PT->getBaseType()) {
+    auto BaseIt = DebugTypeRegs.find(BaseTy);
+    if (BaseIt != DebugTypeRegs.end())
+      return emitExtInst(
+          SPIRV::NonSemanticExtInst::DebugTypePointer, VoidTypeReg,
+          ExtInstSetReg,
+          {BaseIt->second, StorageClassReg, DebugTypePointerFlagsReg}, MAI);
+    // Unsupported type, no DebugType* id available.
+    return std::nullopt;
+  }
+  // No getBaseType() (typical for void*): use DebugInfoNone as Base Type,
+  // same as SPIRV-LLVM-Translator (see issue #109287 and the DISABLED
+  // spirv-val run in debug-type-pointer.ll). spirv-val may still reject this
+  // encoding; see https://github.com/KhronosGroup/SPIRV-Registry/pull/287.
+  return emitExtInst(
+      SPIRV::NonSemanticExtInst::DebugTypePointer, VoidTypeReg, ExtInstSetReg,
+      {CachedDebugInfoNoneReg, StorageClassReg, DebugTypePointerFlagsReg}, MAI);
+}
+
+std::optional<MCRegister>
+SPIRVNonSemanticDebugHandler::emitDebugTypeFunctionForSubroutineType(
+    const DISubroutineType *ST, MCRegister ExtInstSetReg,
+    SPIRV::ModuleAnalysisInfo &MAI) {
+  MCRegister VoidTypeReg = getOrEmitOpTypeVoidReg(MAI);
+  MCRegister I32TypeReg = getOrEmitOpTypeInt32Reg(MAI);
+  MCRegister DebugTypeFunctionFlagsReg =
+      emitOpConstantI32(transDebugFlags(ST), I32TypeReg, MAI);
+  DITypeArray TA = ST->getTypeArray();
+  SmallVector<MCRegister, 8> Ops;
+  Ops.push_back(DebugTypeFunctionFlagsReg);
+  // Empty DI type tuple: no explicit return or parameter slots (hand-written IR
+  // may use !{}). Emit void-only prototype. Same as SPIRV-LLVM-Translator when
+  // DISubroutineType::getTypeArray() has zero elements.
+  if (TA.empty()) {
+    Ops.push_back(VoidTypeReg);
   } else {
-    // Void pointer: use DebugInfoNone for the base type. Note that
-    // spirv-val currently rejects DebugInfoNone as the base type of
-    // DebugTypePointer; see issue #109287 and the DISABLED spirv-val run
-    // in debug-type-pointer.ll.
-    MCRegister NoneReg = emitExtInst(SPIRV::NonSemanticExtInst::DebugInfoNone,
-                                     VoidTypeReg, ExtInstSetReg, {}, MAI);
-    emitExtInst(SPIRV::NonSemanticExtInst::DebugTypePointer, VoidTypeReg,
-                ExtInstSetReg, {NoneReg, StorageClassReg, I32ZeroReg}, MAI);
+    for (unsigned I = 0, E = TA.size(); I != E; ++I) {
+      bool IsReturnType = (I == 0);
+      auto OptReg = mapDISignatureTypeToReg(TA[I], VoidTypeReg, IsReturnType);
+      // No emitted DebugType* id for this slot (e.g., pointer that
+      // was skipped due missing address space, etc.).
+      if (!OptReg)
+        return std::nullopt;
+      Ops.push_back(*OptReg);
+    }
   }
+  return getOrEmitDebugTypeFunction(Ops, VoidTypeReg, ExtInstSetReg, MAI);
+}
+
+std::optional<MCRegister> SPIRVNonSemanticDebugHandler::mapDISignatureTypeToReg(
+    const DIType *Ty, MCRegister VoidTypeReg, bool ReturnType) {
+  if (!Ty) {
+    if (ReturnType)
+      return VoidTypeReg;
+    assert(CachedDebugInfoNoneReg.isValid() &&
+           "DebugInfoNone must be emitted before DISubroutineType operands");
+    return CachedDebugInfoNoneReg;
+  }
+  auto It = DebugTypeRegs.find(Ty);
+  if (It != DebugTypeRegs.end())
+    return It->second;
+
+  return std::nullopt;
 }
 
 void SPIRVNonSemanticDebugHandler::emitNonSemanticDebugStrings(
@@ -258,10 +473,14 @@ void SPIRVNonSemanticDebugHandler::emitNonSemanticDebugStrings(
     return;
 
   for (const CompileUnitInfo &Info : CompileUnits)
-    FileStringRegs.push_back(emitOpString(Info.FilePath, MAI));
+    emitOpStringIfNew(Info.FilePath, MAI);
 
   for (const DIBasicType *BT : BasicTypes)
-    BasicTypeNameRegs.push_back(emitOpString(BT->getName(), MAI));
+    emitOpStringIfNew(BT->getName(), MAI);
+
+#ifndef NDEBUG
+  NonSemanticOpStringsSectionEmitted = true;
+#endif
 }
 
 void SPIRVNonSemanticDebugHandler::emitNonSemanticGlobalDebugInfo(
@@ -277,8 +496,17 @@ void SPIRVNonSemanticDebugHandler::emitNonSemanticGlobalDebugInfo(
   if (!ExtInstSetReg.isValid())
     return; // Extension not available.
 
-  MCRegister VoidTypeReg = findOrEmitOpTypeVoid(MAI);
-  MCRegister I32TypeReg = findOrEmitOpTypeInt32(MAI);
+#ifndef NDEBUG
+  assert(NonSemanticOpStringsSectionEmitted &&
+         "emitNonSemanticDebugStrings() must run before "
+         "emitNonSemanticGlobalDebugInfo()");
+#endif
+
+  MCRegister VoidTypeReg = getOrEmitOpTypeVoidReg(MAI);
+  MCRegister I32TypeReg = getOrEmitOpTypeInt32Reg(MAI);
+
+  CachedDebugInfoNoneReg = emitExtInst(SPIRV::NonSemanticExtInst::DebugInfoNone,
+                                       VoidTypeReg, ExtInstSetReg, {}, MAI);
 
   // Emit integer constants shared across all NSDI instructions. The constant
   // cache ensures each value is emitted at most once even when referenced from
@@ -302,11 +530,8 @@ void SPIRVNonSemanticDebugHandler::emitNonSemanticGlobalDebugInfo(
       });
 
   // Emit DebugSource and DebugCompilationUnit for each compile unit.
-  // FileStringRegs was populated by emitNonSemanticDebugStrings() in section 7.
-  assert(FileStringRegs.size() == CompileUnits.size() &&
-         "FileStringRegs must be populated by emitNonSemanticDebugStrings()");
-  for (auto [Info, FileStrReg, SrcLangReg] :
-       llvm::zip(CompileUnits, FileStringRegs, SrcLangRegs)) {
+  for (auto [Info, SrcLangReg] : llvm::zip(CompileUnits, SrcLangRegs)) {
+    MCRegister FileStrReg = getCachedOpStringReg(Info.FilePath);
     MCRegister DebugSourceReg =
         emitExtInst(SPIRV::NonSemanticExtInst::DebugSource, VoidTypeReg,
                     ExtInstSetReg, {FileStrReg}, MAI);
@@ -321,18 +546,10 @@ void SPIRVNonSemanticDebugHandler::emitNonSemanticGlobalDebugInfo(
   // DebugTypePointer. Cached with other i32 constants.
   MCRegister I32ZeroReg = emitOpConstantI32(0, I32TypeReg, MAI);
 
-  // Maps each DIBasicType to its DebugTypeBasic result register for use as
-  // operands in DebugTypePointer instructions.
-  DenseMap<const DIBasicType *, MCRegister> BasicTypeRegs;
+  DebugTypeRegs.clear();
 
-  // BasicTypeNameRegs was populated by emitNonSemanticDebugStrings() in
-  // section 7.
-  assert(
-      BasicTypeNameRegs.size() == BasicTypes.size() &&
-      "BasicTypeNameRegs must be populated by emitNonSemanticDebugStrings()");
-  unsigned BTIdx = 0;
   for (const DIBasicType *BT : BasicTypes) {
-    MCRegister NameReg = BasicTypeNameRegs[BTIdx++];
+    MCRegister NameReg = getCachedOpStringReg(BT->getName());
     MCRegister SizeReg = emitOpConstantI32(
         static_cast<uint32_t>(BT->getSizeInBits()), I32TypeReg, MAI);
 
@@ -367,11 +584,19 @@ void SPIRVNonSemanticDebugHandler::emitNonSemanticGlobalDebugInfo(
     MCRegister BTReg = emitExtInst(
         SPIRV::NonSemanticExtInst::DebugTypeBasic, VoidTypeReg, ExtInstSetReg,
         {NameReg, SizeReg, EncodingReg, I32ZeroReg}, MAI);
-    BasicTypeRegs[BT] = BTReg;
+    DebugTypeRegs[BT] = BTReg;
   }
 
   // Emit DebugTypePointer for each referenced pointer type.
-  for (const DIDerivedType *PT : PointerTypes)
-    emitDebugTypePointer(PT, VoidTypeReg, I32TypeReg, ExtInstSetReg, I32ZeroReg,
-                         BasicTypeRegs, MAI);
+  for (const DIDerivedType *PT : PointerTypes) {
+    if (auto PtrReg = emitDebugTypePointer(PT, ExtInstSetReg, MAI))
+      DebugTypeRegs[PT] = *PtrReg;
+  }
+
+  // Emit DebugTypeFunction for each distinct DISubroutineType.
+  for (const DISubroutineType *ST : SubroutineTypes) {
+    if (auto FnTyReg =
+            emitDebugTypeFunctionForSubroutineType(ST, ExtInstSetReg, MAI))
+      DebugTypeRegs[ST] = *FnTyReg;
+  }
 }

diff  --git a/llvm/lib/Target/SPIRV/SPIRVNonSemanticDebugHandler.h b/llvm/lib/Target/SPIRV/SPIRVNonSemanticDebugHandler.h
index 7d8bac0c5ab5a..b07e3f23a71af 100644
--- a/llvm/lib/Target/SPIRV/SPIRVNonSemanticDebugHandler.h
+++ b/llvm/lib/Target/SPIRV/SPIRVNonSemanticDebugHandler.h
@@ -21,13 +21,14 @@
 #include "MCTargetDesc/SPIRVBaseInfo.h"
 #include "SPIRVModuleAnalysis.h"
 #include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/SetVector.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringMap.h"
 #include "llvm/CodeGen/DebugHandlerBase.h"
 #include "llvm/IR/DebugInfoMetadata.h"
 #include "llvm/MC/MCInst.h"
 #include "llvm/MC/MCRegister.h"
+#include <optional>
 
 namespace llvm {
 
@@ -40,9 +41,10 @@ class SPIRVSubtarget;
 /// Call sequence:
 ///   beginModule()                    -- collect compile-unit metadata.
 ///   prepareModuleOutput()            -- add extension + ext inst set to MAI.
+///   emitNonSemanticDebugStrings()    -- OpString for NSDI strings (sec. 7).
 ///   emitNonSemanticGlobalDebugInfo() -- emit DebugSource,
 ///                                       DebugCompilationUnit, DebugTypeBasic,
-///                                       DebugTypePointer.
+///                                       DebugTypePointer, DebugTypeFunction.
 ///   beginFunctionImpl()              -- no-op (no per-function DI yet).
 ///   endFunctionImpl()                -- no-op.
 class SPIRVNonSemanticDebugHandler : public DebugHandlerBase {
@@ -58,21 +60,40 @@ class SPIRVNonSemanticDebugHandler : public DebugHandlerBase {
   SmallVector<CompileUnitInfo> CompileUnits;
   int64_t DwarfVersion = 0;
 
-  // Types referenced by debug variable records, collected in beginModule().
-  SetVector<const DIBasicType *> BasicTypes;
-  SetVector<const DIDerivedType *> PointerTypes;
+  // DI types partitioned from DebugInfoFinder.types() in beginModule()
+  // (basics, pointers, subroutine types NSDI v1 may emit).
+  SmallVector<const DIBasicType *> BasicTypes;
+  SmallVector<const DIDerivedType *> PointerTypes;
+  SmallVector<const DISubroutineType *> SubroutineTypes;
+
+  // Filled in emitNonSemanticGlobalDebugInfo(): DI types to their result
+  // registers.
+  DenseMap<const DIType *, MCRegister> DebugTypeRegs;
+
+  // Maps OpString contents to result id. Populated only by emitOpStringIfNew()
+  // during section 7; section 10 uses getCachedOpStringReg() (lookup only).
+  StringMap<MCRegister> OpStringContentCache;
+
+#ifndef NDEBUG // Only declare the variable for debugging purposes.
+  // True after emitNonSemanticDebugStrings() emitted the NSDI OpStrings for
+  // this module. SPIRVAsmPrinter calls that before
+  // emitNonSemanticGlobalDebugInfo().
+  bool NonSemanticOpStringsSectionEmitted = false;
+#endif
+
+  MCRegister CachedDebugInfoNoneReg;
+
+  MCRegister CachedOpTypeVoidReg;
+
+  MCRegister CachedOpTypeInt32Reg;
 
   // Cache of already-emitted i32 constants, keyed by value. Prevents
   // duplicate OpConstant instructions for the same integer value.
   DenseMap<uint32_t, MCRegister> I32ConstantCache;
 
-  // OpString registers for NSDI instructions, populated by
-  // emitNonSemanticDebugStrings() (section 7) and consumed by
-  // emitNonSemanticGlobalDebugInfo() (section 10). OpString must appear in
-  // section 7 per the SPIR-V module layout; it cannot be emitted alongside the
-  // OpExtInst instructions in section 10.
-  SmallVector<MCRegister> FileStringRegs;    // one per CompileUnits entry
-  SmallVector<MCRegister> BasicTypeNameRegs; // one per BasicTypes entry
+  // Cache of already-emitted DebugTypeFunction instructions, keyed by operand
+  // ids (flags, return type, parameters).
+  DenseMap<SmallVector<MCRegister, 8>, MCRegister> DebugTypeFunctionCache;
 
   // True once emitNonSemanticGlobalDebugInfo() has run. Both
   // SPIRVAsmPrinter::emitFunctionHeader() and emitEndOfAsmFile() may call
@@ -91,9 +112,9 @@ class SPIRVNonSemanticDebugHandler : public DebugHandlerBase {
   /// Emit OpString instructions for all NSDI file paths and basic type names
   /// into the debug section (section 7 of the SPIR-V module layout). Must be
   /// called from SPIRVAsmPrinter::outputDebugSourceAndStrings(), after
-  /// prepareModuleOutput() has registered the ext inst set. The resulting
-  /// registers are cached in FileStringRegs and BasicTypeNameRegs for use by
-  /// emitNonSemanticGlobalDebugInfo().
+  /// prepareModuleOutput() has registered the ext inst set. Registers are
+  /// stored in OpStringContentCache; emitNonSemanticGlobalDebugInfo() resolves
+  /// them via getCachedOpStringReg().
   void emitNonSemanticDebugStrings(SPIRV::ModuleAnalysisInfo &MAI);
 
   /// Add SPV_KHR_non_semantic_info extension and
@@ -104,9 +125,10 @@ class SPIRVNonSemanticDebugHandler : public DebugHandlerBase {
                            SPIRV::ModuleAnalysisInfo &MAI);
 
   /// Emit module-scope NSDI instructions (DebugSource, DebugCompilationUnit,
-  /// DebugTypeBasic, DebugTypePointer). Called by SPIRVAsmPrinter::
-  /// outputModuleSections() at section 10 in place of
-  /// outputModuleSection(MB_NonSemanticGlobalDI).
+  /// DebugTypeBasic, DebugTypePointer, DebugTypeFunction). Called by
+  /// SPIRVAsmPrinter::outputModuleSections() at section 10 in place of
+  /// outputModuleSection(MB_NonSemanticGlobalDI). Requires
+  /// emitNonSemanticDebugStrings() to have run first when NSDI strings apply.
   void emitNonSemanticGlobalDebugInfo(SPIRV::ModuleAnalysisInfo &MAI);
 
 protected:
@@ -137,6 +159,14 @@ class SPIRVNonSemanticDebugHandler : public DebugHandlerBase {
 private:
   void emitMCInst(MCInst &Inst);
   MCRegister emitOpString(StringRef S, SPIRV::ModuleAnalysisInfo &MAI);
+
+  /// Section 7 only: emit OpString and cache it if not already present. Must
+  /// not be called after NonSemanticOpStringsSectionEmitted is set.
+  void emitOpStringIfNew(StringRef S, SPIRV::ModuleAnalysisInfo &MAI);
+
+  /// Section 10 only: lookup OpString id from cache; asserts if missing or if
+  /// section 7 did not complete.
+  MCRegister getCachedOpStringReg(StringRef S);
   MCRegister emitOpConstantI32(uint32_t Value, MCRegister I32TypeReg,
                                SPIRV::ModuleAnalysisInfo &MAI);
   MCRegister emitExtInst(SPIRV::NonSemanticExtInst::NonSemanticExtInst Opcode,
@@ -144,6 +174,19 @@ class SPIRVNonSemanticDebugHandler : public DebugHandlerBase {
                          ArrayRef<MCRegister> Operands,
                          SPIRV::ModuleAnalysisInfo &MAI);
 
+  /// Return a cached DebugTypeFunction id when \p Ops matches a prior emission,
+  /// otherwise emit and cache a new instruction.
+  MCRegister getOrEmitDebugTypeFunction(ArrayRef<MCRegister> Ops,
+                                        MCRegister VoidTypeReg,
+                                        MCRegister ExtInstSetReg,
+                                        SPIRV::ModuleAnalysisInfo &MAI);
+
+  /// Return OpTypeVoid id for this module (lazy lookup / emit, then cache).
+  MCRegister getOrEmitOpTypeVoidReg(SPIRV::ModuleAnalysisInfo &MAI);
+
+  /// Return OpTypeInt 32 0 id for this module (lazy lookup / emit, then cache).
+  MCRegister getOrEmitOpTypeInt32Reg(SPIRV::ModuleAnalysisInfo &MAI);
+
   /// Find OpTypeVoid in the already-emitted TypeConstVars section, or emit one
   /// if the module does not contain it (e.g. no void-returning functions).
   MCRegister findOrEmitOpTypeVoid(SPIRV::ModuleAnalysisInfo &MAI);
@@ -152,16 +195,41 @@ class SPIRVNonSemanticDebugHandler : public DebugHandlerBase {
   /// one if the module does not contain it.
   MCRegister findOrEmitOpTypeInt32(SPIRV::ModuleAnalysisInfo &MAI);
 
-  /// Emit a DebugTypePointer instruction for PT. Skips pointer types that do
-  /// not carry a DWARF address space. For pointers whose base type is a
-  /// DIBasicType, looks up the base type's DebugTypeBasic register in
-  /// BasicTypeRegs. All other pointers (void pointers and pointers whose base
-  /// type is not a DIBasicType) use DebugInfoNone as the base type operand.
-  void emitDebugTypePointer(
-      const DIDerivedType *PT, MCRegister VoidTypeReg, MCRegister I32TypeReg,
-      MCRegister ExtInstSetReg, MCRegister I32ZeroReg,
-      const DenseMap<const DIBasicType *, MCRegister> &BasicTypeRegs,
-      SPIRV::ModuleAnalysisInfo &MAI);
+  /// Emit \c DebugTypePointer for pointer metadata \p PT.
+  ///
+  /// \returns The result id register on success. Returns \c std::nullopt and
+  /// emits nothing if \p PT has no DWARF address space (needed to pick the
+  /// SPIR-V storage class), or if \p PT has a non-null base DI type that is not
+  /// yet in \c DebugTypeRegs (the pointee was not emitted as a debug type).
+  ///
+  /// Base Type operand: the register from \c DebugTypeRegs for \p PT's base
+  /// type when it is set and mapped; \c DebugInfoNone when there is no base
+  /// type (e.g. \c void * in IR), consistent with SPIRV-LLVM-Translator.
+  std::optional<MCRegister>
+  emitDebugTypePointer(const DIDerivedType *PT, MCRegister ExtInstSetReg,
+                       SPIRV::ModuleAnalysisInfo &MAI);
+
+  /// Emit one DebugTypeFunction for ST when every DI operand maps to a debug
+  /// type id; otherwise emit nothing and return std::nullopt.
+  std::optional<MCRegister>
+  emitDebugTypeFunctionForSubroutineType(const DISubroutineType *ST,
+                                         MCRegister ExtInstSetReg,
+                                         SPIRV::ModuleAnalysisInfo &MAI);
+
+  /// Map a \c DISubroutineType::getTypeArray() element to an operand register
+  /// for
+  /// \c DebugTypeFunction. Non-null \p Ty resolves via \c DebugTypeRegs; if the
+  /// type was never emitted, returns \c std::nullopt.
+  ///
+  /// LLVM encodes a void return as a null first element (and may use null in
+  /// later slots). NonSemantic \c DebugTypeFunction
+  /// requires a concrete return-type operand, so when \p ReturnType is true and
+  /// \p Ty is null, this returns \p VoidTypeReg (\c OpTypeVoid). When
+  /// \p ReturnType is false and \p Ty is null, this returns
+  /// \c CachedDebugInfoNoneReg (\c DebugInfoNone).
+  std::optional<MCRegister> mapDISignatureTypeToReg(const DIType *Ty,
+                                                    MCRegister VoidTypeReg,
+                                                    bool ReturnType);
 
   /// Map a DWARF source language code to a NonSemantic.Shader.DebugInfo.100
   /// source language code.

diff  --git a/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp b/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp
index 0e917fb55aa1e..e6481c89c0265 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp
@@ -416,7 +416,7 @@ void PointerReplacer::replace(Instruction *I) {
                               LT->getAlign(), LT->getOrdering(),
                               LT->getSyncScopeID());
     NewI->takeName(LT);
-    copyMetadataForLoad(*NewI, *LT);
+    NewI->copyMetadata(*LT);
 
     IC.InsertNewInstWith(NewI, LT->getIterator());
     IC.replaceInstUsesWith(*LT, NewI);

diff  --git a/llvm/test/CodeGen/AArch64/arm64-arith-saturating.ll b/llvm/test/CodeGen/AArch64/arm64-arith-saturating.ll
index 15812d2d52d40..33c258d18ddcc 100644
--- a/llvm/test/CodeGen/AArch64/arm64-arith-saturating.ll
+++ b/llvm/test/CodeGen/AArch64/arm64-arith-saturating.ll
@@ -1,12 +1,6 @@
 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
-; RUN: llc < %s -mtriple=arm64-eabi -mcpu=cyclone | FileCheck %s --check-prefixes=CHECK
-; RUN: llc < %s -mtriple=arm64-eabi -mcpu=cyclone -global-isel -global-isel-abort=2 2>&1 | FileCheck %s --check-prefixes=CHECK,CHECK-GI
-
-; CHECK-GI: warning: Instruction selection used fallback path for vqmovund
-; CHECK-GI-NEXT: warning: Instruction selection used fallback path for vqmovnd_s
-; CHECK-GI-NEXT: warning: Instruction selection used fallback path for sqxtn_ins
-; CHECK-GI-NEXT: warning: Instruction selection used fallback path for sqxtun_insext
-; CHECK-GI-NEXT: warning: Instruction selection used fallback path for saddluse
+; RUN: llc < %s -mtriple=arm64-eabi -mcpu=cyclone | FileCheck %s
+; RUN: llc < %s -mtriple=arm64-eabi -mcpu=cyclone -global-isel | FileCheck %s
 
 define i32 @qadds(<4 x i32> %b, <4 x i32> %c) nounwind readnone optsize ssp {
 ; CHECK-LABEL: qadds:

diff  --git a/llvm/test/CodeGen/AArch64/fp-conversion-to-tbl.ll b/llvm/test/CodeGen/AArch64/fp-conversion-to-tbl.ll
index 1fbca7ca2c27c..8eac8f85126f1 100644
--- a/llvm/test/CodeGen/AArch64/fp-conversion-to-tbl.ll
+++ b/llvm/test/CodeGen/AArch64/fp-conversion-to-tbl.ll
@@ -43,7 +43,7 @@ define void @fptoui_v8f32_to_v8i8_in_loop(ptr %A, ptr %dst) {
 ; CHECK-NEXT:    fcvtzu.4s v3, v2
 ; CHECK-NEXT:    tbl.16b v1, { v3, v4 }, v0
 ; CHECK-NEXT:    str d1, [x1], #16
-; CHECK-NEXT:    b.eq LBB0_1
+; CHECK-NEXT:    b.ne LBB0_1
 ; CHECK-NEXT:  ; %bb.2: ; %exit
 ; CHECK-NEXT:    ret
 ; CHECK-NEXT:    .loh AdrpLdr Lloh0, Lloh1
@@ -59,7 +59,7 @@ loop:
   store <8 x i8> %c, ptr %gep.dst
   %iv.next = add i64 %iv, 1
   %ec = icmp eq i64 %iv.next, 1000
-  br i1 %ec, label %loop, label %exit
+  br i1 %ec, label %exit, label %loop
 
 exit:
   ret void
@@ -127,7 +127,7 @@ define void @fptoui_2x_v8f32_to_v8i8_in_loop(ptr %A, ptr %B, ptr %dst) {
 ; CHECK-NEXT:    str q1, [x2, x8, lsl #4]
 ; CHECK-NEXT:    add x8, x8, #1
 ; CHECK-NEXT:    cmp x8, #1000
-; CHECK-NEXT:    b.eq LBB2_1
+; CHECK-NEXT:    b.ne LBB2_1
 ; CHECK-NEXT:  ; %bb.2: ; %exit
 ; CHECK-NEXT:    ret
 ; CHECK-NEXT:    .loh AdrpLdr Lloh2, Lloh3
@@ -147,7 +147,7 @@ loop:
   store <16 x i8> %s, ptr %gep.dst
   %iv.next = add i64 %iv, 1
   %ec = icmp eq i64 %iv.next, 1000
-  br i1 %ec, label %loop, label %exit
+  br i1 %ec, label %exit, label %loop
 
 exit:
   ret void
@@ -194,7 +194,7 @@ define void @fptoui_2x_v8f32_to_v8i8_in_loop_no_concat_shuffle(ptr %A, ptr %B, p
 ; CHECK-NEXT:    str q1, [x2, x8, lsl #4]
 ; CHECK-NEXT:    add x8, x8, #1
 ; CHECK-NEXT:    cmp x8, #1000
-; CHECK-NEXT:    b.eq LBB3_1
+; CHECK-NEXT:    b.ne LBB3_1
 ; CHECK-NEXT:  ; %bb.2: ; %exit
 ; CHECK-NEXT:    ret
 ; CHECK-NEXT:    .loh AdrpLdr Lloh4, Lloh5
@@ -214,7 +214,7 @@ loop:
   store <16 x i8> %s, ptr %gep.dst
   %iv.next = add i64 %iv, 1
   %ec = icmp eq i64 %iv.next, 1000
-  br i1 %ec, label %loop, label %exit
+  br i1 %ec, label %exit, label %loop
 
 exit:
   ret void
@@ -259,7 +259,7 @@ define void @fptoui_v16f32_to_v16i8_in_loop(ptr %A, ptr %dst) {
 ; CHECK-NEXT:    fcvtzu.4s v3, v7
 ; CHECK-NEXT:    tbl.16b v1, { v3, v4, v5, v6 }, v0
 ; CHECK-NEXT:    str q1, [x1], #32
-; CHECK-NEXT:    b.eq LBB4_1
+; CHECK-NEXT:    b.ne LBB4_1
 ; CHECK-NEXT:  ; %bb.2: ; %exit
 ; CHECK-NEXT:    ret
 ; CHECK-NEXT:    .loh AdrpLdr Lloh6, Lloh7
@@ -275,7 +275,7 @@ loop:
   store <16 x i8> %c, ptr %gep.dst
   %iv.next = add i64 %iv, 1
   %ec = icmp eq i64 %iv.next, 1000
-  br i1 %ec, label %loop, label %exit
+  br i1 %ec, label %exit, label %loop
 
 exit:
   ret void
@@ -330,7 +330,7 @@ define void @fptoui_2x_v16f32_to_v16i8_in_loop(ptr %A, ptr %B, ptr %dst) {
 ; CHECK-NEXT:    tbl.16b v1, { v16, v17, v18, v19 }, v0
 ; CHECK-NEXT:    tbl.16b v2, { v20, v21, v22, v23 }, v0
 ; CHECK-NEXT:    stp q2, q1, [x9]
-; CHECK-NEXT:    b.eq LBB5_1
+; CHECK-NEXT:    b.ne LBB5_1
 ; CHECK-NEXT:  ; %bb.2: ; %exit
 ; CHECK-NEXT:    ret
 ; CHECK-NEXT:    .loh AdrpLdr Lloh8, Lloh9
@@ -350,7 +350,7 @@ loop:
   store <32 x i8> %s, ptr %gep.dst
   %iv.next = add i64 %iv, 1
   %ec = icmp eq i64 %iv.next, 1000
-  br i1 %ec, label %loop, label %exit
+  br i1 %ec, label %exit, label %loop
 
 exit:
   ret void
@@ -370,7 +370,7 @@ define void @fptoui_v8f32_to_v8i16_in_loop(ptr %A, ptr %dst) {
 ; CHECK-NEXT:    str q0, [x1, x8, lsl #4]
 ; CHECK-NEXT:    add x8, x8, #1
 ; CHECK-NEXT:    cmp x8, #1000
-; CHECK-NEXT:    b.eq LBB6_1
+; CHECK-NEXT:    b.ne LBB6_1
 ; CHECK-NEXT:  ; %bb.2: ; %exit
 ; CHECK-NEXT:    ret
 entry:
@@ -385,7 +385,7 @@ loop:
   store <8 x i16> %c, ptr %gep.dst
   %iv.next = add i64 %iv, 1
   %ec = icmp eq i64 %iv.next, 1000
-  br i1 %ec, label %loop, label %exit
+  br i1 %ec, label %exit, label %loop
 
 exit:
   ret void
@@ -412,7 +412,7 @@ define void @fptoui_2x_v8f32_to_v8i16_in_loop(ptr %A, ptr %B, ptr %dst) {
 ; CHECK-NEXT:    uzp1.8h v0, v0, v1
 ; CHECK-NEXT:    uzp1.8h v1, v2, v3
 ; CHECK-NEXT:    stp q0, q1, [x9]
-; CHECK-NEXT:    b.eq LBB7_1
+; CHECK-NEXT:    b.ne LBB7_1
 ; CHECK-NEXT:  ; %bb.2: ; %exit
 ; CHECK-NEXT:    ret
 entry:
@@ -431,7 +431,7 @@ loop:
   store <16 x i16> %s, ptr %gep.dst
   %iv.next = add i64 %iv, 1
   %ec = icmp eq i64 %iv.next, 1000
-  br i1 %ec, label %loop, label %exit
+  br i1 %ec, label %exit, label %loop
 
 exit:
   ret void
@@ -495,7 +495,7 @@ define void @uitofp_v8i8_to_v8f32(ptr %src, ptr %dst) {
 ; CHECK-NEXT:    ucvtf.4s v3, v3
 ; CHECK-NEXT:    ucvtf.4s v2, v2
 ; CHECK-NEXT:    stp q2, q3, [x9]
-; CHECK-NEXT:    b.eq LBB8_1
+; CHECK-NEXT:    b.ne LBB8_1
 ; CHECK-NEXT:  ; %bb.2: ; %exit
 ; CHECK-NEXT:    ret
 ; CHECK-NEXT:    .loh AdrpLdr Lloh11, Lloh13
@@ -512,7 +512,7 @@ loop:
   store <8 x float> %conv, ptr %gep.dst
   %iv.next = add i64 %iv, 1
   %ec = icmp eq i64 %iv.next, 1000
-  br i1 %ec, label %loop, label %exit
+  br i1 %ec, label %exit, label %loop
 
 exit:
   ret void
@@ -623,7 +623,7 @@ define void @uitofp_v16i8_to_v16f32(ptr %src, ptr %dst) {
 ; CHECK-NEXT:    ucvtf.4s v4, v4
 ; CHECK-NEXT:    stp q6, q5, [x9, #32]
 ; CHECK-NEXT:    stp q4, q7, [x9]
-; CHECK-NEXT:    b.eq LBB9_1
+; CHECK-NEXT:    b.ne LBB9_1
 ; CHECK-NEXT:  ; %bb.2: ; %exit
 ; CHECK-NEXT:    ret
 ; CHECK-NEXT:    .loh AdrpLdr Lloh18, Lloh21
@@ -643,7 +643,7 @@ loop:
   store <16 x float> %conv, ptr %gep.dst
   %iv.next = add i64 %iv, 1
   %ec = icmp eq i64 %iv.next, 1000
-  br i1 %ec, label %loop, label %exit
+  br i1 %ec, label %exit, label %loop
 
 exit:
   ret void

diff  --git a/llvm/test/CodeGen/AArch64/pr164181.ll b/llvm/test/CodeGen/AArch64/pr164181.ll
index 72b2a77e51c06..7695e3fd61a84 100644
--- a/llvm/test/CodeGen/AArch64/pr164181.ll
+++ b/llvm/test/CodeGen/AArch64/pr164181.ll
@@ -348,10 +348,9 @@ define void @f(i1 %var_0, i16 %var_1, i64 %var_2, i8 %var_3, i16 %var_4, i1 %var
 ; CHECK-NEXT:  .LBB0_35: // %for.inc505.us
 ; CHECK-NEXT:    // in Loop: Header=BB0_36 Depth=5
 ; CHECK-NEXT:    add x22, x22, #1
-; CHECK-NEXT:    add x27, x27, #1
+; CHECK-NEXT:    adds x27, x27, #1
 ; CHECK-NEXT:    mov w28, wzr
-; CHECK-NEXT:    cmp x27, #0
-; CHECK-NEXT:    b.hs .LBB0_9
+; CHECK-NEXT:    b.ne .LBB0_9
 ; CHECK-NEXT:  .LBB0_36: // %for.body380.us
 ; CHECK-NEXT:    // Parent Loop BB0_4 Depth=1
 ; CHECK-NEXT:    // Parent Loop BB0_6 Depth=2
@@ -466,8 +465,8 @@ if.then466.us:                                    ; preds = %if.then436.us
 for.inc505.us:                                    ; preds = %if.then466.us, %if.then436.us, %for.body380.us
   %13 = phi i8 [ %11, %for.body380.us ], [ %.sroa.speculated817.us, %if.then466.us ], [ 0, %if.then436.us ]
   %indvars.iv.next1019 = add i64 %indvars.iv1018, 1
-  %cmp378.us = icmp ult i64 %indvars.iv1018, 0
-  br i1 %cmp378.us, label %for.body380.us, label %for.cond510.preheader.us
+  %cmp378.us = icmp ugt i64 %indvars.iv1018, 0
+  br i1 %cmp378.us, label %for.cond510.preheader.us, label %for.body380.us
 
 for.body194.us:                                   ; preds = %if.end.us.7, %for.inc371.us
   %indvars.iv = phi i64 [ 0, %if.end.us.7 ], [ %indvars.iv.next, %for.inc371.us ]

diff  --git a/llvm/test/CodeGen/AArch64/sitofp-to-tbl.ll b/llvm/test/CodeGen/AArch64/sitofp-to-tbl.ll
index 297b25ed075e4..2549405c3b4fe 100644
--- a/llvm/test/CodeGen/AArch64/sitofp-to-tbl.ll
+++ b/llvm/test/CodeGen/AArch64/sitofp-to-tbl.ll
@@ -57,7 +57,7 @@ define void @sitofp_v8i8_to_v8f32(ptr %src, ptr %dst) {
 ; CHECK-NEXT:    scvtf v3.4s, v3.4s, #24
 ; CHECK-NEXT:    scvtf v2.4s, v2.4s, #24
 ; CHECK-NEXT:    stp q2, q3, [x9]
-; CHECK-NEXT:    b.eq .LBB0_1
+; CHECK-NEXT:    b.ne .LBB0_1
 ; CHECK-NEXT:  // %bb.2: // %exit
 ; CHECK-NEXT:    ret
 entry:
@@ -72,7 +72,7 @@ loop:
   store <8 x float> %conv, ptr %gep.dst
   %iv.next = add i64 %iv, 1
   %ec = icmp eq i64 %iv.next, 1000
-  br i1 %ec, label %loop, label %exit
+  br i1 %ec, label %exit, label %loop
 
 exit:
   ret void
@@ -175,7 +175,7 @@ define void @sitofp_v16i8_to_v16f32(ptr %src, ptr %dst) {
 ; CHECK-NEXT:    scvtf v4.4s, v4.4s, #24
 ; CHECK-NEXT:    stp q6, q5, [x9, #32]
 ; CHECK-NEXT:    stp q4, q7, [x9]
-; CHECK-NEXT:    b.eq .LBB1_1
+; CHECK-NEXT:    b.ne .LBB1_1
 ; CHECK-NEXT:  // %bb.2: // %exit
 ; CHECK-NEXT:    ret
 entry:
@@ -190,7 +190,7 @@ loop:
   store <16 x float> %conv, ptr %gep.dst
   %iv.next = add i64 %iv, 1
   %ec = icmp eq i64 %iv.next, 1000
-  br i1 %ec, label %loop, label %exit
+  br i1 %ec, label %exit, label %loop
 
 exit:
   ret void
@@ -215,7 +215,7 @@ define void @sitofp_v8i8_to_v8f16(ptr %src, ptr %dst) {
 ; CHECK-NEXT:    str q1, [x1, x8, lsl #4]
 ; CHECK-NEXT:    add x8, x8, #1
 ; CHECK-NEXT:    cmp x8, #1000
-; CHECK-NEXT:    b.eq .LBB2_1
+; CHECK-NEXT:    b.ne .LBB2_1
 ; CHECK-NEXT:  // %bb.2: // %exit
 ; CHECK-NEXT:    ret
 entry:
@@ -230,7 +230,7 @@ loop:
   store <8 x half> %conv, ptr %gep.dst
   %iv.next = add i64 %iv, 1
   %ec = icmp eq i64 %iv.next, 1000
-  br i1 %ec, label %loop, label %exit
+  br i1 %ec, label %exit, label %loop
 
 exit:
   ret void
@@ -252,7 +252,7 @@ define void @sitofp_v2i8_to_v2f64(ptr %src, ptr %dst) {
 ; CHECK-NEXT:    str q0, [x1, x8, lsl #4]
 ; CHECK-NEXT:    add x8, x8, #1
 ; CHECK-NEXT:    cmp x8, #1000
-; CHECK-NEXT:    b.eq .LBB3_1
+; CHECK-NEXT:    b.ne .LBB3_1
 ; CHECK-NEXT:  // %bb.2: // %exit
 ; CHECK-NEXT:    ret
 entry:
@@ -267,7 +267,7 @@ loop:
   store <2 x double> %conv, ptr %gep.dst
   %iv.next = add i64 %iv, 1
   %ec = icmp eq i64 %iv.next, 1000
-  br i1 %ec, label %loop, label %exit
+  br i1 %ec, label %exit, label %loop
 
 exit:
   ret void

diff  --git a/llvm/test/CodeGen/AArch64/trunc-to-tbl.ll b/llvm/test/CodeGen/AArch64/trunc-to-tbl.ll
index fd23f3da18cd7..efa2fec519a86 100644
--- a/llvm/test/CodeGen/AArch64/trunc-to-tbl.ll
+++ b/llvm/test/CodeGen/AArch64/trunc-to-tbl.ll
@@ -57,7 +57,7 @@ define void @trunc_v16i32_to_v16i8_in_loop(ptr %A, ptr %dst) {
 ; CHECK-NEXT:    str q1, [x1, x8, lsl #4]
 ; CHECK-NEXT:    add x8, x8, #1
 ; CHECK-NEXT:    cmp x8, #1000
-; CHECK-NEXT:    b.eq LBB0_1
+; CHECK-NEXT:    b.ne LBB0_1
 ; CHECK-NEXT:  ; %bb.2: ; %exit
 ; CHECK-NEXT:    ret
 ; CHECK-NEXT:    .loh AdrpLdr Lloh0, Lloh1
@@ -83,7 +83,7 @@ define void @trunc_v16i32_to_v16i8_in_loop(ptr %A, ptr %dst) {
 ; CHECK-BE-NEXT:    cmp x8, #1000
 ; CHECK-BE-NEXT:    tbl v1.16b, { v1.16b, v2.16b, v3.16b, v4.16b }, v0.16b
 ; CHECK-BE-NEXT:    st1 { v1.16b }, [x9]
-; CHECK-BE-NEXT:    b.eq .LBB0_1
+; CHECK-BE-NEXT:    b.ne .LBB0_1
 ; CHECK-BE-NEXT:  // %bb.2: // %exit
 ; CHECK-BE-NEXT:    ret
 ;
@@ -107,7 +107,7 @@ define void @trunc_v16i32_to_v16i8_in_loop(ptr %A, ptr %dst) {
 ; CHECK-DISABLE-NEXT:    uzp1 v2.8h, v3.8h, v2.8h
 ; CHECK-DISABLE-NEXT:    uzp1 v0.16b, v0.16b, v2.16b
 ; CHECK-DISABLE-NEXT:    st1 { v0.16b }, [x9]
-; CHECK-DISABLE-NEXT:    b.eq .LBB0_1
+; CHECK-DISABLE-NEXT:    b.ne .LBB0_1
 ; CHECK-DISABLE-NEXT:  // %bb.2: // %exit
 ; CHECK-DISABLE-NEXT:    ret
 entry:
@@ -122,7 +122,7 @@ loop:
   store <16 x i8> %trunc, ptr %gep.dst
   %iv.next = add i64 %iv, 1
   %ec = icmp eq i64 %iv.next, 1000
-  br i1 %ec, label %loop, label %exit
+  br i1 %ec, label %exit, label %loop
 
 exit:
   ret void
@@ -230,7 +230,7 @@ define void @trunc_v8i32_to_v8i8_in_loop(ptr %A, ptr %dst) {
 ; CHECK-NEXT:    str d1, [x1, x8, lsl #3]
 ; CHECK-NEXT:    add x8, x8, #1
 ; CHECK-NEXT:    cmp x8, #1000
-; CHECK-NEXT:    b.eq LBB2_1
+; CHECK-NEXT:    b.ne LBB2_1
 ; CHECK-NEXT:  ; %bb.2: ; %exit
 ; CHECK-NEXT:    ret
 ; CHECK-NEXT:    .loh AdrpLdr Lloh2, Lloh3
@@ -252,7 +252,7 @@ define void @trunc_v8i32_to_v8i8_in_loop(ptr %A, ptr %dst) {
 ; CHECK-BE-NEXT:    cmp x8, #1000
 ; CHECK-BE-NEXT:    tbl v1.16b, { v1.16b, v2.16b }, v0.16b
 ; CHECK-BE-NEXT:    st1 { v1.8b }, [x9]
-; CHECK-BE-NEXT:    b.eq .LBB2_1
+; CHECK-BE-NEXT:    b.ne .LBB2_1
 ; CHECK-BE-NEXT:  // %bb.2: // %exit
 ; CHECK-BE-NEXT:    ret
 ;
@@ -271,7 +271,7 @@ define void @trunc_v8i32_to_v8i8_in_loop(ptr %A, ptr %dst) {
 ; CHECK-DISABLE-NEXT:    uzp1 v0.8h, v0.8h, v1.8h
 ; CHECK-DISABLE-NEXT:    xtn v0.8b, v0.8h
 ; CHECK-DISABLE-NEXT:    st1 { v0.8b }, [x9]
-; CHECK-DISABLE-NEXT:    b.eq .LBB2_1
+; CHECK-DISABLE-NEXT:    b.ne .LBB2_1
 ; CHECK-DISABLE-NEXT:  // %bb.2: // %exit
 ; CHECK-DISABLE-NEXT:    ret
 entry:
@@ -286,7 +286,7 @@ loop:
   store <8 x i8> %trunc, ptr %gep.dst
   %iv.next = add i64 %iv, 1
   %ec = icmp eq i64 %iv.next, 1000
-  br i1 %ec, label %loop, label %exit
+  br i1 %ec, label %exit, label %loop
 
 exit:
   ret void
@@ -348,7 +348,7 @@ define void @trunc_v16i64_to_v16i8_in_loop(ptr %A, ptr %dst) {
 ; CHECK-NEXT:    str q1, [x1, x8, lsl #4]
 ; CHECK-NEXT:    add x8, x8, #1
 ; CHECK-NEXT:    cmp x8, #1000
-; CHECK-NEXT:    b.eq LBB3_1
+; CHECK-NEXT:    b.ne LBB3_1
 ; CHECK-NEXT:  ; %bb.2: ; %exit
 ; CHECK-NEXT:    ret
 ; CHECK-NEXT:    .loh AdrpLdr Lloh4, Lloh5
@@ -384,7 +384,7 @@ define void @trunc_v16i64_to_v16i8_in_loop(ptr %A, ptr %dst) {
 ; CHECK-BE-NEXT:    tbl v2.16b, { v16.16b, v17.16b, v18.16b, v19.16b }, v0.16b
 ; CHECK-BE-NEXT:    mov v1.d[1], v2.d[0]
 ; CHECK-BE-NEXT:    st1 { v1.16b }, [x9]
-; CHECK-BE-NEXT:    b.eq .LBB3_1
+; CHECK-BE-NEXT:    b.ne .LBB3_1
 ; CHECK-BE-NEXT:  // %bb.2: // %exit
 ; CHECK-BE-NEXT:    ret
 ;
@@ -420,7 +420,7 @@ define void @trunc_v16i64_to_v16i8_in_loop(ptr %A, ptr %dst) {
 ; CHECK-DISABLE-NEXT:    uzp1 v0.8h, v0.8h, v2.8h
 ; CHECK-DISABLE-NEXT:    uzp1 v0.16b, v0.16b, v1.16b
 ; CHECK-DISABLE-NEXT:    st1 { v0.16b }, [x9]
-; CHECK-DISABLE-NEXT:    b.eq .LBB3_1
+; CHECK-DISABLE-NEXT:    b.ne .LBB3_1
 ; CHECK-DISABLE-NEXT:  // %bb.2: // %exit
 ; CHECK-DISABLE-NEXT:    ret
 entry:
@@ -435,7 +435,7 @@ loop:
   store <16 x i8> %trunc, ptr %gep.dst
   %iv.next = add i64 %iv, 1
   %ec = icmp eq i64 %iv.next, 1000
-  br i1 %ec, label %loop, label %exit
+  br i1 %ec, label %exit, label %loop
 
 exit:
   ret void
@@ -493,7 +493,7 @@ define void @trunc_v8i64_to_v8i8_in_loop(ptr %A, ptr %dst) {
 ; CHECK-NEXT:    str d1, [x1, x8, lsl #3]
 ; CHECK-NEXT:    add x8, x8, #1
 ; CHECK-NEXT:    cmp x8, #1000
-; CHECK-NEXT:    b.eq LBB4_1
+; CHECK-NEXT:    b.ne LBB4_1
 ; CHECK-NEXT:  ; %bb.2: ; %exit
 ; CHECK-NEXT:    ret
 ; CHECK-NEXT:    .loh AdrpLdr Lloh6, Lloh7
@@ -519,7 +519,7 @@ define void @trunc_v8i64_to_v8i8_in_loop(ptr %A, ptr %dst) {
 ; CHECK-BE-NEXT:    cmp x8, #1000
 ; CHECK-BE-NEXT:    tbl v1.16b, { v1.16b, v2.16b, v3.16b, v4.16b }, v0.16b
 ; CHECK-BE-NEXT:    st1 { v1.8b }, [x9]
-; CHECK-BE-NEXT:    b.eq .LBB4_1
+; CHECK-BE-NEXT:    b.ne .LBB4_1
 ; CHECK-BE-NEXT:  // %bb.2: // %exit
 ; CHECK-BE-NEXT:    ret
 ;
@@ -544,7 +544,7 @@ define void @trunc_v8i64_to_v8i8_in_loop(ptr %A, ptr %dst) {
 ; CHECK-DISABLE-NEXT:    uzp1 v0.8h, v0.8h, v2.8h
 ; CHECK-DISABLE-NEXT:    xtn v0.8b, v0.8h
 ; CHECK-DISABLE-NEXT:    st1 { v0.8b }, [x9]
-; CHECK-DISABLE-NEXT:    b.eq .LBB4_1
+; CHECK-DISABLE-NEXT:    b.ne .LBB4_1
 ; CHECK-DISABLE-NEXT:  // %bb.2: // %exit
 ; CHECK-DISABLE-NEXT:    ret
 entry:
@@ -559,7 +559,7 @@ loop:
   store <8 x i8> %trunc, ptr %gep.dst
   %iv.next = add i64 %iv, 1
   %ec = icmp eq i64 %iv.next, 1000
-  br i1 %ec, label %loop, label %exit
+  br i1 %ec, label %exit, label %loop
 
 exit:
   ret void
@@ -596,7 +596,7 @@ define void @trunc_v8i19_to_v8i8_in_loop(ptr %A, ptr %dst) {
 ; CHECK-NEXT:    str d0, [x1, x8, lsl #3]
 ; CHECK-NEXT:    add x8, x8, #1
 ; CHECK-NEXT:    cmp x8, #1000
-; CHECK-NEXT:    b.eq LBB5_1
+; CHECK-NEXT:    b.ne LBB5_1
 ; CHECK-NEXT:  ; %bb.2: ; %exit
 ; CHECK-NEXT:    ret
 ;
@@ -637,7 +637,7 @@ define void @trunc_v8i19_to_v8i8_in_loop(ptr %A, ptr %dst) {
 ; CHECK-BE-NEXT:    uzp1 v0.8h, v0.8h, v1.8h
 ; CHECK-BE-NEXT:    xtn v0.8b, v0.8h
 ; CHECK-BE-NEXT:    st1 { v0.8b }, [x9]
-; CHECK-BE-NEXT:    b.eq .LBB5_1
+; CHECK-BE-NEXT:    b.ne .LBB5_1
 ; CHECK-BE-NEXT:  // %bb.2: // %exit
 ; CHECK-BE-NEXT:    ret
 ;
@@ -678,7 +678,7 @@ define void @trunc_v8i19_to_v8i8_in_loop(ptr %A, ptr %dst) {
 ; CHECK-DISABLE-NEXT:    uzp1 v0.8h, v0.8h, v1.8h
 ; CHECK-DISABLE-NEXT:    xtn v0.8b, v0.8h
 ; CHECK-DISABLE-NEXT:    st1 { v0.8b }, [x9]
-; CHECK-DISABLE-NEXT:    b.eq .LBB5_1
+; CHECK-DISABLE-NEXT:    b.ne .LBB5_1
 ; CHECK-DISABLE-NEXT:  // %bb.2: // %exit
 ; CHECK-DISABLE-NEXT:    ret
 entry:
@@ -693,7 +693,7 @@ loop:
   store <8 x i8> %trunc, ptr %gep.dst
   %iv.next = add i64 %iv, 1
   %ec = icmp eq i64 %iv.next, 1000
-  br i1 %ec, label %loop, label %exit
+  br i1 %ec, label %exit, label %loop
 
 exit:
   ret void
@@ -724,7 +724,7 @@ define void @trunc_v11i64_to_v11i8_in_loop(ptr %A, ptr %dst) {
 ; CHECK-NEXT:    stur b1, [x1, #10]
 ; CHECK-NEXT:    str h2, [x1, #8]
 ; CHECK-NEXT:    add x1, x1, #16
-; CHECK-NEXT:    b.eq LBB6_1
+; CHECK-NEXT:    b.ne LBB6_1
 ; CHECK-NEXT:  ; %bb.2: ; %exit
 ; CHECK-NEXT:    ret
 ;
@@ -760,7 +760,7 @@ define void @trunc_v11i64_to_v11i8_in_loop(ptr %A, ptr %dst) {
 ; CHECK-BE-NEXT:    stur b0, [x1, #10]
 ; CHECK-BE-NEXT:    str h2, [x1, #8]
 ; CHECK-BE-NEXT:    add x1, x1, #16
-; CHECK-BE-NEXT:    b.eq .LBB6_1
+; CHECK-BE-NEXT:    b.ne .LBB6_1
 ; CHECK-BE-NEXT:  // %bb.2: // %exit
 ; CHECK-BE-NEXT:    ret
 ;
@@ -796,7 +796,7 @@ define void @trunc_v11i64_to_v11i8_in_loop(ptr %A, ptr %dst) {
 ; CHECK-DISABLE-NEXT:    stur b0, [x1, #10]
 ; CHECK-DISABLE-NEXT:    str h2, [x1, #8]
 ; CHECK-DISABLE-NEXT:    add x1, x1, #16
-; CHECK-DISABLE-NEXT:    b.eq .LBB6_1
+; CHECK-DISABLE-NEXT:    b.ne .LBB6_1
 ; CHECK-DISABLE-NEXT:  // %bb.2: // %exit
 ; CHECK-DISABLE-NEXT:    ret
 entry:
@@ -811,7 +811,7 @@ loop:
   store <11 x i8> %trunc, ptr %gep.dst
   %iv.next = add i64 %iv, 1
   %ec = icmp eq i64 %iv.next, 1000
-  br i1 %ec, label %loop, label %exit
+  br i1 %ec, label %exit, label %loop
 
 exit:
   ret void
@@ -829,7 +829,7 @@ define void @trunc_v16i16_to_v16i8_in_loop(ptr %A, ptr %dst) {
 ; CHECK-NEXT:    str q0, [x1, x8, lsl #4]
 ; CHECK-NEXT:    add x8, x8, #1
 ; CHECK-NEXT:    cmp x8, #1000
-; CHECK-NEXT:    b.eq LBB7_1
+; CHECK-NEXT:    b.ne LBB7_1
 ; CHECK-NEXT:  ; %bb.2: ; %exit
 ; CHECK-NEXT:    ret
 ;
@@ -847,7 +847,7 @@ define void @trunc_v16i16_to_v16i8_in_loop(ptr %A, ptr %dst) {
 ; CHECK-BE-NEXT:    cmp x8, #1000
 ; CHECK-BE-NEXT:    uzp1 v0.16b, v0.16b, v1.16b
 ; CHECK-BE-NEXT:    st1 { v0.16b }, [x9]
-; CHECK-BE-NEXT:    b.eq .LBB7_1
+; CHECK-BE-NEXT:    b.ne .LBB7_1
 ; CHECK-BE-NEXT:  // %bb.2: // %exit
 ; CHECK-BE-NEXT:    ret
 ;
@@ -865,7 +865,7 @@ define void @trunc_v16i16_to_v16i8_in_loop(ptr %A, ptr %dst) {
 ; CHECK-DISABLE-NEXT:    cmp x8, #1000
 ; CHECK-DISABLE-NEXT:    uzp1 v0.16b, v0.16b, v1.16b
 ; CHECK-DISABLE-NEXT:    st1 { v0.16b }, [x9]
-; CHECK-DISABLE-NEXT:    b.eq .LBB7_1
+; CHECK-DISABLE-NEXT:    b.ne .LBB7_1
 ; CHECK-DISABLE-NEXT:  // %bb.2: // %exit
 ; CHECK-DISABLE-NEXT:    ret
 entry:
@@ -880,7 +880,7 @@ loop:
   store <16 x i8> %trunc, ptr %gep.dst
   %iv.next = add i64 %iv, 1
   %ec = icmp eq i64 %iv.next, 1000
-  br i1 %ec, label %loop, label %exit
+  br i1 %ec, label %exit, label %loop
 
 exit:
   ret void
@@ -897,7 +897,7 @@ define void @trunc_v8i16_to_v8i8_in_loop(ptr %A, ptr %dst) {
 ; CHECK-NEXT:    str d0, [x1, x8, lsl #3]
 ; CHECK-NEXT:    add x8, x8, #1
 ; CHECK-NEXT:    cmp x8, #1000
-; CHECK-NEXT:    b.eq LBB8_1
+; CHECK-NEXT:    b.ne LBB8_1
 ; CHECK-NEXT:  ; %bb.2: ; %exit
 ; CHECK-NEXT:    ret
 ;
@@ -913,7 +913,7 @@ define void @trunc_v8i16_to_v8i8_in_loop(ptr %A, ptr %dst) {
 ; CHECK-BE-NEXT:    cmp x8, #1000
 ; CHECK-BE-NEXT:    xtn v0.8b, v0.8h
 ; CHECK-BE-NEXT:    st1 { v0.8b }, [x9]
-; CHECK-BE-NEXT:    b.eq .LBB8_1
+; CHECK-BE-NEXT:    b.ne .LBB8_1
 ; CHECK-BE-NEXT:  // %bb.2: // %exit
 ; CHECK-BE-NEXT:    ret
 ;
@@ -929,7 +929,7 @@ define void @trunc_v8i16_to_v8i8_in_loop(ptr %A, ptr %dst) {
 ; CHECK-DISABLE-NEXT:    cmp x8, #1000
 ; CHECK-DISABLE-NEXT:    xtn v0.8b, v0.8h
 ; CHECK-DISABLE-NEXT:    st1 { v0.8b }, [x9]
-; CHECK-DISABLE-NEXT:    b.eq .LBB8_1
+; CHECK-DISABLE-NEXT:    b.ne .LBB8_1
 ; CHECK-DISABLE-NEXT:  // %bb.2: // %exit
 ; CHECK-DISABLE-NEXT:    ret
 entry:
@@ -944,7 +944,7 @@ loop:
   store <8 x i8> %trunc, ptr %gep.dst
   %iv.next = add i64 %iv, 1
   %ec = icmp eq i64 %iv.next, 1000
-  br i1 %ec, label %loop, label %exit
+  br i1 %ec, label %exit, label %loop
 
 exit:
   ret void

diff  --git a/llvm/test/CodeGen/SPIRV/debug-info/debug-type-function-int-string-dedup.ll b/llvm/test/CodeGen/SPIRV/debug-info/debug-type-function-int-string-dedup.ll
new file mode 100644
index 0000000000000..c28e2b062dfcc
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/debug-info/debug-type-function-int-string-dedup.ll
@@ -0,0 +1,44 @@
+; RUN: llc --verify-machineinstrs -O0 -mtriple=spirv64-unknown-unknown --spirv-ext=+SPV_KHR_non_semantic_info %s -o - | FileCheck %s
+; RUN: %if spirv-tools %{ llc --verify-machineinstrs --spirv-ext=+SPV_KHR_non_semantic_info -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %}
+
+; Two distinct !DIBasicType nodes named "int" share one OpString "int".
+
+; CHECK: [[ext:%[0-9]+]] = OpExtInstImport "NonSemantic.Shader.DebugInfo.100"
+; CHECK-COUNT-1: OpString "int"
+; CHECK-DAG: [[type_void:%[0-9]+]] = OpTypeVoid
+; CHECK-DAG: [[type_int32:%[0-9]+]] = OpTypeInt 32 0
+; CHECK-DAG: [[flag_zero:%[0-9]+]] = OpConstant [[type_int32]] 0{{$}}
+; CHECK-DAG: OpExtInst [[type_void]] [[ext]] DebugTypeFunction [[flag_zero]]
+
+target triple = "spirv64-unknown-unknown"
+
+define spir_func i32 @dedupe_a() !dbg !10 {
+entry:
+  ret i32 0
+}
+
+define spir_func i32 @dedupe_b() !dbg !11 {
+entry:
+  ret i32 0
+}
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!2, !3, !4, !5}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version XX.X", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None)
+!1 = !DIFile(filename: "debug-type-function-int-string-dedup.c", directory: "/AAAAAAAAAA/BBBBBBBB/CCCCCCCCC", checksumkind: CSK_MD5, checksum: "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF")
+!2 = !{i32 7, !"Dwarf Version", i32 5}
+!3 = !{i32 2, !"Debug Info Version", i32 3}
+!4 = !{i32 1, !"wchar_size", i32 4}
+!5 = !{i32 7, !"frame-pointer", i32 2}
+
+!6 = !DISubroutineType(cc: DW_CC_LLVM_SpirFunction, types: !7)
+!7 = !{!8}
+!8 = distinct !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+
+!9 = !DISubroutineType(cc: DW_CC_LLVM_SpirFunction, types: !12)
+!12 = !{!13}
+!13 = distinct !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+
+!10 = distinct !DISubprogram(name: "dedupe_a", linkageName: "dedupe_a", scope: !1, file: !1, line: 1, type: !6, scopeLine: 1, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0)
+!11 = distinct !DISubprogram(name: "dedupe_b", linkageName: "dedupe_b", scope: !1, file: !1, line: 2, type: !9, scopeLine: 2, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0)

diff  --git a/llvm/test/CodeGen/SPIRV/debug-info/debug-type-function-multi-scalar-params.ll b/llvm/test/CodeGen/SPIRV/debug-info/debug-type-function-multi-scalar-params.ll
new file mode 100644
index 0000000000000..a49eaede1f374
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/debug-info/debug-type-function-multi-scalar-params.ll
@@ -0,0 +1,39 @@
+; RUN: llc --verify-machineinstrs -O0 -mtriple=spirv64-unknown-unknown --spirv-ext=+SPV_KHR_non_semantic_info %s -o - | FileCheck %s
+; RUN: %if spirv-tools %{ llc --verify-machineinstrs --spirv-ext=+SPV_KHR_non_semantic_info -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %}
+;
+; Multi-slot signature mapping order: DebugTypeFunction must keep operand order
+; for void(int, float, int).
+
+; CHECK: [[ext:%[0-9]+]] = OpExtInstImport "NonSemantic.Shader.DebugInfo.100"
+; CHECK-DAG: [[type_void:%[0-9]+]] = OpTypeVoid
+; CHECK-DAG: [[type_int32:%[0-9]+]] = OpTypeInt 32 0
+; CHECK-DAG: [[flag_zero:%[0-9]+]] = OpConstant [[type_int32]] 0{{$}}
+; CHECK-DAG: [[str_int:%[0-9]+]] = OpString "int"
+; CHECK-DAG: [[str_float:%[0-9]+]] = OpString "float"
+; CHECK-DAG: [[dbg_int:%[0-9]+]] = OpExtInst [[type_void]] [[ext]] DebugTypeBasic [[str_int]]
+; CHECK-DAG: [[dbg_float:%[0-9]+]] = OpExtInst [[type_void]] [[ext]] DebugTypeBasic [[str_float]]
+; CHECK: OpExtInst [[type_void]] [[ext]] DebugTypeFunction [[flag_zero]] [[type_void]] [[dbg_int]] [[dbg_float]] [[dbg_int]]
+
+target triple = "spirv64-unknown-unknown"
+
+define spir_func void @multi_params(i32 %a, float %b, i32 %c) !dbg !10 {
+entry:
+  ret void
+}
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!2, !3, !4, !5}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version XX.X", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None)
+!1 = !DIFile(filename: "debug-type-function-multi-scalar-params.c", directory: "/AAAAAAAAAA/BBBBBBBB/CCCCCCCCC", checksumkind: CSK_MD5, checksum: "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF")
+!2 = !{i32 7, !"Dwarf Version", i32 5}
+!3 = !{i32 2, !"Debug Info Version", i32 3}
+!4 = !{i32 1, !"wchar_size", i32 4}
+!5 = !{i32 7, !"frame-pointer", i32 2}
+
+!6 = !DISubroutineType(cc: DW_CC_LLVM_SpirFunction, types: !7)
+!7 = !{null, !8, !9, !8}
+!8 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!9 = !DIBasicType(name: "float", size: 32, encoding: DW_ATE_float)
+
+!10 = distinct !DISubprogram(name: "multi_params", linkageName: "multi_params", scope: !1, file: !1, line: 1, type: !6, scopeLine: 1, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0)

diff  --git a/llvm/test/CodeGen/SPIRV/debug-info/debug-type-function-omit.ll b/llvm/test/CodeGen/SPIRV/debug-info/debug-type-function-omit.ll
new file mode 100644
index 0000000000000..c49af8964e0f0
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/debug-info/debug-type-function-omit.ll
@@ -0,0 +1,44 @@
+; RUN: llc --verify-machineinstrs -O0 -mtriple=spirv64-unknown-unknown --spirv-ext=+SPV_KHR_non_semantic_info %s -o - | FileCheck %s
+; RUN: %if spirv-tools %{ llc --verify-machineinstrs --spirv-ext=+SPV_KHR_non_semantic_info -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %}
+
+; Unsupported composite parameter and pointer without dwarfAddressSpace — DISubroutineType not lowered to DebugTypeFunction.
+
+; CHECK: OpExtInstImport "NonSemantic.Shader.DebugInfo.100"
+; CHECK: DebugCompilationUnit
+; CHECK-NOT: DebugTypePointer
+; CHECK-NOT: DebugTypeFunction
+
+target triple = "spirv64-unknown-unknown"
+
+define spir_func void @opaque_struct_param(i32 %x) !dbg !10 {
+entry:
+  ret void
+}
+
+define spir_func void @ptr_no_as(ptr %p) !dbg !11 {
+entry:
+  ret void
+}
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!2, !3, !4, !5}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version XX.X", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None)
+!1 = !DIFile(filename: "debug-type-function-omit.c", directory: "/AAAAAAAAAA/BBBBBBBB/CCCCCCCCC", checksumkind: CSK_MD5, checksum: "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF")
+!2 = !{i32 7, !"Dwarf Version", i32 5}
+!3 = !{i32 2, !"Debug Info Version", i32 3}
+!4 = !{i32 1, !"wchar_size", i32 4}
+!5 = !{i32 7, !"frame-pointer", i32 2}
+
+!6 = !DISubroutineType(cc: DW_CC_LLVM_SpirFunction, types: !7)
+!7 = !{null, !8}
+!8 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "opaque_sig", file: !1, line: 50, size: 32, elements: !9, identifier: "opaque_sig")
+!9 = !{}
+
+!12 = !DISubroutineType(cc: DW_CC_LLVM_SpirFunction, types: !13)
+!13 = !{null, !14}
+!14 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !15, size: 64)
+!15 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+
+!10 = distinct !DISubprogram(name: "opaque_struct_param", linkageName: "opaque_struct_param", scope: !1, file: !1, line: 1, type: !6, scopeLine: 1, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0)
+!11 = distinct !DISubprogram(name: "ptr_no_as", linkageName: "ptr_no_as", scope: !1, file: !1, line: 2, type: !12, scopeLine: 2, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0)

diff  --git a/llvm/test/CodeGen/SPIRV/debug-info/debug-type-function-pointer-debug-none-base.ll b/llvm/test/CodeGen/SPIRV/debug-info/debug-type-function-pointer-debug-none-base.ll
new file mode 100644
index 0000000000000..3eb3774a317af
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/debug-info/debug-type-function-pointer-debug-none-base.ll
@@ -0,0 +1,38 @@
+; RUN: llc --verify-machineinstrs -O0 -mtriple=spirv64-unknown-unknown --spirv-ext=+SPV_KHR_non_semantic_info %s -o - | FileCheck %s
+; TODO(#109287): spirv-val coverage remains disabled for DebugTypePointer with
+; DebugInfoNone as the base type.
+;
+; Pointer parameter with null baseType should lower to DebugTypePointer using
+; DebugInfoNone as Base Type, and still be consumed by DebugTypeFunction.
+
+; CHECK: [[ext:%[0-9]+]] = OpExtInstImport "NonSemantic.Shader.DebugInfo.100"
+; CHECK-DAG: [[type_void:%[0-9]+]] = OpTypeVoid
+; CHECK-DAG: [[type_int32:%[0-9]+]] = OpTypeInt 32 0
+; CHECK-DAG: [[flag_zero:%[0-9]+]] = OpConstant [[type_int32]] 0{{$}}
+; CHECK-DAG: [[debug_none:%[0-9]+]] = OpExtInst [[type_void]] [[ext]] DebugInfoNone
+; CHECK-DAG: [[storage_class:%[0-9]+]] = OpConstant [[type_int32]] 8{{$}}
+; CHECK: [[dbg_ptr:%[0-9]+]] = OpExtInst [[type_void]] [[ext]] DebugTypePointer [[debug_none]] [[storage_class]] [[flag_zero]]
+; CHECK: OpExtInst [[type_void]] [[ext]] DebugTypeFunction [[flag_zero]] [[type_void]] [[dbg_ptr]]
+
+target triple = "spirv64-unknown-unknown"
+
+define spir_func void @ptr_null_base(ptr addrspace(4) %p) !dbg !10 {
+entry:
+  ret void
+}
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!2, !3, !4, !5}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version XX.X", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None)
+!1 = !DIFile(filename: "debug-type-function-pointer-debug-none-base.c", directory: "/AAAAAAAAAA/BBBBBBBB/CCCCCCCCC", checksumkind: CSK_MD5, checksum: "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF")
+!2 = !{i32 7, !"Dwarf Version", i32 5}
+!3 = !{i32 2, !"Debug Info Version", i32 3}
+!4 = !{i32 1, !"wchar_size", i32 4}
+!5 = !{i32 7, !"frame-pointer", i32 2}
+
+!6 = !DISubroutineType(cc: DW_CC_LLVM_SpirFunction, types: !7)
+!7 = !{null, !8}
+!8 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: null, size: 64, dwarfAddressSpace: 4)
+
+!10 = distinct !DISubprogram(name: "ptr_null_base", linkageName: "ptr_null_base", scope: !1, file: !1, line: 1, type: !6, scopeLine: 1, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0)

diff  --git a/llvm/test/CodeGen/SPIRV/debug-info/debug-type-function-pointer-param.ll b/llvm/test/CodeGen/SPIRV/debug-info/debug-type-function-pointer-param.ll
new file mode 100644
index 0000000000000..808d90efec896
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/debug-info/debug-type-function-pointer-param.ll
@@ -0,0 +1,35 @@
+; RUN: llc --verify-machineinstrs -O0 -mtriple=spirv64-unknown-unknown --spirv-ext=+SPV_KHR_non_semantic_info %s -o - | FileCheck %s
+; RUN: %if spirv-tools %{ llc --verify-machineinstrs --spirv-ext=+SPV_KHR_non_semantic_info -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %}
+
+; void (*)(addrspace(4) i32*) — DebugTypePointer + DebugTypeFunction includes the pointer parameter operand.
+
+; CHECK: [[ext:%[0-9]+]] = OpExtInstImport "NonSemantic.Shader.DebugInfo.100"
+; CHECK-DAG: [[type_void:%[0-9]+]] = OpTypeVoid
+; CHECK-DAG: [[type_int32:%[0-9]+]] = OpTypeInt 32 0
+; CHECK-DAG: [[flag_zero:%[0-9]+]] = OpConstant [[type_int32]] 0{{$}}
+; CHECK-DAG: OpExtInst [[type_void]] [[ext]] DebugTypePointer
+; CHECK-DAG: OpExtInst [[type_void]] [[ext]] DebugTypeFunction [[flag_zero]] [[type_void]] {{%[0-9]+}}
+
+target triple = "spirv64-unknown-unknown"
+
+define spir_func void @ptr_param(ptr addrspace(4) %p) !dbg !10 {
+entry:
+  ret void
+}
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!2, !3, !4, !5}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version XX.X", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None)
+!1 = !DIFile(filename: "debug-type-function-pointer-param.c", directory: "/AAAAAAAAAA/BBBBBBBB/CCCCCCCCC", checksumkind: CSK_MD5, checksum: "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF")
+!2 = !{i32 7, !"Dwarf Version", i32 5}
+!3 = !{i32 2, !"Debug Info Version", i32 3}
+!4 = !{i32 1, !"wchar_size", i32 4}
+!5 = !{i32 7, !"frame-pointer", i32 2}
+
+!6 = !DISubroutineType(cc: DW_CC_LLVM_SpirFunction, types: !7)
+!7 = !{null, !8}
+!8 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !9, size: 64, dwarfAddressSpace: 4)
+!9 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+
+!10 = distinct !DISubprogram(name: "ptr_param", linkageName: "ptr_param", scope: !1, file: !1, line: 1, type: !6, scopeLine: 1, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0)

diff  --git a/llvm/test/CodeGen/SPIRV/debug-info/debug-type-function-scalar-returns.ll b/llvm/test/CodeGen/SPIRV/debug-info/debug-type-function-scalar-returns.ll
new file mode 100644
index 0000000000000..37e002a21f2ab
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/debug-info/debug-type-function-scalar-returns.ll
@@ -0,0 +1,32 @@
+; RUN: llc --verify-machineinstrs -O0 -mtriple=spirv64-unknown-unknown --spirv-ext=+SPV_KHR_non_semantic_info %s -o - | FileCheck %s
+; RUN: %if spirv-tools %{ llc --verify-machineinstrs --spirv-ext=+SPV_KHR_non_semantic_info -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %}
+
+; CHECK: [[ext:%[0-9]+]] = OpExtInstImport "NonSemantic.Shader.DebugInfo.100"
+; CHECK-DAG: [[type_void:%[0-9]+]] = OpTypeVoid
+; CHECK-DAG: [[type_int32:%[0-9]+]] = OpTypeInt 32 0
+; CHECK-DAG: [[flag_zero:%[0-9]+]] = OpConstant [[type_int32]] 0{{$}}
+; CHECK-DAG: OpString "float"
+; CHECK-DAG: OpExtInst [[type_void]] [[ext]] DebugTypeFunction [[flag_zero]]
+
+target triple = "spirv64-unknown-unknown"
+
+define spir_func float @float_sig() !dbg !9 {
+entry:
+  ret float 0.000000e+00
+}
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!2, !3, !4, !5}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version XX.X", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None)
+!1 = !DIFile(filename: "debug-type-function-scalar-returns.c", directory: "/AAAAAAAAAA/BBBBBBBB/CCCCCCCCC", checksumkind: CSK_MD5, checksum: "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF")
+!2 = !{i32 7, !"Dwarf Version", i32 5}
+!3 = !{i32 2, !"Debug Info Version", i32 3}
+!4 = !{i32 1, !"wchar_size", i32 4}
+!5 = !{i32 7, !"frame-pointer", i32 2}
+
+!6 = !DISubroutineType(cc: DW_CC_LLVM_SpirFunction, types: !7)
+!7 = !{!8}
+!8 = !DIBasicType(name: "float", size: 32, encoding: DW_ATE_float)
+
+!9 = distinct !DISubprogram(name: "float_sig", linkageName: "float_sig", scope: !1, file: !1, line: 1, type: !6, scopeLine: 1, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0)

diff  --git a/llvm/test/CodeGen/SPIRV/debug-info/debug-type-function-subroutine-type-flags.ll b/llvm/test/CodeGen/SPIRV/debug-info/debug-type-function-subroutine-type-flags.ll
new file mode 100644
index 0000000000000..b6d6b429bbd72
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/debug-info/debug-type-function-subroutine-type-flags.ll
@@ -0,0 +1,36 @@
+; RUN: llc --verify-machineinstrs -O0 -mtriple=spirv64-unknown-unknown --spirv-ext=+SPV_KHR_non_semantic_info %s -o - | FileCheck %s
+; RUN: %if spirv-tools %{ llc --verify-machineinstrs --spirv-ext=+SPV_KHR_non_semantic_info -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %}
+
+; Test the encoding of the flags in the DISubroutineType
+
+; CHECK: [[ext:%[0-9]+]] = OpExtInstImport "NonSemantic.Shader.DebugInfo.100"
+; CHECK-DAG: [[type_void:%[0-9]+]] = OpTypeVoid
+; CHECK-DAG: [[type_int32:%[0-9]+]] = OpTypeInt 32 0
+; CHECK-DAG: [[flag_zero:%[0-9]+]] = OpConstant [[type_int32]] 0{{$}}
+; CHECK-DAG: [[flag_prototyped:%[0-9]+]] = OpConstant [[type_int32]] 128{{$}}
+; CHECK-DAG: [[dbg_ptr:%[0-9]+]] = OpExtInst [[type_void]] [[ext]] DebugTypePointer {{.*}} {{.*}} [[flag_zero]]
+; CHECK: OpExtInst [[type_void]] [[ext]] DebugTypeFunction [[flag_prototyped]] [[type_void]] [[dbg_ptr]]
+
+target triple = "spirv64-unknown-unknown"
+
+define spir_func void @ptr_param(ptr addrspace(4) %p) !dbg !10 {
+entry:
+  ret void
+}
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!2, !3, !4, !5}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version XX.X", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None)
+!1 = !DIFile(filename: "debug-type-function-subroutine-type-flags.c", directory: "/AAAAAAAAAA/BBBBBBBB/CCCCCCCCC", checksumkind: CSK_MD5, checksum: "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF")
+!2 = !{i32 7, !"Dwarf Version", i32 5}
+!3 = !{i32 2, !"Debug Info Version", i32 3}
+!4 = !{i32 1, !"wchar_size", i32 4}
+!5 = !{i32 7, !"frame-pointer", i32 2}
+
+!6 = !DISubroutineType(cc: DW_CC_LLVM_SpirFunction, flags: DIFlagPrototyped, types: !7)
+!7 = !{null, !8}
+!8 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !9, size: 64, dwarfAddressSpace: 4)
+!9 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+
+!10 = distinct !DISubprogram(name: "ptr_param", linkageName: "ptr_param", scope: !1, file: !1, line: 1, type: !6, scopeLine: 1, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0)

diff  --git a/llvm/test/CodeGen/SPIRV/debug-info/debug-type-function-void-prototypes.ll b/llvm/test/CodeGen/SPIRV/debug-info/debug-type-function-void-prototypes.ll
new file mode 100644
index 0000000000000..d9f41f4cf0bab
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/debug-info/debug-type-function-void-prototypes.ll
@@ -0,0 +1,42 @@
+; RUN: llc --verify-machineinstrs -O0 -mtriple=spirv64-unknown-unknown --spirv-ext=+SPV_KHR_non_semantic_info %s -o - | FileCheck %s
+; RUN: %if spirv-tools %{ llc --verify-machineinstrs --spirv-ext=+SPV_KHR_non_semantic_info -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %}
+
+; Void function types in LLVM metadata may be written as an empty type list (!{}) or with an explicit
+; null return slot (!{null}); both should produce the same SPIR-V DebugTypeFunction (flags + void only).
+
+; CHECK: [[ext:%[0-9]+]] = OpExtInstImport "NonSemantic.Shader.DebugInfo.100"
+; CHECK-DAG: [[type_void:%[0-9]+]] = OpTypeVoid
+; CHECK-DAG: [[type_int32:%[0-9]+]] = OpTypeInt 32 0
+; CHECK-DAG: [[flag_zero:%[0-9]+]] = OpConstant [[type_int32]] 0{{$}}
+; CHECK-COUNT-1: OpExtInst [[type_void]] [[ext]] DebugTypeFunction [[flag_zero]] [[type_void]]
+
+target triple = "spirv64-unknown-unknown"
+
+define spir_func void @void_fn() !dbg !10 {
+entry:
+  ret void
+}
+
+define spir_func void @void_explicit_null() !dbg !11 {
+entry:
+  ret void
+}
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!2, !3, !4, !5}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version XX.X", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None)
+!1 = !DIFile(filename: "debug-type-function-void-prototypes.c", directory: "/AAAAAAAAAA/BBBBBBBB/CCCCCCCCC", checksumkind: CSK_MD5, checksum: "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF")
+!2 = !{i32 7, !"Dwarf Version", i32 5}
+!3 = !{i32 2, !"Debug Info Version", i32 3}
+!4 = !{i32 1, !"wchar_size", i32 4}
+!5 = !{i32 7, !"frame-pointer", i32 2}
+
+!6 = !DISubroutineType(cc: DW_CC_LLVM_SpirFunction, types: !7)
+!7 = !{}
+
+!8 = !DISubroutineType(cc: DW_CC_LLVM_SpirFunction, types: !9)
+!9 = !{null}
+
+!10 = distinct !DISubprogram(name: "void_fn", linkageName: "void_fn", scope: !1, file: !1, line: 1, type: !6, scopeLine: 1, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0)
+!11 = distinct !DISubprogram(name: "void_explicit_null", linkageName: "void_explicit_null", scope: !1, file: !1, line: 2, type: !8, scopeLine: 2, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0)

diff  --git a/llvm/test/CodeGen/SPIRV/debug-info/debug-type-pointer-composite-pointee.ll b/llvm/test/CodeGen/SPIRV/debug-info/debug-type-pointer-composite-pointee.ll
new file mode 100644
index 0000000000000..ce0a45452f6e4
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/debug-info/debug-type-pointer-composite-pointee.ll
@@ -0,0 +1,38 @@
+; RUN: llc --verify-machineinstrs --spirv-ext=+SPV_KHR_non_semantic_info -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s
+; RUN: %if spirv-tools %{ llc --verify-machineinstrs --spirv-ext=+SPV_KHR_non_semantic_info -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %}
+
+; DW_TAG_array_type composite not yet supported
+
+; CHECK: OpExtInstImport "NonSemantic.Shader.DebugInfo.100"
+; CHECK: OpExtInst {{.*}} DebugCompilationUnit
+; CHECK-NOT: DebugTypePointer
+
+define spir_func void @ptr_to_array() !dbg !10 {
+entry:
+  %p = alloca ptr addrspace(4), align 8
+    #dbg_declare(ptr %p, !11, !DIExpression(DW_OP_constu, 0, DW_OP_swap, DW_OP_xderef), !14)
+  ret void
+}
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!2, !3, !4, !5}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None)
+!1 = !DIFile(filename: "debug-type-pointer-composite-pointee.c", directory: "/src", checksumkind: CSK_MD5, checksum: "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF")
+!2 = !{i32 7, !"Dwarf Version", i32 5}
+!3 = !{i32 2, !"Debug Info Version", i32 3}
+!4 = !{i32 1, !"wchar_size", i32 4}
+!5 = !{i32 7, !"frame-pointer", i32 2}
+
+!6 = !DISubroutineType(cc: DW_CC_LLVM_SpirFunction, types: !7)
+!7 = !{null}
+!8 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!9 = !DICompositeType(tag: DW_TAG_array_type, baseType: !8, size: 256, elements: !12)
+!12 = !{!13}
+!13 = !DISubrange(count: 8)
+
+!10 = distinct !DISubprogram(name: "ptr_to_array", linkageName: "ptr_to_array", scope: !1, file: !1, line: 1, type: !6, scopeLine: 1, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !15)
+!15 = !{}
+!11 = !DILocalVariable(name: "pa", scope: !10, file: !1, line: 2, type: !16)
+!16 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !9, size: 64, dwarfAddressSpace: 4)
+!14 = !DILocation(line: 2, column: 5, scope: !10)

diff  --git a/llvm/test/CodeGen/X86/mbp-false-cfg-break.ll b/llvm/test/CodeGen/X86/mbp-false-cfg-break.ll
index fc2549153321e..aeb558dbd5eaa 100644
--- a/llvm/test/CodeGen/X86/mbp-false-cfg-break.ll
+++ b/llvm/test/CodeGen/X86/mbp-false-cfg-break.ll
@@ -28,7 +28,7 @@ backedge:
   call void @foo()
   %iv.next = add i32 %iv, 1
   %cmp = icmp eq i32 %iv.next, 200
-  br i1 %cmp, label %loop, label %exit, !prof !{!"branch_weights", i32 1000, i32 1}
+  br i1 %cmp, label %exit, label %loop, !prof !{!"branch_weights", i32 1, i32 1000}
 
 exit:
   ret void

diff  --git a/llvm/test/MC/AMDGPU/gfx1250_asm_vimage.s b/llvm/test/MC/AMDGPU/gfx1250_asm_vimage.s
index f799a54fdc775..48e61e4f6303e 100644
--- a/llvm/test/MC/AMDGPU/gfx1250_asm_vimage.s
+++ b/llvm/test/MC/AMDGPU/gfx1250_asm_vimage.s
@@ -26,6 +26,18 @@ tensor_store_from_lds s[0:3], s[4:11] th:TH_STORE_BYPASS scope:SCOPE_SYS
 // GFX12-ERR: :[[@LINE-1]]:1: error: instruction not supported on this GPU (gfx1200): tensor_store_from_lds
 // GFX1250: tensor_store_from_lds s[0:3], s[4:11] th:TH_STORE_BYPASS scope:SCOPE_SYS ; encoding: [0x01,0x40,0x71,0xd0,0x00,0x00,0x3c,0x7c,0x00,0x04,0x7c,0x7c]
 
+tensor_store_from_lds s[0:3], s[4:11], null, null th:TH_STORE_NT_HT scope:SCOPE_DEV
+// GFX12-ERR: :[[@LINE-1]]:1: error: instruction not supported on this GPU (gfx1200): tensor_store_from_lds
+// GFX1250: tensor_store_from_lds s[0:3], s[4:11], null, null th:TH_STORE_NT_HT scope:SCOPE_DEV ; encoding: [0x01,0x40,0x71,0xd0,0x00,0x00,0x68,0x7c,0x00,0x04,0x7c,0x7c]
+
+tensor_store_from_lds s[0:3], s[4:11], null, s[16:19] th:TH_STORE_NT_HT scope:SCOPE_DEV
+// GFX12-ERR: :[[@LINE-1]]:1: error: instruction not supported on this GPU (gfx1200): tensor_store_from_lds
+// GFX1250: tensor_store_from_lds s[0:3], s[4:11], null, s[16:19] th:TH_STORE_NT_HT scope:SCOPE_DEV ; encoding: [0x01,0x40,0x71,0xd0,0x00,0x00,0x68,0x7c,0x00,0x04,0x7c,0x10]
+
+tensor_store_from_lds s[0:3], s[4:11], s[12:15], null th:TH_STORE_NT_HT scope:SCOPE_DEV
+// GFX12-ERR: :[[@LINE-1]]:1: error: instruction not supported on this GPU (gfx1200): tensor_store_from_lds
+// GFX1250: tensor_store_from_lds s[0:3], s[4:11], s[12:15], null th:TH_STORE_NT_HT scope:SCOPE_DEV ; encoding: [0x01,0x40,0x71,0xd0,0x00,0x00,0x68,0x7c,0x00,0x04,0x0c,0x7c]
+
 tensor_store_from_lds s[0:3], s[4:11], s[12:15], s[16:19]
 // GFX12-ERR: :[[@LINE-1]]:1: error: instruction not supported on this GPU (gfx1200): tensor_store_from_lds
 // GFX1250: tensor_store_from_lds s[0:3], s[4:11], s[12:15], s[16:19] ; encoding: [0x01,0x40,0x71,0xd0,0x00,0x00,0x00,0x7c,0x00,0x04,0x0c,0x10]

diff  --git a/llvm/test/MC/AMDGPU/gfx1250_asm_vimage_err.s b/llvm/test/MC/AMDGPU/gfx1250_asm_vimage_err.s
index 2f911ae79c00f..d9f5b8047e701 100644
--- a/llvm/test/MC/AMDGPU/gfx1250_asm_vimage_err.s
+++ b/llvm/test/MC/AMDGPU/gfx1250_asm_vimage_err.s
@@ -37,12 +37,6 @@ tensor_load_to_lds null, s[4:11], s[12:15], s[16:19]
 tensor_load_to_lds s[0:3], null, s[12:15], s[16:19]
 // GFX1250-ERR: :[[@LINE-1]]:28: error: invalid operand for instruction
 
-tensor_load_to_lds s[0:3], s[4:11], null, s[16:19]
-// GFX1250-ERR: :[[@LINE-1]]:37: error: invalid operand for instruction
-
-tensor_load_to_lds s[0:3], s[4:11], s[12:15], null
-// GFX1250-ERR: :[[@LINE-1]]:47: error: invalid operand for instruction
-
 tensor_store_from_lds null, s[4:11]
 // GFX1250-ERR: :[[@LINE-1]]:23: error: invalid operand for instruction
 
@@ -55,12 +49,6 @@ tensor_store_from_lds null, s[4:11], s[12:15], s[16:19]
 tensor_store_from_lds s[0:3], null, s[12:15], s[16:19]
 // GFX1250-ERR: :[[@LINE-1]]:31: error: invalid operand for instruction
 
-tensor_store_from_lds s[0:3], s[4:11], null, s[16:19]
-// GFX1250-ERR: :[[@LINE-1]]:40: error: invalid operand for instruction
-
-tensor_store_from_lds s[0:3], s[4:11], s[12:15], null
-// GFX1250-ERR: :[[@LINE-1]]:50: error: invalid operand for instruction
-
 tensor_load_to_lds s[14:17], s[4:11]
 // GFX1250-ERR: :[[@LINE-1]]:20: error: invalid register alignment
 

diff  --git a/llvm/test/MC/Disassembler/AMDGPU/gfx1250_dasm_vimage.txt b/llvm/test/MC/Disassembler/AMDGPU/gfx1250_dasm_vimage.txt
index a2132f1138969..0bc505e848741 100644
--- a/llvm/test/MC/Disassembler/AMDGPU/gfx1250_dasm_vimage.txt
+++ b/llvm/test/MC/Disassembler/AMDGPU/gfx1250_dasm_vimage.txt
@@ -19,6 +19,15 @@
 0x01,0x40,0x71,0xd0,0x00,0x00,0x3c,0x7c,0x00,0x04,0x7c,0x7c
 # GFX1250: tensor_store_from_lds s[0:3], s[4:11] th:TH_STORE_BYPASS scope:SCOPE_SYS ; encoding: [0x01,0x40,0x71,0xd0,0x00,0x00,0x3c,0x7c,0x00,0x04,0x7c,0x7c]
 
+0x01,0x40,0x71,0xd0,0x00,0x00,0x68,0x7c,0x00,0x04,0x7c,0x7c
+# GFX1250: tensor_store_from_lds s[0:3], s[4:11] th:TH_STORE_NT_HT scope:SCOPE_DEV ; encoding: [0x01,0x40,0x71,0xd0,0x00,0x00,0x68,0x7c,0x00,0x04,0x7c,0x7c]
+
+0x01,0x40,0x71,0xd0,0x00,0x00,0x68,0x7c,0x00,0x04,0x7c,0x10
+# GFX1250: tensor_store_from_lds s[0:3], s[4:11], null, s[16:19] th:TH_STORE_NT_HT scope:SCOPE_DEV ; encoding: [0x01,0x40,0x71,0xd0,0x00,0x00,0x68,0x7c,0x00,0x04,0x7c,0x10]
+
+0x01,0x40,0x71,0xd0,0x00,0x00,0x68,0x7c,0x00,0x04,0x0c,0x7c
+# GFX1250: tensor_store_from_lds s[0:3], s[4:11], s[12:15], null th:TH_STORE_NT_HT scope:SCOPE_DEV ; encoding: [0x01,0x40,0x71,0xd0,0x00,0x00,0x68,0x7c,0x00,0x04,0x0c,0x7c]
+
 0x01,0x40,0x71,0xd0,0x00,0x00,0x00,0x7c,0x00,0x04,0x0c,0x10
 # GFX1250: tensor_store_from_lds s[0:3], s[4:11], s[12:15], s[16:19] ; encoding: [0x01,0x40,0x71,0xd0,0x00,0x00,0x00,0x7c,0x00,0x04,0x0c,0x10]
 

diff  --git a/llvm/test/Transforms/InstCombine/ptr-replace-alloca.ll b/llvm/test/Transforms/InstCombine/ptr-replace-alloca.ll
index f084fe38bb226..3490773b03b82 100644
--- a/llvm/test/Transforms/InstCombine/ptr-replace-alloca.ll
+++ b/llvm/test/Transforms/InstCombine/ptr-replace-alloca.ll
@@ -481,6 +481,26 @@ define i8 @call_readonly_keep_alloca2() {
   ret i8 %v
 }
 
+; The pointer changes but the load type doesn't, so all metadata (here
+; !annotation, which the type-changing copyMetadataForLoad would drop) must be
+; preserved.
+ at g3 = external constant [32 x i8], align 16
+
+define i8 @preserve_load_metadata(i64 %idx) {
+; CHECK-LABEL: @preserve_load_metadata(
+; CHECK-NEXT:    [[PTR:%.*]] = getelementptr inbounds i8, ptr @g3, i64 [[IDX:%.*]]
+; CHECK-NEXT:    [[LOAD:%.*]] = load i8, ptr [[PTR]], align 1, !annotation [[META0:![0-9]+]]
+; CHECK-NEXT:    ret i8 [[LOAD]]
+;
+  %alloca = alloca [32 x i8], align 1, addrspace(1)
+  call void @llvm.memcpy.p1.p0.i64(ptr addrspace(1) %alloca, ptr @g3, i64 32, i1 false)
+  %ptr = getelementptr inbounds [32 x i8], ptr addrspace(1) %alloca, i64 0, i64 %idx
+  %load = load i8, ptr addrspace(1) %ptr, !annotation !0
+  ret i8 %load
+}
+
+!0 = !{!"my-annotation"}
+
 declare void @llvm.memcpy.p1.p0.i64(ptr addrspace(1), ptr, i64, i1)
 declare void @llvm.memcpy.p0.p0.i64(ptr, ptr, i64, i1)
 declare void @llvm.memcpy.p0.p1.i64(ptr, ptr addrspace(1), i64, i1)

diff  --git a/llvm/test/Transforms/LoopStrengthReduce/X86/pr62660-normalization-failure.ll b/llvm/test/Transforms/LoopStrengthReduce/X86/pr62660-normalization-failure.ll
index e6ee9b467c5e0..8abd0b977ba05 100644
--- a/llvm/test/Transforms/LoopStrengthReduce/X86/pr62660-normalization-failure.ll
+++ b/llvm/test/Transforms/LoopStrengthReduce/X86/pr62660-normalization-failure.ll
@@ -83,7 +83,7 @@ define void @pr63840_crash(i64 %sext974, i64 %sext982, i8 %x) {
 ; CHECK-NEXT:    [[PHI1094]] = phi i64 [ [[LSR_IV_NEXT8_LCSSA]], [[BB992]] ], [ [[ADD1054]], [[BB1059]] ]
 ; CHECK-NEXT:    [[LSR_IV_NEXT]] = add nsw i64 [[LSR_IV]], 1
 ; CHECK-NEXT:    [[LSR_IV_NEXT4]] = add i64 [[LSR_IV3]], [[SEXT1046]]
-; CHECK-NEXT:    [[ICMP1050:%.*]] = icmp ult i64 [[LSR_IV_NEXT]], 0
+; CHECK-NEXT:    [[ICMP1050:%.*]] = icmp ugt i64 [[LSR_IV_NEXT]], 0
 ; CHECK-NEXT:    br i1 [[ICMP1050]], label [[BB1053:%.*]], label [[BB1051:%.*]]
 ;
 bb:
@@ -120,6 +120,6 @@ bb1064:                                           ; preds = %bb1059, %bb1053
 bb1092:                                           ; preds = %bb1059, %bb992
   %phi1093 = phi i64 [ 0, %bb992 ], [ %add1060, %bb1059 ]
   %phi1094 = phi i64 [ %add1047, %bb992 ], [ %add1054, %bb1059 ]
-  %icmp1050 = icmp ult i64 %phi1093, 0
+  %icmp1050 = icmp ugt i64 %phi1093, 0
   br i1 %icmp1050, label %bb1053, label %bb1051
 }

diff  --git a/llvm/test/tools/llubi/call_unknown.ll b/llvm/test/tools/llubi/call_unknown.ll
new file mode 100644
index 0000000000000..7943385809025
--- /dev/null
+++ b/llvm/test/tools/llubi/call_unknown.ll
@@ -0,0 +1,12 @@
+; NOTE: Assertions have been autogenerated by utils/update_llubi_test_checks.py UTC_ARGS: --version 6
+; RUN: not llubi --verbose < %s 2>&1 | FileCheck %s
+
+declare i32 @unknown()
+
+define i32 @main() {
+  %res = call i32 @unknown()
+  ret i32 %res
+}
+; CHECK: Entering function: main
+; CHECK-NEXT: Unrecognized instruction:   %res = call i32 @unknown()
+; CHECK-NEXT: error: Execution of function 'main' failed.

diff  --git a/llvm/tools/llubi/lib/Interpreter.cpp b/llvm/tools/llubi/lib/Interpreter.cpp
index 81cc968535a2f..90d1966422a4c 100644
--- a/llvm/tools/llubi/lib/Interpreter.cpp
+++ b/llvm/tools/llubi/lib/Interpreter.cpp
@@ -168,6 +168,8 @@ class InstExecutor : public InstVisitor<InstExecutor, void>,
   void setResult(Instruction &I, AnyValue V) {
     if (!hasProgramExited() && !Handler.onInstructionExecuted(I, V))
       setFailed();
+    if (hasProgramExited())
+      return;
     assert(V.isCompatibleWith(I.getType()) && "Unexpected value storage kind.");
     if (!V.isNone())
       CurrentFrame->ValueMap.insert_or_assign(&I, std::move(V));


        


More information about the llvm-branch-commits mailing list