Skip to content

Commit e4251fc

Browse files
committed
[LangRef][Local] dereferenceable metadata violation is UB
I believe !dereferencable violation is immediate undefined behavior, but this was not explicitly spelled out in LangRef. We already assume that !dereferenceable is implicitly !noundef and cannot return poison in isGuaranteedNotToBeUndefOrPoison(). The reason why we made dereferenceable implicitly noundef is that the purpose of this metadata is to allow speculation, and that would not be legal on a potential poison pointer. Differential Revision: https://reviews.llvm.org/D148202
1 parent c508e93 commit e4251fc

File tree

3 files changed

+7
-5
lines changed

3 files changed

+7
-5
lines changed

llvm/docs/LangRef.rst

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6656,7 +6656,8 @@ or switch that it is attached to is completely unpredictable.
66566656
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
66576657

66586658
The existence of the ``!dereferenceable`` metadata on the instruction
6659-
tells the optimizer that the value loaded is known to be dereferenceable.
6659+
tells the optimizer that the value loaded is known to be dereferenceable,
6660+
otherwise the behavior is undefined.
66606661
The number of bytes known to be dereferenceable is specified by the integer
66616662
value in the metadata node. This is analogous to the ''dereferenceable''
66626663
attribute on parameters and return values.
@@ -6668,7 +6669,7 @@ attribute on parameters and return values.
66686669

66696670
The existence of the ``!dereferenceable_or_null`` metadata on the
66706671
instruction tells the optimizer that the value loaded is known to be either
6671-
dereferenceable or null.
6672+
dereferenceable or null, otherwise the behavior is undefined.
66726673
The number of bytes known to be dereferenceable is specified by the integer
66736674
value in the metadata node. This is analogous to the ''dereferenceable_or_null''
66746675
attribute on parameters and return values.

llvm/lib/Transforms/Utils/Local.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2701,8 +2701,9 @@ void llvm::combineMetadata(Instruction *K, const Instruction *J,
27012701
break;
27022702
case LLVMContext::MD_dereferenceable:
27032703
case LLVMContext::MD_dereferenceable_or_null:
2704-
K->setMetadata(Kind,
2705-
MDNode::getMostGenericAlignmentOrDereferenceable(JMD, KMD));
2704+
if (DoesKMove)
2705+
K->setMetadata(Kind,
2706+
MDNode::getMostGenericAlignmentOrDereferenceable(JMD, KMD));
27062707
break;
27072708
case LLVMContext::MD_preserve_access_index:
27082709
// Preserve !preserve.access.index in K.

llvm/test/Transforms/GVN/metadata.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ define i32 @load_load_noundef(ptr %p) {
138138
define void @load_dereferenceable_dominating(ptr %p) {
139139
; CHECK-LABEL: define void @load_dereferenceable_dominating
140140
; CHECK-SAME: (ptr [[P:%.*]]) {
141-
; CHECK-NEXT: [[A:%.*]] = load ptr, ptr [[P]], align 8
141+
; CHECK-NEXT: [[A:%.*]] = load ptr, ptr [[P]], align 8, !dereferenceable !7
142142
; CHECK-NEXT: call void @use.ptr(ptr [[A]])
143143
; CHECK-NEXT: call void @use.ptr(ptr [[A]])
144144
; CHECK-NEXT: ret void

0 commit comments

Comments
 (0)