Index: docs/LangRef.rst =================================================================== --- docs/LangRef.rst +++ docs/LangRef.rst @@ -5303,6 +5303,29 @@ 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 @@ Irreducible loop header weights are typically based on profile data. +.. _md_invariant.group: + '``invariant.group``' Metadata ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -8602,7 +8627,7 @@ The optional ``!invariant.group`` metadata must reference a single metadata name ```` 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 ```` corresponding to a metadata node with no @@ -8614,22 +8639,14 @@ The optional ``!dereferenceable`` metadata must reference a single metadata name ```` 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 ```` 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 ```` corresponding to a metadata node with one ``i64`` entry. @@ -9626,7 +9643,7 @@ :: - = inttoptr to ; yields ty2 + = inttoptr to [, !dereferenceable !][, !dereferenceable_or_null !` type. +The optional ``!dereferenceable`` metadata must reference a single metadata +name ```` corresponding to a metadata node with one ``i64`` +entry. +See ``dereferenceable`` metadata. + +The optional ``!dereferenceable_or_null`` metadata must reference a single +metadata name ```` corresponding to a metadata node with one +``i64`` entry. +See ``dereferenceable_or_null`` metadata. + Semantics: """""""""" Index: lib/IR/Value.cpp =================================================================== --- lib/IR/Value.cpp +++ lib/IR/Value.cpp @@ -650,6 +650,19 @@ } CanBeNull = true; } + } else if (auto *IP = dyn_cast(this)) { + if (MDNode *MD = IP->getMetadata(LLVMContext::MD_dereferenceable)) { + ConstantInt *CI = mdconst::extract(MD->getOperand(0)); + DerefBytes = CI->getLimitedValue(); + } + if (DerefBytes == 0) { + if (MDNode *MD = + IP->getMetadata(LLVMContext::MD_dereferenceable_or_null)) { + ConstantInt *CI = mdconst::extract(MD->getOperand(0)); + DerefBytes = CI->getLimitedValue(); + } + CanBeNull = true; + } } else if (auto *AI = dyn_cast(this)) { if (!AI->isArrayAllocation()) { DerefBytes = DL.getTypeStoreSize(AI->getAllocatedType()); Index: lib/IR/Verifier.cpp =================================================================== --- lib/IR/Verifier.cpp +++ lib/IR/Verifier.cpp @@ -3983,9 +3983,9 @@ void Verifier::visitDereferenceableMetadata(Instruction& I, MDNode* MD) { Assert(I.getType()->isPointerTy(), "dereferenceable, dereferenceable_or_null " "apply only to pointer types", &I); - Assert(isa(I), + Assert((isa(I) || isa(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(MD->getOperand(0)); Index: test/Analysis/ValueTracking/memory-dereferenceable.ll =================================================================== --- test/Analysis/ValueTracking/memory-dereferenceable.ll +++ test/Analysis/ValueTracking/memory-dereferenceable.ll @@ -172,6 +172,14 @@ 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) { Index: test/Verifier/dereferenceable-md-inttoptr.ll =================================================================== --- /dev/null +++ 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 +} Index: test/Verifier/dereferenceable-md.ll =================================================================== --- test/Verifier/dereferenceable-md.ll +++ test/Verifier/dereferenceable-md.ll @@ -7,7 +7,7 @@ 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 @@ 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 @@ 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