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:
parent
575af2b076
commit
d817c75cad
@ -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:
|
||||
""""""""""
|
||||
|
||||
|
@ -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());
|
||||
|
@ -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));
|
||||
|
@ -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) {
|
||||
|
6
test/Verifier/dereferenceable-md-inttoptr.ll
Normal file
6
test/Verifier/dereferenceable-md-inttoptr.ll
Normal 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
|
||||
}
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user