1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-22 18:54:02 +01:00

[LangRef] Clarify the semantics of branch on undef

Summary:
This patch clarifies the semantics of branching on undef value.

Defining `br undef` as undefined behavior explains optimizations that use branch conditions, such as CVP (D76931) and GVN (propagateEquality).

For `switch cond`, it is defined to raise UB if cond is an expression containing undef && cond is not frozen &&
it may yield different values.
This allows that at the destination block the branch condition can be assumed to be frozen already (otherwise UB was already triggered).
This condition is slightly stricter than MemorySanitizer, which allows undef-y condition if it always leads to the same destination,
but it does not break MemorySanitizer because we are giving stricter constraint.

Reviewers: efriedma, fhahn, nikic, spatel, jdoerfert, nlopes

Reviewed By: nlopes

Subscribers: regehr, llvm-commits

Tags: #llvm

Differential Revision: https://reviews.llvm.org/D76973
This commit is contained in:
Juneyoung Lee 2020-03-28 15:11:09 +09:00
parent 1519f8d30a
commit 2cd7fcb259

View File

@ -3416,6 +3416,7 @@ uses with" concept would not hold.
To ensure all uses of a given register observe the same value (even if
'``undef``'), the :ref:`freeze instruction <i_freeze>` can be used.
A value is frozen if its uses see the same value.
.. code-block:: llvm
@ -3452,7 +3453,34 @@ match what was already there. However, a store *to* an undefined
location could clobber arbitrary memory, therefore, it has undefined
behavior.
**MemorySanitizer**, a detector of uses of uninitialized memory,
Branching on an undefined value is undefined behavior.
This explains optimizations that depend on branch conditions to construct
predicates, such as Correlated Value Propagation and Global Value Numbering.
In case of switch instruction, the branch condition should be frozen, otherwise
it is undefined behavior.
.. code-block:: text
Unsafe:
br undef, BB1, BB2 ; UB
%X = and i32 undef, 255
switch %X, label %ret [ .. ] ; UB
store undef, i8* %ptr
%X = load i8* %ptr ; %X is undef
switch i8 %X, label %ret [ .. ] ; UB
Safe:
%X = or i8 undef, 255 ; always 255
switch i8 %X, label %ret [ .. ] ; Well-defined
%X = freeze i1 undef
br %X, BB1, BB2 ; Well-defined (non-deterministic jump)
This is also consistent with the behavior of MemorySanitizer.
MemorySanitizer, detector of uses of uninitialized memory,
defines a branch with condition that depends on an undef value (or
certain other values, like e.g. a result of a load from heap-allocated
memory that has never been stored to) to have an externally visible
@ -7035,7 +7063,8 @@ Upon execution of a conditional '``br``' instruction, the '``i1``'
argument is evaluated. If the value is ``true``, control flows to the
'``iftrue``' ``label`` argument. If "cond" is ``false``, control flows
to the '``iffalse``' ``label`` argument.
If '``cond``' is ``poison``, this instruction has undefined behavior.
If '``cond``' is ``poison`` or ``undef``, this instruction has undefined
behavior.
Example:
""""""""
@ -7086,7 +7115,8 @@ When the '``switch``' instruction is executed, this table is searched
for the given value. If the value is found, control flow is transferred
to the corresponding destination; otherwise, control flow is transferred
to the default destination.
If '``value``' is ``poison``, this instruction has undefined behavior.
If '``value``' is ``poison`` or ``undef``, this instruction has undefined
behavior.
Implementation:
"""""""""""""""
@ -7151,7 +7181,8 @@ Control transfers to the block specified in the address argument. All
possible destination blocks must be listed in the label list, otherwise
this instruction has undefined behavior. This implies that jumps to
labels defined in other functions have undefined behavior as well.
If '``address``' is ``poison``, this instruction has undefined behavior.
If '``address``' is ``poison`` or ``undef``, this instruction has undefined
behavior.
Implementation:
"""""""""""""""