[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