Index: docs/LangRef.rst =================================================================== --- docs/LangRef.rst +++ docs/LangRef.rst @@ -9626,7 +9626,7 @@ :: - = inttoptr to ; yields ty2 + = inttoptr to [, !dereferenceable !] ; yields ty2 Overview: """"""""" @@ -9641,6 +9641,25 @@ cast, and a type to cast it to, which must be a :ref:`pointer ` type. +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. + +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. + Semantics: """""""""" 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/Verifier/dereferenceable-md-inttoptr.ll =================================================================== --- /dev/null +++ test/Verifier/dereferenceable-md-inttoptr.ll @@ -0,0 +1,10 @@ +; RUN: llc < %s -march=amdgcn -mcpu=verde -verify-machineinstrs | FileCheck %s +; RUN: llc < %s -march=amdgcn -mcpu=tonga -verify-machineinstrs | FileCheck %s +; RUN: llc < %s -march=amdgcn -mcpu=gfx900 -verify-machineinstrs | FileCheck %s + +; CHECK: f_0: + +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