First part of PR12251. Add documentation and verifier support for the range

metadata.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@153359 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Rafael Espindola 2012-03-24 00:14:51 +00:00
parent 1db394921b
commit 39dd328ed0
6 changed files with 165 additions and 1 deletions

View File

@ -104,6 +104,7 @@
<ol>
<li><a href="#tbaa">'<tt>tbaa</tt>' Metadata</a></li>
<li><a href="#fpaccuracy">'<tt>fpaccuracy</tt>' Metadata</a></li>
<li><a href="#range">'<tt>range</tt>' Metadata</a></li>
</ol>
</li>
</ol>
@ -3028,6 +3029,39 @@ call void @llvm.dbg.value(metadata !24, i64 0, metadata !25)
</pre>
</div>
<!-- _______________________________________________________________________ -->
<h4>
<a name="range">'<tt>range</tt>' Metadata</a>
</h4>
<div>
<p><tt>range</tt> metadata may be attached only to loads of integer types. It
expresses the possible ranges the loaded value is in. The ranges are
represented with a flattened list of integers. The loaded value is known to
be in the union of the ranges defined by each consecutive pair. Each pair
has the following properties:</p>
<ul>
<li>The type must match the type loaded by the instruction.</li>
<li>The pair <tt>a,b</tt> represents the range <tt>[a,b)</tt>.</li>
<li>Both <tt>a</tt> and <tt>b</tt> are constants.</li>
<li>The range is allowed to wrap.</li>
<li>The range should not represent the full or empty set. That is,
<tt>a!=b</tt>. </li>
</ul>
<p>Examples:</p>
<div class="doc_code">
<pre>
%a = load i8* %x, align 1, !range !0 ; Can only be 0 or 1
%b = load i8* %y, align 1, !range !1 ; Can only be 255 (-1), 0 or 1
%c = load i8* %z, align 1, !range !2 ; Can only be 0, 1, 3, 4 or 5
...
!0 = metadata !{ i8 0, i8 2 }
!1 = metadata !{ i8 255, i8 2 }
!2 = metadata !{ i8 0, i8 2, i8 3, i8 6 }
</pre>
</div>
</div>
</div>
</div>

View File

@ -42,7 +42,8 @@ public:
MD_dbg = 0, // "dbg"
MD_tbaa = 1, // "tbaa"
MD_prof = 2, // "prof"
MD_fpaccuracy = 3 // "fpaccuracy"
MD_fpaccuracy = 3, // "fpaccuracy"
MD_range = 4 // "range"
};
/// getMDKindID - Return a unique non-zero ID for the specified metadata kind.

View File

@ -48,6 +48,11 @@ LLVMContext::LLVMContext() : pImpl(new LLVMContextImpl(*this)) {
unsigned FPAccuracyID = getMDKindID("fpaccuracy");
assert(FPAccuracyID == MD_fpaccuracy && "fpaccuracy kind id drifted");
(void)FPAccuracyID;
// Create the 'range' metadata kind.
unsigned RangeID = getMDKindID("range");
assert(RangeID == MD_range && "range kind id drifted");
(void)RangeID;
}
LLVMContext::~LLVMContext() { delete pImpl; }

View File

