diff options
Diffstat (limited to 'llvm')
| -rw-r--r-- | llvm/docs/LangRef.rst | 57 | ||||
| -rw-r--r-- | llvm/lib/IR/Value.cpp | 13 | ||||
| -rw-r--r-- | llvm/lib/IR/Verifier.cpp | 4 | ||||
| -rw-r--r-- | llvm/test/Analysis/ValueTracking/memory-dereferenceable.ll | 8 | ||||
| -rw-r--r-- | llvm/test/Verifier/dereferenceable-md-inttoptr.ll | 6 | ||||
| -rw-r--r-- | llvm/test/Verifier/dereferenceable-md.ll | 48 |
6 files changed, 116 insertions, 20 deletions
diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst index 87e8a557504..f3b28029936 100644 --- a/llvm/docs/LangRef.rst +++ b/llvm/docs/LangRef.rst @@ -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: """""""""" diff --git a/llvm/lib/IR/Value.cpp b/llvm/lib/IR/Value.cpp index b7f77dc3043..6a743b708f9 100644 --- a/llvm/lib/IR/Value.cpp +++ b/llvm/lib/IR/Value.cpp @@ -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()); diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp index 9346c8bda75..1793ba42009 100644 --- a/llvm/lib/IR/Verifier.cpp +++ b/llvm/lib/IR/Verifier.cpp @@ -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)); diff --git a/llvm/test/Analysis/ValueTracking/memory-dereferenceable.ll b/llvm/test/Analysis/ValueTracking/memory-dereferenceable.ll index 2e9453f670c..80bc72d0d5b 100644 --- a/llvm/test/Analysis/ValueTracking/memory-dereferenceable.ll +++ b/llvm/test/Analysis/ValueTracking/memory-dereferenceable.ll @@ -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) { diff --git a/llvm/test/Verifier/dereferenceable-md-inttoptr.ll b/llvm/test/Verifier/dereferenceable-md-inttoptr.ll new file mode 100644 index 00000000000..8c3c57e7d39 --- /dev/null +++ b/llvm/test/Verifier/dereferenceable-md-inttoptr.ll @@ -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 +} diff --git a/llvm/test/Verifier/dereferenceable-md.ll b/llvm/test/Verifier/dereferenceable-md.ll index 94c89c33202..d1b38abd8e4 100644 --- a/llvm/test/Verifier/dereferenceable-md.ll +++ b/llvm/test/Verifier/dereferenceable-md.ll @@ -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 |

