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
.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
.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