@ -51,6 +51,7 @@
#include "llvm/DerivedTypes.h"
#include "llvm/InlineAsm.h"
#include "llvm/IntrinsicInst.h"
#include "llvm/LLVMContext.h"
#include "llvm/Metadata.h"
#include "llvm/Module.h"
#include "llvm/Pass.h"
@ -1369,6 +1370,25 @@ void Verifier::visitLoadInst(LoadInst &LI) {
Assert1(LI.getSynchScope() == CrossThread,
"Non-atomic load cannot have SynchronizationScope specified", &LI);
}
if (MDNode *Range = LI.getMetadata(LLVMContext::MD_range)) {
unsigned NumOperands = Range->getNumOperands();
Assert1(NumOperands % 2 == 0, "Unfinished range!", Range);
unsigned NumRanges = NumOperands / 2;
Assert1(NumRanges >= 1, "It should have at least one range!", Range);
for (unsigned i = 0; i < NumRanges; ++i) {
ConstantInt *Low = dyn_cast<ConstantInt>(Range->getOperand(2*i));
Assert1(Low, "The lower limit must be an integer!", Low);
ConstantInt *High = dyn_cast<ConstantInt>(Range->getOperand(2*i + 1));
Assert1(High, "The upper limit must be an integer!", High);
Assert1(High->getType() == Low->getType() &&
High->getType() == ElTy, "Range types must match load type!",
&LI);
Assert1(High->getValue() != Low->getValue(), "Range must not be empty!",
Range);
}
}
visitInstruction(LI);
}
@ -1641,6 +1661,10 @@ void Verifier::visitInstruction(Instruction &I) {
"Cannot take the address of an inline asm!", &I);
}
}
MDNode *MD = I.getMetadata(LLVMContext::MD_range);
Assert1(!MD || isa<LoadInst>(I), "Ranges are only for loads!", &I);
InstsInThisBlock.insert(&I);
}

78
test/Verifier/range-1.ll Normal file
View File

@ -0,0 +1,78 @@
; RUN: not llvm-as < %s -o /dev/null |& FileCheck %s
define void @f1(i8* %x) {
entry:
store i8 0, i8* %x, align 1, !range !0
ret void
}
!0 = metadata !{i8 0, i8 1}
; CHECK: Ranges are only for loads!
; CHECK-NEXT: store i8 0, i8* %x, align 1, !range !0
define i8 @f2(i8* %x) {
entry:
%y = load i8* %x, align 1, !range !1
ret i8 %y
}
!1 = metadata !{}
; CHECK: It should have at least one range!
; CHECK-NEXT: metadata
define i8 @f3(i8* %x) {
entry:
%y = load i8* %x, align 1, !range !2
ret i8 %y
}
!2 = metadata !{i8 0}
; CHECK: Unfinished range!
define i8 @f4(i8* %x) {
entry:
%y = load i8* %x, align 1, !range !3
ret i8 %y
}
!3 = metadata !{double 0.0, i8 0}
; CHECK: The lower limit must be an integer!
define i8 @f5(i8* %x) {
entry:
%y = load i8* %x, align 1, !range !4
ret i8 %y
}
!4 = metadata !{i8 0, double 0.0}
; CHECK: The upper limit must be an integer!
define i8 @f6(i8* %x) {
entry:
%y = load i8* %x, align 1, !range !5
ret i8 %y
}
!5 = metadata !{i32 0, i8 0}
; CHECK: Range types must match load type!
; CHECK: %y = load
define i8 @f7(i8* %x) {
entry:
%y = load i8* %x, align 1, !range !6
ret i8 %y
}
!6 = metadata !{i8 0, i32 0}
; CHECK: Range types must match load type!
; CHECK: %y = load
define i8 @f8(i8* %x) {
entry:
%y = load i8* %x, align 1, !range !7
ret i8 %y
}
!7 = metadata !{i32 0, i32 0}
; CHECK: Range types must match load type!
; CHECK: %y = load
define i8 @f9(i8* %x) {
entry:
%y = load i8* %x, align 1, !range !8
ret i8 %y
}
!8 = metadata !{i8 0, i8 0}
; CHECK: Range must not be empty!

22
test/Verifier/range-2.ll Normal file
View File

@ -0,0 +1,22 @@
; RUN: llvm-as < %s -o /dev/null
define i8 @f1(i8* %x) {
entry:
%y = load i8* %x, align 1, !range !0
ret i8 %y
}
!0 = metadata !{i8 0, i8 1}
define i8 @f2(i8* %x) {
entry:
%y = load i8* %x, align 1, !range !1
ret i8 %y
}
!1 = metadata !{i8 255, i8 1}
define i8 @f3(i8* %x) {
entry:
%y = load i8* %x, align 1, !range !2
ret i8 %y
}
!2 = metadata !{i8 1, i8 3, i8 5, i8 42}