[llvm] 03661fb - [docs][UB] add section on poison propagation through select
Nuno Lopes via llvm-commits
llvm-commits at lists.llvm.org
Wed Dec 11 08:52:08 PST 2024
Author: Nuno Lopes
Date: 2024-12-11T16:52:03Z
New Revision: 03661fbe45e70bde2984a5fc0feab6396407a33b
URL: https://github.com/llvm/llvm-project/commit/03661fbe45e70bde2984a5fc0feab6396407a33b
DIFF: https://github.com/llvm/llvm-project/commit/03661fbe45e70bde2984a5fc0feab6396407a33b.diff
LOG: [docs][UB] add section on poison propagation through select
Examples from Nikita Popov, thank you!
Added:
Modified:
llvm/docs/UndefinedBehavior.rst
Removed:
################################################################################
diff --git a/llvm/docs/UndefinedBehavior.rst b/llvm/docs/UndefinedBehavior.rst
index f68bbbd505330a..82ae20c74f330e 100644
--- a/llvm/docs/UndefinedBehavior.rst
+++ b/llvm/docs/UndefinedBehavior.rst
@@ -237,6 +237,53 @@ Poison values can be replaced with any value of type (undef, concrete values,
or a ``freeze`` instruction).
+Propagation of Poison Through Select
+------------------------------------
+Most instructions return poison if any of their inputs is poison.
+A notable exception is the ``select`` instruction, which is poison if and
+only if the condition is poison or the selected value is poison.
+This means that ``select`` acts as a barrier for poison propagation, which
+impacts which optimizations can be performed.
+
+For example, consider the following function:
+
+.. code-block:: llvm
+
+ define i1 @fn(i32 %x, i32 %y) {
+ %cmp1 = icmp ne i32 %x, 0
+ %cmp2 = icmp ugt i32 %x, %y
+ %and = select i1 %cmp1, i1 %cmp2, i1 false
+ ret i1 %and
+ }
+
+It is not correct to optimize the ``select`` into an ``and`` because when
+``%cmp1`` is false, the ``select`` is only poison if ``%x`` is poison, while
+the ``and`` below is poison if either ``%x`` or ``%y`` are poison.
+
+.. code-block:: llvm
+
+ define i1 @fn(i32 %x, i32 %y) {
+ %cmp1 = icmp ne i32 %x, 0
+ %cmp2 = icmp ugt i32 %x, %y
+ %and = and i1 %cmp1, %cmp2 ;; poison if %x or %y are poison
+ ret i1 %and
+ }
+
+However, the optimization is possible if all operands of the values are used in
+the condition (notice the flipped operands in the ``select``):
+
+.. code-block:: llvm
+
+ define i1 @fn(i32 %x, i32 %y) {
+ %cmp1 = icmp ne i32 %x, 0
+ %cmp2 = icmp ugt i32 %x, %y
+ %and = select i1 %cmp2, i1 %cmp1, i1 false
+ ; ok to replace with:
+ %and = and i1 %cmp1, %cmp2
+ ret i1 %and
+ }
+
+
The Freeze Instruction
======================
Both undef and poison values sometimes propagate too much down an expression
More information about the llvm-commits
mailing list