[llvm] r366826 - [IR][Verifier] Allow IntToPtrInst to be !dereferenceable
Ryan Taylor via llvm-commits
llvm-commits at lists.llvm.org
Tue Jul 23 10:19:56 PDT 2019
Author: rtayl
Date: Tue Jul 23 10:19:56 2019
New Revision: 366826
URL: http://llvm.org/viewvc/llvm-project?rev=366826&view=rev
Log:
[IR][Verifier] Allow IntToPtrInst to be !dereferenceable
Summary:
Allow IntToPtrInst to carry !dereferenceable metadata tag.
This is valid since !dereferenceable can be only be applied to
pointer type values.
Change-Id: If8a6e3c616f073d51eaff52ab74535c29ed497b4
Subscribers: llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D64954
Added:
llvm/trunk/test/Verifier/dereferenceable-md-inttoptr.ll
Modified:
llvm/trunk/docs/LangRef.rst
llvm/trunk/lib/IR/Value.cpp
llvm/trunk/lib/IR/Verifier.cpp
llvm/trunk/test/Analysis/ValueTracking/memory-dereferenceable.ll
llvm/trunk/test/Verifier/dereferenceable-md.ll
Modified: llvm/trunk/docs/LangRef.rst
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/LangRef.rst?rev=366826&r1=366825&r2=366826&view=diff
==============================================================================
--- llvm/trunk/docs/LangRef.rst (original)
+++ llvm/trunk/docs/LangRef.rst Tue Jul 23 10:19:56 2019
@@ -5303,6 +5303,29 @@ optimizations related to compare and bra
is treated as a boolean value; if it exists, it signals that the branch
or switch that it is attached to is completely unpredictable.
+.. _md_dereferenceable:
+
+'``dereferenceable``' Metadata
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The existence of the ``!dereferenceable`` metadata on the instruction
+tells the optimizer that the value loaded is known to be dereferenceable.
+The number of bytes known to be dereferenceable is specified by the integer
+value in the metadata node. This is analogous to the ''dereferenceable''
+attribute on parameters and return values.
+
+.. _md_dereferenceable_or_null:
+
+'``dereferenceable_or_null``' Metadata
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The existence of the ``!dereferenceable_or_null`` metadata on the
+instruction tells the optimizer that the value loaded is known to be either
+dereferenceable or null.
+The number of bytes known to be dereferenceable is specified by the integer
+value in the metadata node. This is analogous to the ''dereferenceable_or_null''
+attribute on parameters and return values.
+
.. _llvm.loop:
'``llvm.loop``'
@@ -5807,6 +5830,8 @@ the irreducible loop) of 100:
Irreducible loop header weights are typically based on profile data.
+.. _md_invariant.group:
+
'``invariant.group``' Metadata
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -8602,7 +8627,7 @@ otherwise, the behavior is undefined.
The optional ``!invariant.group`` metadata must reference a single metadata name
``<index>`` corresponding to a metadata node with no entries.
- See ``invariant.group`` metadata.
+ See ``invariant.group`` metadata :ref:`invariant.group <md_invariant.group>`
The optional ``!nonnull`` metadata must reference a single
metadata name ``<index>`` corresponding to a metadata node with no
@@ -8614,22 +8639,14 @@ values. This metadata can only be applie
The optional ``!dereferenceable`` metadata must reference a single metadata
name ``<deref_bytes_node>`` corresponding to a metadata node with one ``i64``
-entry. The existence of the ``!dereferenceable`` metadata on the instruction
-tells the optimizer that the value loaded is known to be dereferenceable.
-The number of bytes known to be dereferenceable is specified by the integer
-value in the metadata node. This is analogous to the ''dereferenceable''
-attribute on parameters and return values. This metadata can only be applied
-to loads of a pointer type.
+entry.
+See ``dereferenceable`` metadata :ref:`dereferenceable <md_dereferenceable>`
The optional ``!dereferenceable_or_null`` metadata must reference a single
metadata name ``<deref_bytes_node>`` corresponding to a metadata node with one
-``i64`` entry. The existence of the ``!dereferenceable_or_null`` metadata on the
-instruction tells the optimizer that the value loaded is known to be either
-dereferenceable or null.
-The number of bytes known to be dereferenceable is specified by the integer
-value in the metadata node. This is analogous to the ''dereferenceable_or_null''
-attribute on parameters and return values. This metadata can only be applied
-to loads of a pointer type.
+``i64`` entry.
+See ``dereferenceable_or_null`` metadata :ref:`dereferenceable_or_null
+<md_dereferenceable_or_null>`
The optional ``!align`` metadata must reference a single metadata name
``<align_node>`` corresponding to a metadata node with one ``i64`` entry.
@@ -9626,7 +9643,7 @@ Syntax:
::
- <result> = inttoptr <ty> <value> to <ty2> ; yields ty2
+ <result> = inttoptr <ty> <value> to <ty2>[, !dereferenceable !<deref_bytes_node>][, !dereferenceable_or_null !<deref_bytes_node] ; yields ty2
Overview:
"""""""""
@@ -9641,6 +9658,16 @@ The '``inttoptr``' instruction takes an
cast, and a type to cast it to, which must be a :ref:`pointer <t_pointer>`
type.
+The optional ``!dereferenceable`` metadata must reference a single metadata
+name ``<deref_bytes_node>`` corresponding to a metadata node with one ``i64``
+entry.
+See ``dereferenceable`` metadata.
+
+The optional ``!dereferenceable_or_null`` metadata must reference a single
+metadata name ``<deref_bytes_node>`` corresponding to a metadata node with one
+``i64`` entry.
+See ``dereferenceable_or_null`` metadata.
+
Semantics:
""""""""""
Modified: llvm/trunk/lib/IR/Value.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/Value.cpp?rev=366826&r1=366825&r2=366826&view=diff
==============================================================================
--- llvm/trunk/lib/IR/Value.cpp (original)
+++ llvm/trunk/lib/IR/Value.cpp Tue Jul 23 10:19:56 2019
@@ -650,6 +650,19 @@ uint64_t Value::getPointerDereferenceabl
}
CanBeNull = true;
}
+ } else if (auto *IP = dyn_cast<IntToPtrInst>(this)) {
+ if (MDNode *MD = IP->getMetadata(LLVMContext::MD_dereferenceable)) {
+ ConstantInt *CI = mdconst::extract<ConstantInt>(MD->getOperand(0));
+ DerefBytes = CI->getLimitedValue();
+ }
+ if (DerefBytes == 0) {
+ if (MDNode *MD =
+ IP->getMetadata(LLVMContext::MD_dereferenceable_or_null)) {
+ ConstantInt *CI = mdconst::extract<ConstantInt>(MD->getOperand(0));
+ DerefBytes = CI->getLimitedValue();
+ }
+ CanBeNull = true;
+ }
} else if (auto *AI = dyn_cast<AllocaInst>(this)) {
if (!AI->isArrayAllocation()) {
DerefBytes = DL.getTypeStoreSize(AI->getAllocatedType());
Modified: llvm/trunk/lib/IR/Verifier.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/Verifier.cpp?rev=366826&r1=366825&r2=366826&view=diff
==============================================================================
--- llvm/trunk/lib/IR/Verifier.cpp (original)
+++ llvm/trunk/lib/IR/Verifier.cpp Tue Jul 23 10:19:56 2019
@@ -3983,9 +3983,9 @@ void Verifier::verifyDominatesUse(Instru
void Verifier::visitDereferenceableMetadata(Instruction& I, MDNode* MD) {
Assert(I.getType()->isPointerTy(), "dereferenceable, dereferenceable_or_null "
"apply only to pointer types", &I);
- Assert(isa<LoadInst>(I),
+ Assert((isa<LoadInst>(I) || isa<IntToPtrInst>(I)),
"dereferenceable, dereferenceable_or_null apply only to load"
- " instructions, use attributes for calls or invokes", &I);
+ " and inttoptr instructions, use attributes for calls or invokes", &I);
Assert(MD->getNumOperands() == 1, "dereferenceable, dereferenceable_or_null "
"take one operand!", &I);
ConstantInt *CI = mdconst::dyn_extract<ConstantInt>(MD->getOperand(0));
Modified: llvm/trunk/test/Analysis/ValueTracking/memory-dereferenceable.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Analysis/ValueTracking/memory-dereferenceable.ll?rev=366826&r1=366825&r2=366826&view=diff
==============================================================================
--- llvm/trunk/test/Analysis/ValueTracking/memory-dereferenceable.ll (original)
+++ llvm/trunk/test/Analysis/ValueTracking/memory-dereferenceable.ll Tue Jul 23 10:19:56 2019
@@ -172,6 +172,14 @@ entry:
ret void
}
+; CHECK: The following are dereferenceable:
+; CHECK: %ptr = inttoptr i32 %val to i32*, !dereferenceable !0
+define i32 @f_0(i32 %val) {
+ %ptr = inttoptr i32 %val to i32*, !dereferenceable !0
+ %load29 = load i32, i32* %ptr, align 8
+ ret i32 %load29
+}
+
; Just check that we don't crash.
; CHECK-LABEL: 'opaque_type_crasher'
define void @opaque_type_crasher(%TypeOpaque* dereferenceable(16) %a) {
Added: llvm/trunk/test/Verifier/dereferenceable-md-inttoptr.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Verifier/dereferenceable-md-inttoptr.ll?rev=366826&view=auto
==============================================================================
--- llvm/trunk/test/Verifier/dereferenceable-md-inttoptr.ll (added)
+++ llvm/trunk/test/Verifier/dereferenceable-md-inttoptr.ll Tue Jul 23 10:19:56 2019
@@ -0,0 +1,6 @@
+; RUN: llvm-as < %s -o /dev/null
+
+define i8* @f_0(i8 %val) {
+ %ptr = inttoptr i8 %val to i8*, !dereferenceable_or_null !{i64 2}
+ ret i8* %ptr
+}
Modified: llvm/trunk/test/Verifier/dereferenceable-md.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Verifier/dereferenceable-md.ll?rev=366826&r1=366825&r2=366826&view=diff
==============================================================================
--- llvm/trunk/test/Verifier/dereferenceable-md.ll (original)
+++ llvm/trunk/test/Verifier/dereferenceable-md.ll Tue Jul 23 10:19:56 2019
@@ -7,7 +7,7 @@ entry:
call i8* @foo(), !dereferenceable !{i64 2}
ret void
}
-; CHECK: dereferenceable, dereferenceable_or_null apply only to load instructions, use attributes for calls or invokes
+; CHECK: dereferenceable, dereferenceable_or_null apply only to load and inttoptr instructions, use attributes for calls or invokes
; CHECK-NEXT: call i8* @foo()
define void @f2() {
@@ -15,7 +15,7 @@ entry:
call i8* @foo(), !dereferenceable_or_null !{i64 2}
ret void
}
-; CHECK: dereferenceable, dereferenceable_or_null apply only to load instructions, use attributes for calls or invokes
+; CHECK: dereferenceable, dereferenceable_or_null apply only to load and inttoptr instructions, use attributes for calls or invokes
; CHECK-NEXT: call i8* @foo()
define i8 @f3(i8* %x) {
@@ -83,4 +83,46 @@ entry:
ret i8* %y
}
; CHECK: dereferenceable, dereferenceable_or_null metadata value must be an i64!
-; CHECK-NEXT: load i8*, i8** %x
\ No newline at end of file
+; CHECK-NEXT: load i8*, i8** %x
+
+define i8* @f_11(i8 %val) {
+ %ptr = inttoptr i8 %val to i8*, !dereferenceable !{i32 2}
+ ret i8* %ptr
+}
+; CHECK: dereferenceable, dereferenceable_or_null metadata value must be an i64!
+; CHECK-NEXT: %ptr = inttoptr i8 %val to i8*, !dereferenceable !3
+
+define i8* @f_12(i8 %val) {
+ %ptr = inttoptr i8 %val to i8*, !dereferenceable_or_null !{i32 2}
+ ret i8* %ptr
+}
+; CHECK: dereferenceable, dereferenceable_or_null metadata value must be an i64!
+; CHECK-NEXT: %ptr = inttoptr i8 %val to i8*, !dereferenceable_or_null !3
+
+define i8* @f_13(i8 %val) {
+ %ptr = inttoptr i8 %val to i8*, !dereferenceable !{}
+ ret i8* %ptr
+}
+; CHECK: dereferenceable, dereferenceable_or_null take one operand
+; CHECK-NEXT: %ptr = inttoptr i8 %val to i8*, !dereferenceable !1
+
+define i8* @f_14(i8 %val) {
+ %ptr = inttoptr i8 %val to i8*, !dereferenceable_or_null !{}
+ ret i8* %ptr
+}
+; CHECK: dereferenceable, dereferenceable_or_null take one operand
+; CHECK-NEXT: %ptr = inttoptr i8 %val to i8*, !dereferenceable_or_null !1
+
+define i8* @f_15(i8 %val) {
+ %ptr = inttoptr i8 %val to i8*, !dereferenceable !{!"str"}
+ ret i8* %ptr
+}
+; CHECK: dereferenceable, dereferenceable_or_null metadata value must be an i64!
+; CHECK-NEXT: %ptr = inttoptr i8 %val to i8*, !dereferenceable !2
+
+define i8* @f_16(i8 %val) {
+ %ptr = inttoptr i8 %val to i8*, !dereferenceable_or_null !{!"str"}
+ ret i8* %ptr
+}
+; CHECK: dereferenceable, dereferenceable_or_null metadata value must be an i64!
+; CHECK-NEXT: %ptr = inttoptr i8 %val to i8*, !dereferenceable_or_null !2
More information about the llvm-commits
mailing list