[PATCH] D63044: [LangRef] Clarify poison semantics

Nikita Popov via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Sat Jun 8 01:43:32 PDT 2019


nikic created this revision.
nikic added reviewers: efriedma, hfinkel, nlopes, reames.
Herald added subscribers: llvm-commits, hiraditya.
Herald added a project: LLVM.

I find the current documentation of poison rather confusing, mainly because its use of "undefined behavior" doesn't seem to align with our usual interpretation (of //immediate// UB). Especially the sentence "any instruction that has a dependence on a poison value has undefined behavior" is very confusing.

Clarify poison semantics by:

- Replacing the introductory paragraph with the standard rationale for having poison value.
- Spelling out that an instruction depending on poison returns poison.
- Spelling out how we go from a poison value to immediate undefined behavior and give the two examples we currently use in ValueTracking.
- Spelling out that side effects depending on poison are UB.

I've also added two TODOs in ValueTracking -- if I'm not misunderstanding something, the current logic in getGuaranteedNonFullPoisonOp() is only legal under the assumption that dereferencing null is always UB.

(Context: Discussion in D62939 <https://reviews.llvm.org/D62939> on when exactly poison turns into UB.)


Repository:
  rL LLVM

https://reviews.llvm.org/D63044

Files:
  llvm/docs/LangRef.rst
  llvm/lib/Analysis/ValueTracking.cpp


Index: llvm/lib/Analysis/ValueTracking.cpp
===================================================================
--- llvm/lib/Analysis/ValueTracking.cpp
+++ llvm/lib/Analysis/ValueTracking.cpp
@@ -4336,6 +4336,8 @@
 }
 
 bool llvm::propagatesFullPoison(const Instruction *I) {
+  // TODO: This should include all instructions apart from phis, selects and
+  // call-like instructions.
   switch (I->getOpcode()) {
   case Instruction::Add:
   case Instruction::Sub:
@@ -4369,6 +4371,8 @@
 
 const Value *llvm::getGuaranteedNonFullPoisonOp(const Instruction *I) {
   switch (I->getOpcode()) {
+    // TODO: These should be limited to address space 0 and absence of the
+    // null-pointer-is-valid attribute.
     case Instruction::Store:
       return cast<StoreInst>(I)->getPointerOperand();
 
Index: llvm/docs/LangRef.rst
===================================================================
--- llvm/docs/LangRef.rst
+++ llvm/docs/LangRef.rst
@@ -3218,10 +3218,9 @@
 Poison Values
 -------------
 
-Poison values are similar to :ref:`undef values <undefvalues>`, however
-they also represent the fact that an instruction or constant expression
-that cannot evoke side effects has nevertheless detected a condition
-that results in undefined behavior.
+In order to facilitate speculative execution, many instructions do not
+invoke immediate undefined behavior when provided with illegal operands,
+and return a poison value instead.
 
 There is currently no way of representing a poison value in the IR; they
 only exist when produced by operations such as :ref:`add <i_add>` with
@@ -3258,9 +3257,22 @@
    successor.
 -  Dependence is transitive.
 
-Poison values have the same behavior as :ref:`undef values <undefvalues>`,
-with the additional effect that any instruction that has a *dependence*
-on a poison value has undefined behavior.
+An instruction that *depends* on a poison value, produces a poison value
+itself. A poison value may be relaxed into an
+:ref:`undef value <undefvalues>`, which takes an arbitrary bit-pattern.
+
+This means that immediate undefined behavior occurs if a poison value is
+used as an instruction operand that has any values that trigger undefined
+behavior. Notably this includes (but is not limited to):
+
+-  The pointer operand of a :ref:`load <i_load>`, :ref:`store <i_store>` or
+   any other pointer dereferencing instruction, if dereferencing ``null``
+   is undefined behavior based on address space and function attributes.
+-  The divisor operand of a ``udiv``, ``sdiv``, ``urem`` or ``srem``
+   instruction.
+
+Additionally, undefined behavior occurs if a side effect, including any
+:ref:`volatile <volatile>` operation, depends on poison.
 
 Here are some examples:
 


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D63044.203676.patch
Type: text/x-patch
Size: 2723 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20190608/e00631ae/attachment-0001.bin>


More information about the llvm-commits mailing list