diff options
author | Chris Lattner <sabre@nondot.org> | 2009-09-20 22:35:26 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2009-09-20 22:35:26 +0000 |
commit | f15380ba8ae35941dcd56d9a288ad023295dde30 (patch) | |
tree | 456d6cfae5b5b5c66614ff86923984bb850161e5 | |
parent | 96077036f06478d96c123283a50cfba49858fd40 (diff) | |
download | external_llvm-f15380ba8ae35941dcd56d9a288ad023295dde30.zip external_llvm-f15380ba8ae35941dcd56d9a288ad023295dde30.tar.gz external_llvm-f15380ba8ae35941dcd56d9a288ad023295dde30.tar.bz2 |
implement and document support for CHECK-NOT
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@82408 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | docs/TestingGuide.html | 30 | ||||
-rw-r--r-- | test/Transforms/GVN/rle.ll | 21 | ||||
-rw-r--r-- | utils/FileCheck/FileCheck.cpp | 58 |
3 files changed, 101 insertions, 8 deletions
diff --git a/docs/TestingGuide.html b/docs/TestingGuide.html index f974363..9e4a40a 100644 --- a/docs/TestingGuide.html +++ b/docs/TestingGuide.html @@ -595,6 +595,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> <!-- _______________________________________________________________________ --> diff --git a/test/Transforms/GVN/rle.ll b/test/Transforms/GVN/rle.ll index 1c5ab67..6b45890 100644 --- a/test/Transforms/GVN/rle.ll +++ b/test/Transforms/GVN/rle.ll @@ -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 +} + + + diff --git a/utils/FileCheck/FileCheck.cpp b/utils/FileCheck/FileCheck.cpp index 8de2612..b429f5d 100644 --- a/utils/FileCheck/FileCheck.cpp +++ b/utils/FileCheck/FileCheck.cpp @@ -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. |