implement and document support for CHECK-NOT

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@82408 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Chris Lattner 2009-09-20 22:35:26 +00:00
parent 96077036f0
commit f15380ba8a
3 changed files with 101 additions and 8 deletions

View File

@ -594,6 +594,36 @@ directive in a file.</p>
</div>
<!-- _______________________________________________________________________ -->
<div class="doc_subsubsection"><a
name="FileCheck-CHECK-NOT">The "CHECK-NOT:" directive</a></div>
<div class="doc_text">
<p>The CHECK-NOT: directive is used to verify that a string doesn't occur
between two matches (or the first matches and the beginning of the file). For
example, to verify that a load is removed by a transformation, a test like this
can be used:</p>
<div class="doc_code">
<pre>
define i8 @coerce_offset0(i32 %V, i32* %P) {
store i32 %V, i32* %P
%P2 = bitcast i32* %P to i8*
%P3 = getelementptr i8* %P2, i32 2
%A = load i8* %P3
ret i8 %A
; <b>CHECK:</b> @coerce_offset0
; <b>CHECK-NOT:</b> load
; <b>CHECK:</b> ret i8
}
</pre>
</div>
</div>
<!-- _______________________________________________________________________ -->
<div class="doc_subsection"><a name="dgvars">Variables and
substitutions</a></div>

View File

@ -191,3 +191,24 @@ Cont:
; CHECK: ret i8 %A
}
;;===----------------------------------------------------------------------===;;
;; Store -> Load and Load -> Load forwarding where src and dst are different
;; types, and the reload is an offset from the store pointer.
;;===----------------------------------------------------------------------===;;
;; i32 -> f32 forwarding.
define i8 @coerce_offset0(i32 %V, i32* %P) {
store i32 %V, i32* %P
%P2 = bitcast i32* %P to i8*
%P3 = getelementptr i8* %P2, i32 2
%A = load i8* %P3
ret i8 %A
; CHECK: @coerce_offset0
; CHECK-NOT: load
; CHECK: ret i8
}

View File

@ -51,6 +51,11 @@ struct CheckString {
/// to a CHECK: directive.
bool IsCheckNext;
/// NotStrings - These are all of the strings that are disallowed from
/// occurring between this match string and the previous one (or start of
/// file).
std::vector<std::pair<SMLoc, std::string> > NotStrings;
CheckString(const std::string &S, SMLoc L, bool isCheckNext)
: Str(S), Loc(L), IsCheckNext(isCheckNext) {}
};
@ -74,6 +79,8 @@ static bool ReadCheckFile(SourceMgr &SM,
// Find all instances of CheckPrefix followed by : in the file.
StringRef Buffer = F->getBuffer();
std::vector<std::pair<SMLoc, std::string> > NotMatches;
while (1) {
// See if Prefix occurs in the memory buffer.
Buffer = Buffer.substr(Buffer.find(CheckPrefix));
@ -86,16 +93,19 @@ static bool ReadCheckFile(SourceMgr &SM,
// When we find a check prefix, keep track of whether we find CHECK: or
// CHECK-NEXT:
bool IsCheckNext;
bool IsCheckNext = false, IsCheckNot = false;
// Verify that the : is present after the prefix.
if (Buffer[CheckPrefix.size()] == ':') {
Buffer = Buffer.substr(CheckPrefix.size()+1);
IsCheckNext = false;
} else if (Buffer.size() > CheckPrefix.size()+6 &&
memcmp(Buffer.data()+CheckPrefix.size(), "-NEXT:", 6) == 0) {
Buffer = Buffer.substr(CheckPrefix.size()+7);
IsCheckNext = true;
} else if (Buffer.size() > CheckPrefix.size()+5 &&
memcmp(Buffer.data()+CheckPrefix.size(), "-NOT:", 5) == 0) {
Buffer = Buffer.substr(CheckPrefix.size()+6);
IsCheckNot = true;
} else {
Buffer = Buffer.substr(1);
continue;
@ -103,8 +113,7 @@ static bool ReadCheckFile(SourceMgr &SM,
// Okay, we found the prefix, yay. Remember the rest of the line, but
// ignore leading and trailing whitespace.
while (!Buffer.empty() && (Buffer[0] == ' ' || Buffer[0] == '\t'))
Buffer = Buffer.substr(1);
Buffer = Buffer.substr(Buffer.find_first_not_of(" \t"));
// Scan ahead to the end of line.
size_t EOL = Buffer.find_first_of("\n\r");
@ -122,6 +131,16 @@ static bool ReadCheckFile(SourceMgr &SM,
return true;
}
StringRef PatternStr = Buffer.substr(0, EOL);
// Handle CHECK-NOT.
if (IsCheckNot) {
NotMatches.push_back(std::make_pair(SMLoc::getFromPointer(Buffer.data()),
PatternStr.str()));
Buffer = Buffer.substr(EOL);
continue;
}
// Verify that CHECK-NEXT lines have at least one CHECK line before them.
if (IsCheckNext && CheckStrings.empty()) {
SM.PrintMessage(SMLoc::getFromPointer(CheckPrefixStart),
@ -131,10 +150,10 @@ static bool ReadCheckFile(SourceMgr &SM,
}
// Okay, add the string we captured to the output vector and move on.
CheckStrings.push_back(CheckString(std::string(Buffer.data(),
Buffer.data()+EOL),
CheckStrings.push_back(CheckString(PatternStr.str(),
SMLoc::getFromPointer(Buffer.data()),
IsCheckNext));
std::swap(NotMatches, CheckStrings.back().NotStrings);
Buffer = Buffer.substr(EOL);
}
@ -145,6 +164,12 @@ static bool ReadCheckFile(SourceMgr &SM,
return true;
}
if (!NotMatches.empty()) {
errs() << "error: '" << CheckPrefix
<< "-NOT:' not supported after last check line.\n";
return true;
}
return false;
}
@ -271,7 +296,8 @@ int main(int argc, char **argv) {
// file.
StringRef Buffer = F->getBuffer();
const char *LastMatch = 0;
const char *LastMatch = Buffer.data();
for (unsigned StrNo = 0, e = CheckStrings.size(); StrNo != e; ++StrNo) {
const CheckString &CheckStr = CheckStrings[StrNo];
@ -290,7 +316,8 @@ int main(int argc, char **argv) {
// the previous line (i.e. that there is one newline between them).
if (CheckStr.IsCheckNext) {
// Count the number of newlines between the previous match and this one.
assert(LastMatch && "CHECK-NEXT can't be the first check in a file");
assert(LastMatch != F->getBufferStart() &&
"CHECK-NEXT can't be the first check in a file");
unsigned NumNewLines = CountNumNewlinesBetween(LastMatch, Buffer.data());
if (NumNewLines == 0) {
@ -316,6 +343,21 @@ int main(int argc, char **argv) {
return 1;
}
}
// If this match had "not strings", verify that they don't exist in the
// skipped region.
StringRef SkippedRegion(LastMatch, Buffer.data()-LastMatch);
for (unsigned i = 0, e = CheckStr.NotStrings.size(); i != e; ++i) {
size_t Pos = SkippedRegion.find(CheckStr.NotStrings[i].second);
if (Pos == StringRef::npos) continue;
SM.PrintMessage(SMLoc::getFromPointer(LastMatch+Pos),
CheckPrefix+"-NOT: string occurred!", "error");
SM.PrintMessage(CheckStr.NotStrings[i].first,
CheckPrefix+"-NOT: pattern specified here", "note");
return 1;
}
// Otherwise, everything is good. Remember this as the last match and move
// on to the next one.