public inbox for [email protected]
help / color / mirror / Atom feedLLVM 22
5+ messages / 2 participants
[nested] [flat]
* LLVM 22
@ 2026-01-03 02:02 Thomas Munro <[email protected]>
0 siblings, 2 replies; 5+ messages in thread
From: Thomas Munro @ 2026-01-03 02:02 UTC (permalink / raw)
To: PostgreSQL Hackers <[email protected]>
Hi,
Ideally we should have all changes for LLVM 22 in our February minor
releases. I have written up some notes on release synchronisation on
the wiki[1] to show the scheduling problem if we don't. The second
patch here still needs some validation.
1. We won't need our local llvm::backport::SectionMemoryManager for
LLVM 22, so it will be nice to draw a line under that messy business.
See commit message for details.
You can review the differences between our in-tree copy and the code
that was finally committed and will shortly ship in LLVM 22 like this:
LLVM_BRANCH=main
LLVM_URL=https://raw.githubusercontent.com/llvm/llvm-project/refs/heads
curl -s \
$LLVM_URL/$LLVM_BRANCH/llvm/include/llvm/ExecutionEngine/SectionMemoryManager.h
| \
diff -u - src/include/jit/SectionMemoryManager.h
curl -s \
$LLVM_URL/$LLVM_BRANCH/llvm/lib/ExecutionEngine/SectionMemoryManager.cpp | \
diff -u - src/backend/jit/llvm/SectionMemoryManager.cpp
In a week or two, LLVM_BRANCH=release/22.x should work too. I've
attached the output, which shows the expected changes in our copy,
namely:
* top-of-file comments
* namespace change
* tweaks for older LLVM versions
* tree-wide spellchecks and #include "" -> <> changes
They haven't made any changes on their side, except for adding some
LLVM_ABI macros added in LLVM 20 that we missed. See commit message
for why we don't want those.
The place in llvmjit_backport.h that does:
-#if defined(__aarch64__)
+#if defined(__aarch64__) && LLVM_VERSION_MAJOR < 22
#define USE_LLVM_BACKPORT_SECTION_MEMORY_MANAGER
... would be like this in REL_17_STABLE and earlier:
+#if defined(__aarch64__) && LLVM_VERSION_MAJOR > 11 && LLVM_VERSION_MAJOR < 22
That's because we never made the backport work with LLVM < 12, and I
have heard no complaints about that so at this point it looks like we
got away with it.
2. LLVM 22 changed the semantics of the "lifetime.end" instruction.
See commit message for references. Without this change, LLVM main/22
assertions fail in the regression tests with messages like this in
postmaster.log:
Intrinsic has incorrect argument type!
ptr @llvm.lifetime.end.p0
Intrinsic has incorrect argument type!
ptr @llvm.lifetime.end.p0
2026-01-02 17:28:31.394 NZDT client backend[42798] pg_regress/boolean
FATAL: fatal llvm error: Broken module found, compilation aborted!
I haven't seen anything bad happen in non-assertion builds.
Here's a potential minimal fix. I haven't yet proven that the
optimisation is still working as expected. Probably need to compile
an expression that calls an inlined function and then a non-inlined
function with jit_dump_bitcode=true, then find the right XXX.bc file
under pgdata, llvm-dis XXX.bc, llc XXX.ll, then visually inspect XXX.s
with enough caffeine to confirm that it's not spilling something (ie
store instructions) where previously it didn't, but I wanted to post
what I had so far to see if anyone has a better idea or an easy way to
test it...
[1] https://wiki.postgresql.org/wiki/LLVM#Cadence
--- - 2026-01-02 17:03:43.795228000 +1300
+++ src/include/jit/SectionMemoryManager.h 2026-01-02 16:52:50.352095000 +1300
@@ -1,3 +1,8 @@
+/*
+ * This is a copy of LLVM source code modified by the PostgreSQL project.
+ * See SectionMemoryManager.cpp for notes on provenance and license.
+ */
+
//===- SectionMemoryManager.h - Memory manager for MCJIT/RtDyld -*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
@@ -11,18 +16,19 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_EXECUTIONENGINE_SECTIONMEMORYMANAGER_H
-#define LLVM_EXECUTIONENGINE_SECTIONMEMORYMANAGER_H
+#ifndef LLVM_EXECUTIONENGINE_BACKPORT_SECTIONMEMORYMANAGER_H
+#define LLVM_EXECUTIONENGINE_BACKPORT_SECTIONMEMORYMANAGER_H
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/ExecutionEngine/RTDyldMemoryManager.h"
-#include "llvm/Support/Compiler.h"
-#include "llvm/Support/Memory.h"
+#include <llvm/ADT/SmallVector.h>
+#include <llvm/ExecutionEngine/RTDyldMemoryManager.h>
+#include <llvm/Support/Alignment.h>
+#include <llvm/Support/Memory.h>
#include <cstdint>
#include <string>
#include <system_error>
namespace llvm {
+namespace backport {
/// This is a simple memory manager which implements the methods called by
/// the RuntimeDyld class to allocate memory for section-based loading of
@@ -37,7 +43,7 @@
/// in the JITed object. Permissions can be applied either by calling
/// MCJIT::finalizeObject or by calling SectionMemoryManager::finalizeMemory
/// directly. Clients of MCJIT should call MCJIT::finalizeObject.
-class LLVM_ABI SectionMemoryManager : public RTDyldMemoryManager {
+class SectionMemoryManager : public RTDyldMemoryManager {
public:
/// This enum describes the various reasons to allocate pages from
/// allocateMappedMemory.
@@ -49,7 +55,7 @@
/// Implementations of this interface are used by SectionMemoryManager to
/// request pages from the operating system.
- class LLVM_ABI MemoryMapper {
+ class MemoryMapper {
public:
/// This method attempts to allocate \p NumBytes bytes of virtual memory for
/// \p Purpose. \p NearBlock may point to an existing allocation, in which
@@ -119,9 +125,17 @@
/// Implements allocating all memory in a single block. This is required to
/// limit memory offsets to fit the ARM ABI; large memory systems may
/// otherwise allocate separate sections too far apart.
+#if LLVM_VERSION_MAJOR < 16
+ virtual void reserveAllocationSpace(uintptr_t CodeSize, uint32_t CodeAlign,
+ uintptr_t RODataSize,
+ uint32_t RODataAlign,
+ uintptr_t RWDataSize,
+ uint32_t RWDataAlign) override;
+#else
void reserveAllocationSpace(uintptr_t CodeSize, Align CodeAlign,
uintptr_t RODataSize, Align RODataAlign,
uintptr_t RWDataSize, Align RWDataAlign) override;
+#endif
/// Allocates a memory block of (at least) the given size suitable for
/// executable code.
@@ -139,7 +153,7 @@
/// a default alignment of 16 will be used.
uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,
unsigned SectionID, StringRef SectionName,
- bool isReadOnly) override;
+ bool IsReadOnly) override;
/// Update section-specific memory permissions and other attributes.
///
@@ -168,7 +182,7 @@
// The actual block of free memory
sys::MemoryBlock Free;
// If there is a pending allocation from the same reservation right before
- // this block, store it's index in PendingMem, to be able to update the
+ // this block, store its index in PendingMem, to be able to update the
// pending region if part of this block is allocated, rather than having to
// create a new one
unsigned PendingPrefixIndex;
@@ -206,6 +220,7 @@
bool ReserveAllocation;
};
+} // end namespace backport
} // end namespace llvm
-#endif // LLVM_EXECUTIONENGINE_SECTIONMEMORYMANAGER_H
+#endif // LLVM_EXECUTIONENGINE_BACKPORT_SECTIONMEMORYMANAGER_H
--- - 2026-01-02 17:03:57.672285000 +1300
+++ src/backend/jit/llvm/SectionMemoryManager.cpp 2026-01-02 16:52:50.351938000 +1300
@@ -1,3 +1,19 @@
+/*
+ * This file is from LLVM 22 (originally pull request #71968), with minor
+ * modifications to avoid name clash and work with older LLVM versions. It
+ * replaces llvm::SectionMemoryManager, and is injected into llvm::RuntimeDyld
+ * to fix a memory layout bug on large memory ARM systems on LLVM < 22.
+ *
+ * We can remove this code (.cpp, .h, .LICENSE) once LLVM 22 is our minimum
+ * supported version or we've switched to JITLink for at least Aarch64.
+ *
+ * This file is a modified copy of a part of the LLVM source code that
+ * we would normally access from the LLVM library. It is therefore
+ * covered by the license at https://llvm.org/LICENSE.txt, reproduced
+ * verbatim in SectionMemoryManager.LICENSE in fulfillment of clause
+ * 4a.
+ */
+
//===- SectionMemoryManager.cpp - Memory manager for MCJIT/RtDyld *- C++ -*-==//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
@@ -11,11 +27,16 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/ExecutionEngine/SectionMemoryManager.h"
-#include "llvm/Config/config.h"
-#include "llvm/Support/Process.h"
+#include "jit/llvmjit_backport.h"
+#ifdef USE_LLVM_BACKPORT_SECTION_MEMORY_MANAGER
+
+#include "jit/SectionMemoryManager.h"
+#include <llvm/Support/MathExtras.h>
+#include <llvm/Support/Process.h>
+
namespace llvm {
+namespace backport {
bool SectionMemoryManager::hasSpace(const MemoryGroup &MemGroup,
uintptr_t Size) const {
@@ -26,9 +47,21 @@
return false;
}
+#if LLVM_VERSION_MAJOR < 16
+void SectionMemoryManager::reserveAllocationSpace(uintptr_t CodeSize,
+ uint32_t CodeAlign_i,
+ uintptr_t RODataSize,
+ uint32_t RODataAlign_i,
+ uintptr_t RWDataSize,
+ uint32_t RWDataAlign_i) {
+ Align CodeAlign(CodeAlign_i);
+ Align RODataAlign(RODataAlign_i);
+ Align RWDataAlign(RWDataAlign_i);
+#else
void SectionMemoryManager::reserveAllocationSpace(
uintptr_t CodeSize, Align CodeAlign, uintptr_t RODataSize,
Align RODataAlign, uintptr_t RWDataSize, Align RWDataAlign) {
+#endif
if (CodeSize == 0 && RODataSize == 0 && RWDataSize == 0)
return;
@@ -365,4 +398,7 @@
}
}
+} // namespace backport
} // namespace llvm
+
+#endif
Attachments:
[text/plain] SectionMemoryManager-diff.txt (6.8K, 2-SectionMemoryManager-diff.txt)
download | inline:
--- - 2026-01-02 17:03:43.795228000 +1300
+++ src/include/jit/SectionMemoryManager.h 2026-01-02 16:52:50.352095000 +1300
@@ -1,3 +1,8 @@
+/*
+ * This is a copy of LLVM source code modified by the PostgreSQL project.
+ * See SectionMemoryManager.cpp for notes on provenance and license.
+ */
+
//===- SectionMemoryManager.h - Memory manager for MCJIT/RtDyld -*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
@@ -11,18 +16,19 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_EXECUTIONENGINE_SECTIONMEMORYMANAGER_H
-#define LLVM_EXECUTIONENGINE_SECTIONMEMORYMANAGER_H
+#ifndef LLVM_EXECUTIONENGINE_BACKPORT_SECTIONMEMORYMANAGER_H
+#define LLVM_EXECUTIONENGINE_BACKPORT_SECTIONMEMORYMANAGER_H
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/ExecutionEngine/RTDyldMemoryManager.h"
-#include "llvm/Support/Compiler.h"
-#include "llvm/Support/Memory.h"
+#include <llvm/ADT/SmallVector.h>
+#include <llvm/ExecutionEngine/RTDyldMemoryManager.h>
+#include <llvm/Support/Alignment.h>
+#include <llvm/Support/Memory.h>
#include <cstdint>
#include <string>
#include <system_error>
namespace llvm {
+namespace backport {
/// This is a simple memory manager which implements the methods called by
/// the RuntimeDyld class to allocate memory for section-based loading of
@@ -37,7 +43,7 @@
/// in the JITed object. Permissions can be applied either by calling
/// MCJIT::finalizeObject or by calling SectionMemoryManager::finalizeMemory
/// directly. Clients of MCJIT should call MCJIT::finalizeObject.
-class LLVM_ABI SectionMemoryManager : public RTDyldMemoryManager {
+class SectionMemoryManager : public RTDyldMemoryManager {
public:
/// This enum describes the various reasons to allocate pages from
/// allocateMappedMemory.
@@ -49,7 +55,7 @@
/// Implementations of this interface are used by SectionMemoryManager to
/// request pages from the operating system.
- class LLVM_ABI MemoryMapper {
+ class MemoryMapper {
public:
/// This method attempts to allocate \p NumBytes bytes of virtual memory for
/// \p Purpose. \p NearBlock may point to an existing allocation, in which
@@ -119,9 +125,17 @@
/// Implements allocating all memory in a single block. This is required to
/// limit memory offsets to fit the ARM ABI; large memory systems may
/// otherwise allocate separate sections too far apart.
+#if LLVM_VERSION_MAJOR < 16
+ virtual void reserveAllocationSpace(uintptr_t CodeSize, uint32_t CodeAlign,
+ uintptr_t RODataSize,
+ uint32_t RODataAlign,
+ uintptr_t RWDataSize,
+ uint32_t RWDataAlign) override;
+#else
void reserveAllocationSpace(uintptr_t CodeSize, Align CodeAlign,
uintptr_t RODataSize, Align RODataAlign,
uintptr_t RWDataSize, Align RWDataAlign) override;
+#endif
/// Allocates a memory block of (at least) the given size suitable for
/// executable code.
@@ -139,7 +153,7 @@
/// a default alignment of 16 will be used.
uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,
unsigned SectionID, StringRef SectionName,
- bool isReadOnly) override;
+ bool IsReadOnly) override;
/// Update section-specific memory permissions and other attributes.
///
@@ -168,7 +182,7 @@
// The actual block of free memory
sys::MemoryBlock Free;
// If there is a pending allocation from the same reservation right before
- // this block, store it's index in PendingMem, to be able to update the
+ // this block, store its index in PendingMem, to be able to update the
// pending region if part of this block is allocated, rather than having to
// create a new one
unsigned PendingPrefixIndex;
@@ -206,6 +220,7 @@
bool ReserveAllocation;
};
+} // end namespace backport
} // end namespace llvm
-#endif // LLVM_EXECUTIONENGINE_SECTIONMEMORYMANAGER_H
+#endif // LLVM_EXECUTIONENGINE_BACKPORT_SECTIONMEMORYMANAGER_H
--- - 2026-01-02 17:03:57.672285000 +1300
+++ src/backend/jit/llvm/SectionMemoryManager.cpp 2026-01-02 16:52:50.351938000 +1300
@@ -1,3 +1,19 @@
+/*
+ * This file is from LLVM 22 (originally pull request #71968), with minor
+ * modifications to avoid name clash and work with older LLVM versions. It
+ * replaces llvm::SectionMemoryManager, and is injected into llvm::RuntimeDyld
+ * to fix a memory layout bug on large memory ARM systems on LLVM < 22.
+ *
+ * We can remove this code (.cpp, .h, .LICENSE) once LLVM 22 is our minimum
+ * supported version or we've switched to JITLink for at least Aarch64.
+ *
+ * This file is a modified copy of a part of the LLVM source code that
+ * we would normally access from the LLVM library. It is therefore
+ * covered by the license at https://llvm.org/LICENSE.txt, reproduced
+ * verbatim in SectionMemoryManager.LICENSE in fulfillment of clause
+ * 4a.
+ */
+
//===- SectionMemoryManager.cpp - Memory manager for MCJIT/RtDyld *- C++ -*-==//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
@@ -11,11 +27,16 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/ExecutionEngine/SectionMemoryManager.h"
-#include "llvm/Config/config.h"
-#include "llvm/Support/Process.h"
+#include "jit/llvmjit_backport.h"
+#ifdef USE_LLVM_BACKPORT_SECTION_MEMORY_MANAGER
+
+#include "jit/SectionMemoryManager.h"
+#include <llvm/Support/MathExtras.h>
+#include <llvm/Support/Process.h>
+
namespace llvm {
+namespace backport {
bool SectionMemoryManager::hasSpace(const MemoryGroup &MemGroup,
uintptr_t Size) const {
@@ -26,9 +47,21 @@
return false;
}
+#if LLVM_VERSION_MAJOR < 16
+void SectionMemoryManager::reserveAllocationSpace(uintptr_t CodeSize,
+ uint32_t CodeAlign_i,
+ uintptr_t RODataSize,
+ uint32_t RODataAlign_i,
+ uintptr_t RWDataSize,
+ uint32_t RWDataAlign_i) {
+ Align CodeAlign(CodeAlign_i);
+ Align RODataAlign(RODataAlign_i);
+ Align RWDataAlign(RWDataAlign_i);
+#else
void SectionMemoryManager::reserveAllocationSpace(
uintptr_t CodeSize, Align CodeAlign, uintptr_t RODataSize,
Align RODataAlign, uintptr_t RWDataSize, Align RWDataAlign) {
+#endif
if (CodeSize == 0 && RODataSize == 0 && RWDataSize == 0)
return;
@@ -365,4 +398,7 @@
}
}
+} // namespace backport
} // namespace llvm
+
+#endif
[text/x-patch] 0001-jit-Skip-local-SectionMemoryManager-for-LLVM-22.patch (4.7K, 3-0001-jit-Skip-local-SectionMemoryManager-for-LLVM-22.patch)
download | inline diff:
From ae70eea20a9173502c5ffc97a6c85741e0b922e1 Mon Sep 17 00:00:00 2001
From: Thomas Munro <[email protected]>
Date: Wed, 31 Dec 2025 17:35:04 +1300
Subject: [PATCH 1/2] jit: Skip local SectionMemoryManager for LLVM 22.
Now that LLVM has committed[1] the bug fix that we slurped into the tree
in commit 9044fc1d, we only need to use our local copy for LLVM < 22.
This avoids further maintenance burden (cf 0dceba21), and also
establishes a garbage collection horizon that will let us delete our
copy when the time comes.
The only change that we don't have from the version that was committed
is the addition of a LLVM_ABI macro to control shared library exports,
but that isn't defined before LLVM 20 (our copy has to work with earlier
versions), and isn't appropriate here as our copy is private and in our
own library.
Also adjust the comments to explain that this is the code from LLVM 22.
Historical details about the pull request are now irrelevant.
[1] https://github.com/llvm/llvm-project/commit/1922c6ca262311bf321d33997471917adcdfbaef
Backpatch-through: 14
Reviewed-by:
Discussion:
---
src/backend/jit/llvm/SectionMemoryManager.cpp | 22 ++++++-------------
src/include/jit/SectionMemoryManager.h | 2 +-
src/include/jit/llvmjit_backport.h | 4 ++--
3 files changed, 10 insertions(+), 18 deletions(-)
diff --git a/src/backend/jit/llvm/SectionMemoryManager.cpp b/src/backend/jit/llvm/SectionMemoryManager.cpp
index 2171db5f382..e113ce81a3d 100644
--- a/src/backend/jit/llvm/SectionMemoryManager.cpp
+++ b/src/backend/jit/llvm/SectionMemoryManager.cpp
@@ -1,25 +1,17 @@
/*
- * This file is from https://github.com/llvm/llvm-project/pull/71968
- * with minor modifications to avoid name clash and work with older
- * LLVM versions. The llvm::backport::SectionMemoryManager class is a
- * drop-in replacement for llvm::SectionMemoryManager, for use with
- * llvm::RuntimeDyld. It fixes a memory layout bug on large memory
- * ARM systems (see pull request for details). If the LLVM project
- * eventually commits the change, we may need to resynchronize our
- * copy with any further modifications, but they would be unlikely to
- * backport it into the LLVM versions that we target so we would still
- * need this copy.
+ * This file is from LLVM 22 (originally pull request #71968), with minor
+ * modifications to avoid name clash and work with older LLVM versions. It
+ * replaces llvm::SectionMemoryManager, and is injected into llvm::RuntimeDyld
+ * to fix a memory layout bug on large memory ARM systems on LLVM < 22.
*
- * In the future we will switch to using JITLink instead of
- * RuntimeDyld where possible, and later remove this code (.cpp, .h,
- * .LICENSE) after all LLVM versions that we target allow it.
+ * We can remove this code (.cpp, .h, .LICENSE) once LLVM 22 is our minimum
+ * supported version or we've switched to JITLink for at least Aarch64.
*
* This file is a modified copy of a part of the LLVM source code that
* we would normally access from the LLVM library. It is therefore
* covered by the license at https://llvm.org/LICENSE.txt, reproduced
* verbatim in SectionMemoryManager.LICENSE in fulfillment of clause
- * 4a. The bugfix changes from the pull request are also covered, per
- * clause 5.
+ * 4a.
*/
//===- SectionMemoryManager.cpp - Memory manager for MCJIT/RtDyld *- C++ -*-==//
diff --git a/src/include/jit/SectionMemoryManager.h b/src/include/jit/SectionMemoryManager.h
index 924a99b0d33..4c9bd1c7f01 100644
--- a/src/include/jit/SectionMemoryManager.h
+++ b/src/include/jit/SectionMemoryManager.h
@@ -1,5 +1,5 @@
/*
- * This is a copy LLVM source code modified by the PostgreSQL project.
+ * This is a copy of LLVM source code modified by the PostgreSQL project.
* See SectionMemoryManager.cpp for notes on provenance and license.
*/
diff --git a/src/include/jit/llvmjit_backport.h b/src/include/jit/llvmjit_backport.h
index cba8eafc4f3..71cfdfc832f 100644
--- a/src/include/jit/llvmjit_backport.h
+++ b/src/include/jit/llvmjit_backport.h
@@ -8,14 +8,14 @@
#include <llvm/Config/llvm-config.h>
/*
- * LLVM's RuntimeDyld can produce code that crashes on larger memory ARM
+ * Pre-LLVM 22 RuntimeDyld can produce code that crashes on large memory ARM
* systems, because llvm::SectionMemoryManager allocates multiple pieces of
* memory that can be placed too far apart for the generated code. See
* src/backend/jit/llvm/SectionMemoryManager.cpp for the patched replacement
* class llvm::backport::SectionMemoryManager that we use as a workaround.
* This header controls whether we use it.
*/
-#if defined(__aarch64__)
+#if defined(__aarch64__) && LLVM_VERSION_MAJOR < 22
#define USE_LLVM_BACKPORT_SECTION_MEMORY_MANAGER
#endif
--
2.52.0
[text/x-patch] 0002-jit-API-changes-for-LLVM-22.patch (3.7K, 4-0002-jit-API-changes-for-LLVM-22.patch)
download | inline diff:
From 72a6e3d4040cde58e26a27febbf48671f025e056 Mon Sep 17 00:00:00 2001
From: Thomas Munro <[email protected]>
Date: Wed, 19 Nov 2025 00:00:13 +1300
Subject: [PATCH 2/2] jit: API changes for LLVM 22.
The lifetime.end intrinsic can now only be used for stack memory
allocated with alloca. We were using it to tell the optimizer that we
are no longer interested in the arguments and null flag in a
FunctionCallInfo struct, so it could avoid actually storing them if it
managed to inline the function and keep everything in registers. It
can't figure that out by itself because it's part of the ExecEvalStep
struct and we scribble on it directly rather than building a new one on
the stack.
Instead, store the special poison value (undef would work too). This
generates no actual code, but tells the optimizer that we are not
interested in the values.
Deform functions use LLVMBuildAlloca() for a stack variable, but that
memory is reclaimed implicitly by the ret instruction. This code should
probably do the same, but the change is non-trivial and not studied yet.
https://github.com/llvm/llvm-project/pull/149310
https://llvm.org/docs/LangRef.html#llvm-lifetime-end-intrinsic
https://llvm.org/docs/LangRef.html#i-alloca
---
src/backend/jit/llvm/llvmjit_expr.c | 18 +++++++++++++-----
1 file changed, 13 insertions(+), 5 deletions(-)
diff --git a/src/backend/jit/llvm/llvmjit_expr.c b/src/backend/jit/llvm/llvmjit_expr.c
index f9c7f29e728..4dd2223bd2d 100644
--- a/src/backend/jit/llvm/llvmjit_expr.c
+++ b/src/backend/jit/llvm/llvmjit_expr.c
@@ -62,7 +62,9 @@ static LLVMValueRef build_EvalXFuncInt(LLVMBuilderRef b, LLVMModuleRef mod,
LLVMValueRef v_state,
ExprEvalStep *op,
int natts, LLVMValueRef *v_args);
+#if LLVM_VERSION_MAJOR < 22
static LLVMValueRef create_LifetimeEnd(LLVMModuleRef mod);
+#endif
/* macro making it easier to call ExecEval* functions */
#define build_EvalXFunc(b, mod, funcname, v_state, op, ...) \
@@ -3007,14 +3009,11 @@ BuildV1Call(LLVMJitContext *context, LLVMBuilderRef b,
LLVMModuleRef mod, FunctionCallInfo fcinfo,
LLVMValueRef *v_fcinfo_isnull)
{
- LLVMContextRef lc;
LLVMValueRef v_fn;
LLVMValueRef v_fcinfo_isnullp;
LLVMValueRef v_retval;
LLVMValueRef v_fcinfo;
- lc = LLVMGetModuleContext(mod);
-
v_fn = llvm_function_reference(context, b, mod, fcinfo);
v_fcinfo = l_ptr_const(fcinfo, l_ptr(StructFunctionCallInfoData));
@@ -3031,10 +3030,16 @@ BuildV1Call(LLVMJitContext *context, LLVMBuilderRef b,
*v_fcinfo_isnull = l_load(b, TypeStorageBool, v_fcinfo_isnullp, "");
/*
- * Add lifetime-end annotation, signaling that writes to memory don't have
- * to be retained (important for inlining potential).
+ * Signal that writes to FunctionCallInfoData don't have to be retained
+ * (important for inlining potential).
*/
+#if LLVM_VERSION_MAJOR >= 22
+ for (int i = 0; i < fcinfo->nargs; ++i)
+ LLVMBuildStore(b, LLVMGetPoison(StructNullableDatum), l_funcvaluep(b, v_fcinfo, i));
+ LLVMBuildStore(b, LLVMGetPoison(TypeStorageBool), v_fcinfo_isnullp);
+#else
{
+ LLVMContextRef lc = LLVMGetModuleContext(mod);
LLVMValueRef v_lifetime = create_LifetimeEnd(mod);
LLVMValueRef params[2];
@@ -3046,6 +3051,7 @@ BuildV1Call(LLVMJitContext *context, LLVMBuilderRef b,
params[1] = l_ptr_const(&fcinfo->isnull, l_ptr(LLVMInt8TypeInContext(lc)));
l_call(b, LLVMGetFunctionType(v_lifetime), v_lifetime, params, lengthof(params), "");
}
+#endif
return v_retval;
}
@@ -3083,6 +3089,7 @@ build_EvalXFuncInt(LLVMBuilderRef b, LLVMModuleRef mod, const char *funcname,
return v_ret;
}
+#if LLVM_VERSION_MAJOR < 22
static LLVMValueRef
create_LifetimeEnd(LLVMModuleRef mod)
{
@@ -3112,3 +3119,4 @@ create_LifetimeEnd(LLVMModuleRef mod)
return fn;
}
+#endif
--
2.52.0
^ permalink raw reply [nested|flat] 5+ messages in thread
* Re: LLVM 22
@ 2026-01-04 05:02 Thomas Munro <[email protected]>
parent: Thomas Munro <[email protected]>
1 sibling, 0 replies; 5+ messages in thread
From: Thomas Munro @ 2026-01-04 05:02 UTC (permalink / raw)
To: PostgreSQL Hackers <[email protected]>
On Sat, Jan 3, 2026 at 3:02 PM Thomas Munro <[email protected]> wrote:
> 1. We won't need our local llvm::backport::SectionMemoryManager for
> LLVM 22, so it will be nice to draw a line under that messy business.
> See commit message for details.
While that's true, there is a problem with the patch I posted:
"ReserveAlloc" is not enabled when called from C. I can't actually
reproduce the issue locally due to lack of RAM connected to an ARM
CPU, or I'd have noticed that... I'll attempt to do something about
that upstream[1], let's see... if not, we can still use the new
in-tree SectionMemoryManager, but we'll still need some C++ glue code.
[1] https://github.com/llvm/llvm-project/issues/174305
^ permalink raw reply [nested|flat] 5+ messages in thread
* Re: LLVM 22
@ 2026-01-05 21:56 Matheus Alcantara <[email protected]>
parent: Thomas Munro <[email protected]>
1 sibling, 1 reply; 5+ messages in thread
From: Matheus Alcantara @ 2026-01-05 21:56 UTC (permalink / raw)
To: Thomas Munro <[email protected]>; PostgreSQL Hackers <[email protected]>
Hi,
On Fri Jan 2, 2026 at 11:02 PM -03, Thomas Munro wrote:
> 2. LLVM 22 changed the semantics of the "lifetime.end" instruction.
> See commit message for references. Without this change, LLVM main/22
> assertions fail in the regression tests with messages like this in
> postmaster.log:
>
> Intrinsic has incorrect argument type!
> ptr @llvm.lifetime.end.p0
> Intrinsic has incorrect argument type!
> ptr @llvm.lifetime.end.p0
> 2026-01-02 17:28:31.394 NZDT client backend[42798] pg_regress/boolean
> FATAL: fatal llvm error: Broken module found, compilation aborted!
>
I've managed to reproduce this using LLVM 22.
> Here's a potential minimal fix. I haven't yet proven that the
> optimisation is still working as expected. Probably need to compile
> an expression that calls an inlined function and then a non-inlined
> function with jit_dump_bitcode=true, then find the right XXX.bc file
> under pgdata, llvm-dis XXX.bc, llc XXX.ll, then visually inspect XXX.s
> with enough caffeine to confirm that it's not spilling something (ie
> store instructions) where previously it didn't, but I wanted to post
> what I had so far to see if anyone has a better idea or an easy way to
> test it...
>
I'm not super familiar with reading assembly code but I tried my best to
inspect the LLVM 22 and LLVM 21 outputs and if I understood correctly I
think that 0002 is working as expected.
I've noticed a reduction on some instructions when using LLVM 22 with
the 0002 patch compared with LLVM 21. For example, here we needed less
instructions to set up the registers:
LLVM 22:
LBB2_8: ; %b.op.1.start
mov x20, #40824 ; =0x9f78
movk x20, #19456, lsl #16
movk x20, #1, lsl #32
ldr x8, [x23]
ldrb w9, [x24]
str x8, [x20, #152]
strb w9, [x20, #160]
LLVM 21:
LBB2_8: ; %b.op.1.start
mov x25, #25352 ; =0x6308
movk x25, #2946, lsl #16
movk x25, #1, lsl #32
mov x20, #23533 ; =0x5bed
movk x20, #2946, lsl #16
movk x20, #1, lsl #32
ldr x8, [x23]
ldrb w9, [x24]
stur x8, [x25, #-248]
sturb w9, [x25, #-240]
I've also noticed that the generated assembly code for LLVM 22 use the
str and strb instructions instead of stur and sturb in some cases, which
according to IA is an improvement but unfortunately I did not find any
reference to prove this, sorry.
To test this I did the following steps:
set jit_above_cost = 0;
set jit_inline_above_cost = 0;
set jit_optimize_above_cost = 0;
set jit_dump_bitcode = true;
explain(analyze) select i % 2 = 0 OR i % 3 = 0 from generate_series(1, 100) i;
I'm attaching the .s files for the llvm 22 and for the llvm 21 outputs
that I used to inspect.
--
Matheus Alcantara
EDB: https://www.enterprisedb.com
Attachments:
[text/x-asm] out.21.s (6.5K, 2-out.21.s)
download | inline:
.build_version macos, 15, 0
.section __TEXT,__text,regular,pure_instructions
.globl _evalexpr_0_0 ; -- Begin function evalexpr_0_0
.p2align 2
_evalexpr_0_0: ; @evalexpr_0_0
.cfi_startproc
; %bb.0: ; %entry
mov w8, #1 ; =0x1
mov x9, #19325 ; =0x4b7d
movk x9, #2946, lsl #16
movk x9, #1, lsl #32
stur x8, [x9, #3]
strb wzr, [x9]
ldr x8, [x0, #8]
ldrb w9, [x0, #5]
strb w9, [x2]
mov x0, x8
ret
.cfi_endproc
; -- End function
.globl _evalexpr_0_1 ; -- Begin function evalexpr_0_1
.p2align 2
_evalexpr_0_1: ; @evalexpr_0_1
.cfi_startproc
; %bb.0: ; %entry
mov w8, #100 ; =0x64
mov x9, #20733 ; =0x50fd
movk x9, #2946, lsl #16
movk x9, #1, lsl #32
stur x8, [x9, #3]
strb wzr, [x9]
ldr x8, [x0, #8]
ldrb w9, [x0, #5]
strb w9, [x2]
mov x0, x8
ret
.cfi_endproc
; -- End function
.globl _evalexpr_0_2 ; -- Begin function evalexpr_0_2
.p2align 2
_evalexpr_0_2: ; @evalexpr_0_2
.cfi_startproc
; %bb.0: ; %entry
stp x26, x25, [sp, #-80]! ; 16-byte Folded Spill
stp x24, x23, [sp, #16] ; 16-byte Folded Spill
stp x22, x21, [sp, #32] ; 16-byte Folded Spill
stp x20, x19, [sp, #48] ; 16-byte Folded Spill
stp x29, x30, [sp, #64] ; 16-byte Folded Spill
add x29, sp, #64
.cfi_def_cfa w29, 16
.cfi_offset w30, -8
.cfi_offset w29, -16
.cfi_offset w19, -24
.cfi_offset w20, -32
.cfi_offset w21, -40
.cfi_offset w22, -48
.cfi_offset w23, -56
.cfi_offset w24, -64
.cfi_offset w25, -72
.cfi_offset w26, -80
mov x19, x0
ldr x20, [x1, #8]
ldr x8, [x0, #16]
ldp x23, x24, [x20, #24]
ldp x21, x22, [x8, #24]
ldrh w8, [x20, #6]
cbnz w8, LBB2_8
; %bb.1: ; %op.0.fetch
ldr x8, [x20, #64]
ldr x8, [x8, #16]
ldrh w9, [x8, #18]
tst w9, #0x7ff
b.eq LBB2_5
; %bb.2: ; %block.attr.0.start.i
ldrb w9, [x8, #22]
ldrh w10, [x8, #20]
tbz w10, #0, LBB2_6
; %bb.3: ; %block.attr.0.start.i
ldrb w10, [x8, #23]
tbnz w10, #0, LBB2_6
; %bb.4: ; %block.attr.0.attisnull.i
mov w8, #0 ; =0x0
mov w9, #1 ; =0x1
strb w9, [x24]
str xzr, [x23]
b LBB2_7
LBB2_5: ; %adjust_unavail_cols.i
mov x0, x20
mov w1, #0 ; =0x0
mov w2, #1 ; =0x1
bl _slot_getmissingattrs
mov w8, #0 ; =0x0
b LBB2_7
LBB2_6: ; %block.attr.0.store.i
strb wzr, [x24]
ldrsw x8, [x8, x9]
str x8, [x23]
mov w8, #4 ; =0x4
LBB2_7: ; %deform_0_3.exit
mov w9, #1 ; =0x1
strh w9, [x20, #6]
str w8, [x20, #104]
ldrh w8, [x20, #4]
orr w8, w8, #0x8
strh w8, [x20, #4]
LBB2_8: ; %b.op.1.start
mov x25, #25352 ; =0x6308
movk x25, #2946, lsl #16
movk x25, #1, lsl #32
mov x20, #23533 ; =0x5bed
movk x20, #2946, lsl #16
movk x20, #1, lsl #32
ldr x8, [x23]
ldrb w9, [x24]
stur x8, [x25, #-248]
sturb w9, [x25, #-240]
mov w26, #1 ; =0x1
strb w26, [x20, #1419]
ldurb w8, [x25, #-240]
cmp w8, #1
b.eq LBB2_11
; %bb.9: ; %b.2.isnull.1
ldurb w8, [x25, #-224]
cmp w8, #1
b.eq LBB2_11
; %bb.10: ; %b.2.no-null-args
sturb wzr, [x25, #-252]
sub x0, x25, #280
bl _int4mod
ldurb w8, [x25, #-252]
add x9, x20, #1411
str x0, [x9]
strb w8, [x20, #1419]
LBB2_11: ; %b.op.3.start
strb w26, [x20]
ldrb w8, [x20, #1419]
cmp w8, #1
b.eq LBB2_14
; %bb.12: ; %b.3.isnull.1
sub x8, x25, #384
ldrb w8, [x8]
cmp w8, #1
b.eq LBB2_14
; %bb.13: ; %b.3.no-null-args
strb wzr, [x20, #1407]
add x0, x20, #1379
bl _int4eq
ldrb w8, [x20, #1407]
stur x0, [x20, #3]
strb w8, [x20]
LBB2_14: ; %b.op.4.start
sub x26, x20, #2661
strb wzr, [x26]
ldrb w8, [x20]
cmp w8, #1
b.ne LBB2_16
; %bb.15: ; %b.4.boolisanynull
strb w8, [x26]
strb w8, [x20]
stur xzr, [x20, #3]
b LBB2_17
LBB2_16: ; %b.4.boolchecktrue
ldur x8, [x20, #3]
cmp x8, #1
b.eq LBB2_25
LBB2_17: ; %b.op.5.start
ldr x8, [x23]
ldrb w9, [x24]
str x8, [x25, #152]
strb w9, [x25, #160]
mov w23, #1 ; =0x1
strb w23, [x25]
cmp w9, #1
b.eq LBB2_20
; %bb.18: ; %b.6.isnull.1
ldrb w8, [x25, #176]
cmp w8, #1
b.eq LBB2_20
; %bb.19: ; %b.6.no-null-args
strb wzr, [x25, #148]
add x0, x25, #120
bl _int4mod
ldrb w8, [x25, #148]
stur x0, [x25, #-8]
strb w8, [x25]
LBB2_20: ; %b.op.7.start
strb w23, [x20]
ldrb w8, [x25]
cmp w8, #1
b.eq LBB2_23
; %bb.21: ; %b.7.isnull.1
ldrb w8, [x25, #16]
cmp w8, #1
b.eq LBB2_23
; %bb.22: ; %b.op.8.start
sturb wzr, [x25, #-12]
sub x0, x25, #40
bl _int4eq
ldurb w8, [x25, #-12]
stur x0, [x20, #3]
strb w8, [x20]
cmp w8, #1
b.ne LBB2_26
LBB2_23: ; %b.8.boolcont.thread
mov w8, #1 ; =0x1
strb w8, [x26]
LBB2_24: ; %b.8.boolisanynull
mov w8, #1 ; =0x1
strb w8, [x20]
stur xzr, [x20, #3]
LBB2_25: ; %b.op.9.start
ldr x8, [x19, #8]
ldrb w9, [x19, #5]
strb w9, [x22]
str x8, [x21]
mov x0, #0 ; =0x0
ldp x29, x30, [sp, #64] ; 16-byte Folded Reload
ldp x20, x19, [sp, #48] ; 16-byte Folded Reload
ldp x22, x21, [sp, #32] ; 16-byte Folded Reload
ldp x24, x23, [sp, #16] ; 16-byte Folded Reload
ldp x26, x25, [sp], #80 ; 16-byte Folded Reload
ret
LBB2_26: ; %b.8.boolchecktrue
ldur x8, [x20, #3]
cmp x8, #1
b.eq LBB2_25
; %bb.27: ; %b.8.boolcont
ldrb w8, [x26]
cbnz w8, LBB2_24
b LBB2_25
.cfi_endproc
; -- End function
.subsections_via_symbols
[text/x-asm] out.22.s (6.5K, 3-out.22.s)
download | inline:
.build_version macos, 15, 0
.section __TEXT,__text,regular,pure_instructions
.globl _evalexpr_2_0 ; -- Begin function evalexpr_2_0
.p2align 2
_evalexpr_2_0: ; @evalexpr_2_0
.cfi_startproc
; %bb.0: ; %entry
mov w8, #1 ; =0x1
mov x9, #35197 ; =0x897d
movk x9, #19456, lsl #16
movk x9, #1, lsl #32
stur x8, [x9, #3]
strb wzr, [x9]
ldr x8, [x0, #8]
ldrb w9, [x0, #5]
strb w9, [x2]
mov x0, x8
ret
.cfi_endproc
; -- End function
.globl _evalexpr_2_1 ; -- Begin function evalexpr_2_1
.p2align 2
_evalexpr_2_1: ; @evalexpr_2_1
.cfi_startproc
; %bb.0: ; %entry
mov w8, #100 ; =0x64
mov x9, #36525 ; =0x8ead
movk x9, #19456, lsl #16
movk x9, #1, lsl #32
stur x8, [x9, #3]
strb wzr, [x9]
ldr x8, [x0, #8]
ldrb w9, [x0, #5]
strb w9, [x2]
mov x0, x8
ret
.cfi_endproc
; -- End function
.globl _evalexpr_2_2 ; -- Begin function evalexpr_2_2
.p2align 2
_evalexpr_2_2: ; @evalexpr_2_2
.cfi_startproc
; %bb.0: ; %entry
stp x26, x25, [sp, #-80]! ; 16-byte Folded Spill
stp x24, x23, [sp, #16] ; 16-byte Folded Spill
stp x22, x21, [sp, #32] ; 16-byte Folded Spill
stp x20, x19, [sp, #48] ; 16-byte Folded Spill
stp x29, x30, [sp, #64] ; 16-byte Folded Spill
add x29, sp, #64
.cfi_def_cfa w29, 16
.cfi_offset w30, -8
.cfi_offset w29, -16
.cfi_offset w19, -24
.cfi_offset w20, -32
.cfi_offset w21, -40
.cfi_offset w22, -48
.cfi_offset w23, -56
.cfi_offset w24, -64
.cfi_offset w25, -72
.cfi_offset w26, -80
mov x19, x0
ldr x20, [x1, #8]
ldr x8, [x0, #16]
ldp x23, x24, [x20, #24]
ldp x21, x22, [x8, #24]
ldrh w8, [x20, #6]
cbnz w8, LBB2_8
; %bb.1: ; %op.0.fetch
ldr x8, [x20, #64]
ldr x8, [x8, #16]
ldrh w9, [x8, #18]
tst w9, #0x7ff
b.eq LBB2_5
; %bb.2: ; %block.attr.0.start.i
ldrb w9, [x8, #22]
ldrh w10, [x8, #20]
tbz w10, #0, LBB2_6
; %bb.3: ; %block.attr.0.start.i
ldrb w10, [x8, #23]
tbnz w10, #0, LBB2_6
; %bb.4: ; %block.attr.0.attisnull.i
mov w8, #0 ; =0x0
mov w9, #1 ; =0x1
strb w9, [x24]
str xzr, [x23]
b LBB2_7
LBB2_5: ; %adjust_unavail_cols.i
mov x0, x20
mov w1, #0 ; =0x0
mov w2, #1 ; =0x1
bl _slot_getmissingattrs
mov w8, #0 ; =0x0
b LBB2_7
LBB2_6: ; %block.attr.0.store.i
strb wzr, [x24]
ldrsw x8, [x8, x9]
str x8, [x23]
mov w8, #4 ; =0x4
LBB2_7: ; %deform_2_3.exit
mov w9, #1 ; =0x1
strh w9, [x20, #6]
str w8, [x20, #104]
ldrh w8, [x20, #4]
orr w8, w8, #0x8
strh w8, [x20, #4]
LBB2_8: ; %b.op.1.start
mov x20, #40824 ; =0x9f78
movk x20, #19456, lsl #16
movk x20, #1, lsl #32
ldr x8, [x23]
ldrb w9, [x24]
str x8, [x20, #152]
strb w9, [x20, #160]
mov w26, #1 ; =0x1
strb w26, [x20]
cmp w9, #1
b.eq LBB2_11
; %bb.9: ; %b.2.isnull.1
ldrb w8, [x20, #176]
cmp w8, #1
b.eq LBB2_11
; %bb.10: ; %b.2.no-null-args
strb wzr, [x20, #148]
add x0, x20, #120
bl _int4mod
ldrb w8, [x20, #148]
stur x0, [x20, #-8]
strb w8, [x20]
LBB2_11: ; %b.op.3.start
mov x25, #39405 ; =0x99ed
movk x25, #19456, lsl #16
movk x25, #1, lsl #32
strb w26, [x25]
ldrb w8, [x20]
cmp w8, #1
b.eq LBB2_14
; %bb.12: ; %b.3.isnull.1
ldrb w8, [x20, #16]
cmp w8, #1
b.eq LBB2_14
; %bb.13: ; %b.3.no-null-args
sturb wzr, [x20, #-12]
sub x0, x20, #40
bl _int4eq
ldurb w8, [x20, #-12]
stur x0, [x25, #3]
strb w8, [x25]
LBB2_14: ; %b.op.4.start
sub x26, x25, #2741
strb wzr, [x26]
ldrb w8, [x25]
cmp w8, #1
b.ne LBB2_16
; %bb.15: ; %b.4.boolisanynull
strb w8, [x26]
strb w8, [x25]
stur xzr, [x25, #3]
b LBB2_17
LBB2_16: ; %b.4.boolchecktrue
ldur x8, [x25, #3]
cmp x8, #1
b.eq LBB2_25
LBB2_17: ; %b.op.5.start
ldr x8, [x23]
ldrb w9, [x24]
str x8, [x20, #552]
strb w9, [x20, #560]
mov w23, #1 ; =0x1
strb w23, [x20, #400]
cmp w9, #1
b.eq LBB2_20
; %bb.18: ; %b.6.isnull.1
ldrb w8, [x20, #576]
cmp w8, #1
b.eq LBB2_20
; %bb.19: ; %b.6.no-null-args
strb wzr, [x20, #548]
add x0, x20, #520
bl _int4mod
ldrb w8, [x20, #548]
str x0, [x20, #392]
strb w8, [x20, #400]
LBB2_20: ; %b.op.7.start
strb w23, [x25]
ldrb w8, [x20, #400]
cmp w8, #1
b.eq LBB2_23
; %bb.21: ; %b.7.isnull.1
ldrb w8, [x20, #416]
cmp w8, #1
b.eq LBB2_23
; %bb.22: ; %b.op.8.start
strb wzr, [x20, #388]
add x0, x20, #360
bl _int4eq
ldrb w8, [x20, #388]
stur x0, [x25, #3]
strb w8, [x25]
cmp w8, #1
b.ne LBB2_26
LBB2_23: ; %b.8.boolcont.thread
mov w8, #1 ; =0x1
strb w8, [x26]
LBB2_24: ; %b.8.boolisanynull
mov w8, #1 ; =0x1
strb w8, [x25]
stur xzr, [x25, #3]
LBB2_25: ; %b.op.9.start
ldr x8, [x19, #8]
ldrb w9, [x19, #5]
strb w9, [x22]
str x8, [x21]
mov x0, #0 ; =0x0
ldp x29, x30, [sp, #64] ; 16-byte Folded Reload
ldp x20, x19, [sp, #48] ; 16-byte Folded Reload
ldp x22, x21, [sp, #32] ; 16-byte Folded Reload
ldp x24, x23, [sp, #16] ; 16-byte Folded Reload
ldp x26, x25, [sp], #80 ; 16-byte Folded Reload
ret
LBB2_26: ; %b.8.boolchecktrue
ldur x8, [x25, #3]
cmp x8, #1
b.eq LBB2_25
; %bb.27: ; %b.8.boolcont
ldrb w8, [x26]
cbnz w8, LBB2_24
b LBB2_25
.cfi_endproc
; -- End function
.subsections_via_symbols
^ permalink raw reply [nested|flat] 5+ messages in thread
* Re: LLVM 22
@ 2026-01-05 23:50 Thomas Munro <[email protected]>
parent: Matheus Alcantara <[email protected]>
0 siblings, 1 reply; 5+ messages in thread
From: Thomas Munro @ 2026-01-05 23:50 UTC (permalink / raw)
To: Matheus Alcantara <[email protected]>; +Cc: PostgreSQL Hackers <[email protected]>
On Tue, Jan 6, 2026 at 10:56 AM Matheus Alcantara
<[email protected]> wrote:
> On Fri Jan 2, 2026 at 11:02 PM -03, Thomas Munro wrote:
> > Intrinsic has incorrect argument type!
> > ptr @llvm.lifetime.end.p0
> > Intrinsic has incorrect argument type!
> > ptr @llvm.lifetime.end.p0
> > 2026-01-02 17:28:31.394 NZDT client backend[42798] pg_regress/boolean
> > FATAL: fatal llvm error: Broken module found, compilation aborted!
> >
> I've managed to reproduce this using LLVM 22.
Thanks for testing!
> > Here's a potential minimal fix. I haven't yet proven that the
> > optimisation is still working as expected. Probably need to compile
> > an expression that calls an inlined function and then a non-inlined
> > function with jit_dump_bitcode=true, then find the right XXX.bc file
> > under pgdata, llvm-dis XXX.bc, llc XXX.ll, then visually inspect XXX.s
> > with enough caffeine to confirm that it's not spilling something (ie
> > store instructions) where previously it didn't, but I wanted to post
> > what I had so far to see if anyone has a better idea or an easy way to
> > test it...
> >
> I'm not super familiar with reading assembly code but I tried my best to
> inspect the LLVM 22 and LLVM 21 outputs and if I understood correctly I
> think that 0002 is working as expected.
Cool. And as another sanity test, if you comment out the new poison
code so that we don't try to prevent unwanted spills/stores, can you
see any?
> I've noticed a reduction on some instructions when using LLVM 22 with
> the 0002 patch compared with LLVM 21. For example, here we needed less
> instructions to set up the registers:
>
> LLVM 22:
> LBB2_8: ; %b.op.1.start
> mov x20, #40824 ; =0x9f78
> movk x20, #19456, lsl #16
> movk x20, #1, lsl #32
> ldr x8, [x23]
> ldrb w9, [x24]
> str x8, [x20, #152]
> strb w9, [x20, #160]
>
> LLVM 21:
> LBB2_8: ; %b.op.1.start
> mov x25, #25352 ; =0x6308
> movk x25, #2946, lsl #16
> movk x25, #1, lsl #32
> mov x20, #23533 ; =0x5bed
> movk x20, #2946, lsl #16
> movk x20, #1, lsl #32
> ldr x8, [x23]
> ldrb w9, [x24]
> stur x8, [x25, #-248]
> sturb w9, [x25, #-240]
>
> I've also noticed that the generated assembly code for LLVM 22 use the
> str and strb instructions instead of stur and sturb in some cases, which
> according to IA is an improvement but unfortunately I did not find any
> reference to prove this, sorry.
Interesting.
^ permalink raw reply [nested|flat] 5+ messages in thread
* Re: LLVM 22
@ 2026-01-06 18:35 Matheus Alcantara <[email protected]>
parent: Thomas Munro <[email protected]>
0 siblings, 0 replies; 5+ messages in thread
From: Matheus Alcantara @ 2026-01-06 18:35 UTC (permalink / raw)
To: Thomas Munro <[email protected]>; Matheus Alcantara <[email protected]>; +Cc: PostgreSQL Hackers <[email protected]>
On Mon Jan 5, 2026 at 8:50 PM -03, Thomas Munro wrote:
>> > Here's a potential minimal fix. I haven't yet proven that the
>> > optimisation is still working as expected. Probably need to compile
>> > an expression that calls an inlined function and then a non-inlined
>> > function with jit_dump_bitcode=true, then find the right XXX.bc file
>> > under pgdata, llvm-dis XXX.bc, llc XXX.ll, then visually inspect XXX.s
>> > with enough caffeine to confirm that it's not spilling something (ie
>> > store instructions) where previously it didn't, but I wanted to post
>> > what I had so far to see if anyone has a better idea or an easy way to
>> > test it...
>> >
>> I'm not super familiar with reading assembly code but I tried my best to
>> inspect the LLVM 22 and LLVM 21 outputs and if I understood correctly I
>> think that 0002 is working as expected.
>
> Cool. And as another sanity test, if you comment out the new poison
> code so that we don't try to prevent unwanted spills/stores, can you
> see any?
>
Yes, I've commented the poison code block introduced on 0002 and the
generated assembly code seems more bloated, for example:
LLVM 22 with 0002 and the poison code block commented:
LBB2_8:
mov x25, #15624 ; =0x3d08
movk x25, #7427, lsl #16
movk x25, #1, lsl #32
mov x20, #13805 ; =0x35ed
movk x20, #7427, lsl #16
movk x20, #1, lsl #32
ldr x8, [x23]
ldrb w9, [x24]
stur x8, [x25, #-248]
sturb w9, [x25, #-240]
mov w26, #1 ; =0x1
strb w26, [x20, #1419]
ldurb w8, [x25, #-240]
cmp w8, #1
b.eq LBB2_11
LLVM 22 with 0002:
LBB2_8:
mov x20, #40824 ; =0x9f78
movk x20, #19456, lsl #16
movk x20, #1, lsl #32
ldr x8, [x23]
ldrb w9, [x24]
str x8, [x20, #152]
strb w9, [x20, #160]
mov w26, #1 ; =0x1
strb w26, [x20]
cmp w9, #1
b.eq LBB2_11
IIUC with the commented code the LLVM compiler added an extra
load ldurb followed by cmp w8, #1. With the patch it performs a
comparison cmp w9, #1 directly using a register it already has.
--
Matheus Alcantara
EDB: https://www.enterprisedb.com
^ permalink raw reply [nested|flat] 5+ messages in thread
end of thread, other threads:[~2026-01-06 18:35 UTC | newest]
Thread overview: 5+ messages (download: mbox mbox.gz follow: Atom feed)
-- links below jump to the message on this page --
2026-01-03 02:02 LLVM 22 Thomas Munro <[email protected]>
2026-01-04 05:02 ` Thomas Munro <[email protected]>
2026-01-05 21:56 ` Matheus Alcantara <[email protected]>
2026-01-05 23:50 ` Thomas Munro <[email protected]>
2026-01-06 18:35 ` Matheus Alcantara <[email protected]>
This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox