[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