[llvm] 84a5d93 - [LangRef] Make !range, !nonnull and !align return poison instead of IUB

Nikita Popov via llvm-commits llvm-commits at lists.llvm.org
Thu Jan 12 01:01:02 PST 2023


Author: Nikita Popov
Date: 2023-01-12T10:00:54+01:00
New Revision: 84a5d93f43cd92b489d3ee6327f88764364fdb26

URL: https://github.com/llvm/llvm-project/commit/84a5d93f43cd92b489d3ee6327f88764364fdb26
DIFF: https://github.com/llvm/llvm-project/commit/84a5d93f43cd92b489d3ee6327f88764364fdb26.diff

LOG: [LangRef] Make !range, !nonnull and !align return poison instead of IUB

Make violation of !range, !nonnull and !align metadata return poison
instead of causing immediate undefined behavior. This makes the
behavior match that of the nonnull and align parameter and return
value attributes. The previous behavior can be restored by additionally
specifying the !noundef metadata, same as with parameters.

Some benefits of this change are:

 * This is needed to fix https://github.com/llvm/llvm-project/issues/59888.
   Under current semantics, it is illegal to add !range annotations
   based on known bits. Unless we want to drop that optimization
   entirely, we need to change the !range semantics.
 * This allows preserving range/nonnull/align metadata on
   speculated loads. !noundef metadata needs to be dropped, but
   the poison-generating metadata can be retained.

I don't think there are really disadvantages to the change (apart
from the need to review and adjust optimizations for the new
semantics), as the old behavior is still available via !noundef,
so it should be strictly more flexible.

Differential Revision: https://reviews.llvm.org/D141386

Added: 
    

Modified: 
    llvm/docs/LangRef.rst

Removed: 
    


################################################################################
diff  --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
index 0e2c08d24c758..79589c21275bd 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -6391,10 +6391,10 @@ representing the maximum relative error, for example:
 ``range`` metadata may be attached only to ``load``, ``call`` and ``invoke`` of
 integer types. It expresses the possible ranges the loaded value or the value
 returned by the called function at this call site is in. If the loaded or
-returned value is not in the specified range, the behavior is undefined. The
-ranges are represented with a flattened list of integers. The loaded value or
-the value returned is known to be in the union of the ranges defined by each
-consecutive pair. Each pair has the following properties:
+returned value is not in the specified range, a poison value is returned
+instead. The ranges are represented with a flattened list of integers. The
+loaded value or the value returned is known to be in the union of the ranges
+defined by each consecutive pair. Each pair has the following properties:
 
 -  The type must match the type loaded by the instruction.
 -  The pair ``a,b`` represents the range ``[a,b)``.
@@ -10198,9 +10198,9 @@ The optional ``!nonnull`` metadata must reference a single
 metadata name ``<empty_node>`` corresponding to a metadata node with no
 entries. The existence of the ``!nonnull`` metadata on the
 instruction tells the optimizer that the value loaded is known to
-never be null. If the value is null at runtime, the behavior is undefined.
-This is analogous to the ``nonnull`` attribute on parameters and return
-values. This metadata can only be applied to loads of a pointer type.
+never be null. If the value is null at runtime, a poison value is returned
+instead.  This is analogous to the ``nonnull`` attribute on parameters and
+return values. This metadata can only be applied to loads of a pointer type.
 
 The optional ``!dereferenceable`` metadata must reference a single metadata
 name ``<deref_bytes_node>`` corresponding to a metadata node with one ``i64``
@@ -10220,13 +10220,16 @@ optimizer that the value loaded is known to be aligned to a boundary specified
 by the integer value in the metadata node. The alignment must be a power of 2.
 This is analogous to the ''align'' attribute on parameters and return values.
 This metadata can only be applied to loads of a pointer type. If the returned
-value is not appropriately aligned at runtime, the behavior is undefined.
+value is not appropriately aligned at runtime, a poison value is returned
+instead.
 
 The optional ``!noundef`` metadata must reference a single metadata name
 ``<empty_node>`` corresponding to a node with no entries. The existence of
 ``!noundef`` metadata on the instruction tells the optimizer that the value
 loaded is known to be :ref:`well defined <welldefinedvalues>`.
-If the value isn't well defined, the behavior is undefined.
+If the value isn't well defined, the behavior is undefined. If the ``!noundef``
+metadata is combined with poison-generating metadata like ``!nonnull``,
+violation of that metadata constraint will also result in undefined behavior.
 
 Semantics:
 """"""""""


        


More information about the llvm-commits mailing list