Skip to content

Commit 03661fb

Browse files
committed
[docs][UB] add section on poison propagation through select
Examples from Nikita Popov, thank you!
1 parent 08f9040 commit 03661fb

File tree

1 file changed

+47
-0
lines changed

1 file changed

+47
-0
lines changed

llvm/docs/UndefinedBehavior.rst

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,53 @@ Poison values can be replaced with any value of type (undef, concrete values,
237237
or a ``freeze`` instruction).
238238

239239

240+
Propagation of Poison Through Select
241+
------------------------------------
242+
Most instructions return poison if any of their inputs is poison.
243+
A notable exception is the ``select`` instruction, which is poison if and
244+
only if the condition is poison or the selected value is poison.
245+
This means that ``select`` acts as a barrier for poison propagation, which
246+
impacts which optimizations can be performed.
247+
248+
For example, consider the following function:
249+
250+
.. code-block:: llvm
251+
252+
define i1 @fn(i32 %x, i32 %y) {
253+
%cmp1 = icmp ne i32 %x, 0
254+
%cmp2 = icmp ugt i32 %x, %y
255+
%and = select i1 %cmp1, i1 %cmp2, i1 false
256+
ret i1 %and
257+
}
258+
259+
It is not correct to optimize the ``select`` into an ``and`` because when
260+
``%cmp1`` is false, the ``select`` is only poison if ``%x`` is poison, while
261+
the ``and`` below is poison if either ``%x`` or ``%y`` are poison.
262+
263+
.. code-block:: llvm
264+
265+
define i1 @fn(i32 %x, i32 %y) {
266+
%cmp1 = icmp ne i32 %x, 0
267+
%cmp2 = icmp ugt i32 %x, %y
268+
%and = and i1 %cmp1, %cmp2 ;; poison if %x or %y are poison
269+
ret i1 %and
270+
}
271+
272+
However, the optimization is possible if all operands of the values are used in
273+
the condition (notice the flipped operands in the ``select``):
274+
275+
.. code-block:: llvm
276+
277+
define i1 @fn(i32 %x, i32 %y) {
278+
%cmp1 = icmp ne i32 %x, 0
279+
%cmp2 = icmp ugt i32 %x, %y
280+
%and = select i1 %cmp2, i1 %cmp1, i1 false
281+
; ok to replace with:
282+
%and = and i1 %cmp1, %cmp2
283+
ret i1 %and
284+
}
285+
286+
240287
The Freeze Instruction
241288
======================
242289
Both undef and poison values sometimes propagate too much down an expression

0 commit comments

Comments
 (0)