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

Nikita Popov via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Tue Jan 10 07:15:31 PST 2023


nikic created this revision.
nikic added reviewers: nlopes, jdoerfert, spatel, efriedma.
Herald added a subscriber: StephenFan.
Herald added a project: All.
nikic requested review of this revision.
Herald added a project: LLVM.
Herald added a subscriber: llvm-commits.

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.


https://reviews.llvm.org/D141386

Files:
  llvm/docs/LangRef.rst


Index: llvm/docs/LangRef.rst
===================================================================
--- llvm/docs/LangRef.rst
+++ llvm/docs/LangRef.rst
@@ -6375,10 +6375,10 @@
 ``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)``.
@@ -10182,9 +10182,9 @@
 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``
@@ -10204,13 +10204,16 @@
 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:
 """"""""""


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D141386.487799.patch
Type: text/x-patch
Size: 2989 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20230110/d518e67e/attachment.bin>


More information about the llvm-commits mailing list