1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2025-01-31 20:51:52 +01:00

[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

llvm-svn: 366826
This commit is contained in:
Ryan Taylor 2019-07-23 17:19:56 +00:00
parent 575af2b076
commit d817c75cad
6 changed files with 116 additions and 20 deletions

View File

@ -5303,6 +5303,29 @@ optimizations related to compare and branch instructions. The metadata
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 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``
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 :ref:`integer <t_integer>` value to
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:
""""""""""

View File

@ -650,6 +650,19 @@ uint64_t Value::getPointerDereferenceableBytes(const DataLayout &DL,
}
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());

View File

@ -3983,9 +3983,9 @@ void Verifier::verifyDominatesUse(Instruction &I, unsigned i) {
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));

View File

@ -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) {

View File

@ -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
}

View File

@ -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
; 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