<table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Issue</th>
<td>
<a href=https://github.com/llvm/llvm-project/issues/86162>86162</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>
[inliner] AddReturnAttributes with non existing operands
</td>
</tr>
<tr>
<th>Labels</th>
<td>
new issue
</td>
</tr>
<tr>
<th>Assignees</th>
<td>
</td>
</tr>
<tr>
<th>Reporter</th>
<td>
erthalion
</td>
</tr>
</table>
<pre>
Hi,
I think we've hit the Inliner bug when using LLVM in PostgreSQL [[1]]. Here is
what happens:
* To process a query PostgreSQL creates a deform function
* The module with this function is fed into LLVMRunPasses
* The Inliner pass crashes inside AddReturnAttributes with an assert:
```
llvm/include/llvm/IR/Instructions.h:3420: llvm::Value* llvm::ReturnInst::getOperand(unsigned int) const:
Assertion `i_nocapture < OperandTraits<ReturnInst>::operands(this) && "getOperand() out of range!"' failed.
```
It seems `CallBase` was identified to have some attributes, but one
`ReturnInst` doesn't have any operands to work with [[2]]. The instruction
we're talking about is the return instruction from the `outblock` in the deform
function, which was generated via `LLVMBuildRetVoid` and is literally
`ret void` (I'll add the full function body at the end).
The unfortunate part is that this started to crash only recently. My
understanding that the reason is this change [[3]], which has enabled `noundef`
attributes propagation. It looks like `ret void` is considered to be `noundef`
(this is exactly the kind of an attribute that causes the crash), thus
`ValidUB.hasAttributes()` now returns true and everything proceed further to
work with operands. If I comment out `if (CB.hasRetAttr(Attribute::NoUndef))`
condition everything works fine.
Any ideas how to fix that? Any other information necessary? I've tried to
experiment with excluding problematic ReturnInst from the loop, but it turns
out not only `getOperand`, `getNumOperands` is also crashing. I'll try to come
up with an isolated test case, in the meantime if you folks are brave enough I
can show how to reproduce it directly on PostgreSQL.
---
Here is the full body of the deform function, the `outblock` is a cleanup code
that does `ret void`.
```
; Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write) uwtable
define internal void @deform_0_1(ptr nocapture noundef writeonly align 8 %0) #0 {
entry:
%v_offp = alloca i64, align 8
%1 = getelementptr inbounds %struct.TupleTableSlot, ptr %0, i32 0, i32 5
%tts_values = load ptr, ptr %1, align 8
%2 = getelementptr inbounds %struct.TupleTableSlot, ptr %0, i32 0, i32 6
%tts_ISNULL = load ptr, ptr %2, align 8
%3 = getelementptr inbounds %struct.TupleTableSlot, ptr %0, i32 0, i32 1
%4 = getelementptr inbounds %struct.TupleTableSlot, ptr %0, i32 0, i32 2
%5 = getelementptr inbounds %struct.MinimalTupleTableSlot, ptr %0, i32 0, i32 4
%6 = getelementptr inbounds %struct.MinimalTupleTableSlot, ptr %0, i32 0, i32 1
%tupleheader = load ptr, ptr %6, align 8
%7 = getelementptr inbounds %struct.HeapTupleData, ptr %tupleheader, i32 0, i32 3
%tuple = load ptr, ptr %7, align 8
%8 = getelementptr inbounds %struct.HeapTupleHeaderData, ptr %tuple, i32 0, i32 5
%9 = getelementptr inbounds %struct.HeapTupleHeaderData, ptr %tuple, i32 0, i32 3
%infomask1 = load i16, ptr %9, align 2
%10 = getelementptr inbounds %struct.HeapTupleHeaderData, ptr %tuple, i32 0, i32 2
%infomask2 = load i16, ptr %10, align 2
%11 = and i16 1, %infomask1
%hasnulls = icmp ne i16 %11, 0
%maxatt = and i16 2047, %infomask2
%12 = getelementptr inbounds %struct.HeapTupleHeaderData, ptr %tuple, i32 0, i32 4
%13 = load i8, ptr %12, align 1
%t_hoff = zext i8 %13 to i32
%v_tupdata_base = getelementptr i8, ptr %tuple, i32 %t_hoff
%v_slot_off = load i32, ptr %5, align 4
%14 = zext i32 %v_slot_off to i64
store i64 %14, ptr %v_offp, align 8
%15 = icmp ult i16 %maxatt, 1
br i1 %15, label %adjust_unavail_cols, label %find_startblock
adjust_unavail_cols: ; preds = %entry
%16 = zext i16 %maxatt to i32
call void @slot_getmissingattrs(ptr %0, i32 %16, i32 1)
br label %find_startblock
find_startblock: ; preds = %adjust_unavail_cols, %entry
%17 = load i16, ptr %4, align 2
switch i16 %17, label %deadblock [
i16 0, label %block.attr.0.attcheckattno
]
outblock: ; preds = %block.attr.0.store, %block.attr.0.attisnull, %block.attr.0.attcheckattno
%18 = load i64, ptr %v_offp, align 8
store i16 1, ptr %4, align 2
%19 = trunc i64 %18 to i32
store i32 %19, ptr %5, align 4
%tts_flags = load i16, ptr %3, align 2
%20 = or i16 %tts_flags, 8
store i16 %20, ptr %3, align 2
ret void
deadblock: ; preds = %find_startblock
unreachable
block.attr.0.attcheckattno: ; preds = %find_startblock
store i64 0, ptr %v_offp, align 8
%heap_natts = icmp uge i16 0, %maxatt
br i1 %heap_natts, label %outblock, label %block.attr.0.start
block.attr.0.start: ; preds = %block.attr.0.attcheckattno
%21 = getelementptr i8, ptr %8, i32 0
%attnullbyte = load i8, ptr %21, align 1
%22 = and i8 %attnullbyte, 1
%attisnull = icmp eq i8 %22, 0
%23 = and i1 %hasnulls, %attisnull
br i1 %23, label %block.attr.0.attisnull, label %block.attr.0.attcheckalign
block.attr.0.attisnull: ; preds = %block.attr.0.start
%24 = getelementptr i8, ptr %tts_ISNULL, i16 0
store i8 1, ptr %24, align 1
%25 = getelementptr i64, ptr %tts_values, i16 0
store i64 0, ptr %25, align 8
br label %outblock
block.attr.0.attcheckalign: ; preds = %block.attr.0.start
br label %block.attr.0.align
block.attr.0.align: ; preds = %block.attr.0.attcheckalign
br label %block.attr.0.store
block.attr.0.store: ; preds = %block.attr.0.align
%26 = load i64, ptr %v_offp, align 8
%27 = getelementptr i8, ptr %v_tupdata_base, i64 %26
%28 = getelementptr i64, ptr %tts_values, i16 0
%29 = getelementptr i8, ptr %tts_ISNULL, i16 0
store i8 0, ptr %29, align 1
%attr_byval = load i8, ptr %27, align 1
%30 = zext i8 %attr_byval to i64
store i64 %30, ptr %28, align 8
%31 = load i64, ptr %v_offp, align 8
%increment_offset = add i64 %31, 1
store i64 %increment_offset, ptr %v_offp, align 8
br label %outblock
}
```
[1]: https://www.postgresql.org/message-id/flat/CAFj8pRACpVFr7LMdVYENUkScG5FCYMZDDdSGNU-tch%2Bw98OxYg%40mail.gmail.com
[2]: https://github.com/llvm/llvm-project/blob/main/llvm/lib/Transforms/Utils/InlineFunction.cpp#L1387
[3]: https://github.com/llvm/llvm-project/commit/2da4960f20f7e5d88a68ce25636a895284dc66d8
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJy0Wl1v47YS_TXKC7GGRNmy_JAHJ6m7AbLb3v0Cel8MWhpZbChSJak4vr_-YkhZol07H0W3KBzbImfOzJw5Q1nLjOFbCXAdzW6i2d0V62yt9DVoWzPBlbzaqHJ__ZFH9DaK76J46V_via25fCQ7iOj8CUjNLbE1kHspuARNNt2W7GqQpDNcbsnDw49PhEvyuzJ2q-Hrfx6I83eTRLO7aHY3IR9BA-HGW9_VzJKatS1IE6XL0HFEl-SbIq1WBRhDGPmrA70PDRcamAW8VEKldEOqThaWKxkYqIE0quwEkB23NcZihmUE30NJuLTKAf_Syd-ZMWCODRxCbZkxpNDM1GAIl4aXQJZl-QVsp-XSWs03HeJxnpgkaErb07CyuP_ffRTiqYnoistCdCVEdNV_cf8FX6SxunNYzaSO0mU6pXGULolblC6jdPmDiQ4Q6PiVx4N7_ect2N9a0EyWEc076Vjggo7oghSqX-fQLB1iTE2UxXwtVcFa22kgUXpLeiPfNOPWROlt6OcX70r5JSaiOWYaHUQ0i2hGIkqPcOAl1VmiKqKZ3EJEk4jSiM5JxbiAcnI2Wz0lLTEAjUGQt0yIG2YgymKyY4bwEqTlFYeSWEVq9gTEqAYIG8oT0VuyQc8SBh9BKFlMSgVGRnRu_X4m9-QQGBrdKf3oa-yZTQ_MRq7wsWQ9w7FvNBDLxCM2CNtg2Ny4JtLOb7iJVFo17lqUxaqzG6GKRwTFpfvWM92bHuhOb8mu5kXtMrAFCZpZKMkTZ2gFmX3TcYFE_aF4idaYLBGD4BY0E2I_ZEKDJU_9oojm9xGdC0FYWTrvVSfE2D4oGIR5OQCs6mISlgnT0clKadtJZoG0TPeBuz3cEGOZtr5Srq2IkmJPNBQgrdhPyKceVydL0MYyWWIG-_2YPWZ8FztrRY1E6ouS-qKMqamZISDZRkCJSZEKjVYDs0Z-oOK0bMswxAm5t0Qo9YipenQ1CROETpXTAe2j2MA523034HJ4ZoUVewf_kcsS-Y9KcfDugytYZ8AzxOUlogsMxNadGQr1gwlefr-Z1MwsA25jYyE0qXY9uwyxugNXcXgCvUc533pZhZJUnbY1aGJVT9eB3AfKT8h9Re5JoZoGpHVNi-JQIT1unf8vYBFCRPMBiZeDz-q7SwTCXwzpKJQsuSNQgAf9GlJxCUccWso9tjQzpFY7zHDFn12OonRF8KJy6DnSrHElIxJwXjC9xyX3fmhZ7QXBG4XnFjR30bhI4RnFt8_KRgAaKsioCWNPCqXag37gHMT0epuYFqmsZ3CUxYHYZTFu8d997prfDhrpCcSE6dnP5XZC-oazeu-6QjW9SHXtMFa4UcL1twWDXDGA9nt9aIBJyxsgvCJ71ZFKiUdDmAay0ShmIFW3rcl9XwomicHM9tnV0GpVdgVgdCXX4MiqwnF-VJ4PHz6EH_vRPkqFUwhVBcpFQtE6J3M4zgsBTHYtKVTZh-_aAnX5pAUnL4zWKL0hq4NWITPxhEGazthWq63GQ4VUlQYgUmkoOm3wndnLgmAH77A9d1yIXqQbaJTeRzRnetsAzlqy09wCTrJuZ1FZvN8SkMY4YEFLJhxUEk1jn4B1vE4imrdWk3G89orhDToKMcG3kuQkorPYj9E0JtH8pmewtMjvPm5c9LRWVdWSKL0jTAhVMMKzKea4N9SvxKWJW7UFCwKwCRAKlxuEYPC6n0WTb10r4BuG9VUoi6ZwocdzS3hKyfBmFli31qyf8FBinBuhWIkbg_3JeVj0X4eVncC6__r5-8PDJVj0PKz0X4eVBNan_7p1Glifvc36Jy55w8Q7nEwDJ9nPchLmyeK2GlgJ-lL9svP1m78N3kdgrcN2xywLrAaO_wYwPQV4Cdr8PLT8ndA-OhjnAL7YkYuf5yYdBQhHcMPMYzImgSdZYGExJiHkaBL_PHihnwM-eglfEl8A6CNyJ-YkI069wniDpTUzshPCKx8vmpbgHEgybwY3xsHqhj0za4-M03g6P7F_BOWNGvlPchW2dJIGScrDHAUiedSe61pVldv0P3i2hOe9GavQeDimbNeWzLL1hhk4F01-CengJvD7tDZC2fXBtwec0sDEbAR8FOE0AOuNB7YQdTYsN1bhsSab-o2BcT90L0zZ2ciCTtgDDXzRccuQv40mPPFb8HvBNiDwIyv_7Ixdd5I9MS7WhRLm6HrFZbl2t1D-9BSchM5tTZfkxf_wuNRqKD17Izrzh4wgoizIWRjNcZVJwcR46HE53YJtuDFcbpk7hvnjTyj6zvwo_HQRJOctAZ9eei3YswFfSPi5VMwvqcj07yJidtwW9aAD86MilsBKB9ndt_YeiFscHy10iyaYv0mMf4oaikdmrVQDrtldmJLhVJ0u_x7qkTVH8D7SUzfcKdqFi2cw0FmSB7nJ3tIufYMdxPVyJp15P86s7mQxNGV-QsHeYk-sxet6gMfDSrCtuVTX9Dwa6qeX0ofyDoZwfX6Cxy-h8St2h_uboJoDT95E7QsEP9tAhHRSAyvq8Q7Gv75Q7XOUumB8VM_4jcpZA2vXklkbzNFuC2NPjDJ6qqDj1qPeGVrhYkM53BeD91df7aNLHUHP3nGFgy4fx_G4Dc10Qmz2Fi6MY5qcH8eUjqeK_MTU0ejxl3yPj8mGv_ptlIZnFvwiDY4r4YmnL8soGKeVoemLajbKzCuCh7G-RNLe0Bs0byi4T9nZO7Gjw8hwB-mK5ch4zPH8SL_o9EJxzt6VHQnleA99ydVJO9HZmVYKR-fQAa_2t0vwRY15R1JD98euXq7hAcAbe2009oJLP-Eutzdefd1l6AqTnr130OGms_ej-dHm8IjsCOCnHA1_z6Bnbx7fyiI0cPa28L2EPyLh4jzhMX3rzf6JiUsyNj-_MY1P7ygCUy-c0dMjVPmF33WS91bP35UV2mUL1xjo797KcnCdHOnrEazTvW9x-UIPz-9eeER2eOCaLkltbeuerdJVRFe73W7S-h9zzV9iovQ2oqsGjGFb-MDLiK4qwWxEV7fL1Z95-2V52_5Y6fnDp_LHH798_v74tfh1trr949N_7-7Kr79-_v7BFjVm-Wa3yH97_mOLB7e4YVxMtu61UM2AiJ5FtOW27jZu4fD0E_98aLX6EwrEshFqgzAZl8Eajt9900yaSunGRHT13XIcRSv_wPbw2--kaNuIpg9Jms8HLOk_xVKopuH4hpZsusjiisbVHGZlnrMsL4DOsjRj-WJG82lZZFmZX5XXablIF-wKrpN5ksTTKaXzq_qasTJdpNO0KEpawGyWzSFjMJtvsjKZz5Lkil_TmE7jlCZJHqdTOplu8jhflGWezIHN5ptoGoPLMmLEWl5xYzq4zrMko1eOOMY97qdUwo64ixHFMlzpaxfXptuaaBoLbqwZrVhuhft3Atw_-Y5md5cfdEslCTxzY7ncDg-Nrjotrt-dWwcQC-gC-H8AAAD__3S47JM">