[llvm-commits] [llvm] r82408 - in /llvm/trunk: docs/TestingGuide.html test/Transforms/GVN/rle.ll utils/FileCheck/FileCheck.cpp

Chris Lattner sabre at nondot.org
Sun Sep 20 15:35:26 PDT 2009


Author: lattner
Date: Sun Sep 20 17:35:26 2009
New Revision: 82408

URL: http://llvm.org/viewvc/llvm-project?rev=82408&view=rev
Log:
implement and document support for CHECK-NOT

Modified:
    llvm/trunk/docs/TestingGuide.html
    llvm/trunk/test/Transforms/GVN/rle.ll
    llvm/trunk/utils/FileCheck/FileCheck.cpp

Modified: llvm/trunk/docs/TestingGuide.html
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/TestingGuide.html?rev=82408&r1=82407&r2=82408&view=diff

==============================================================================
--- llvm/trunk/docs/TestingGuide.html (original)
+++ llvm/trunk/docs/TestingGuide.html Sun Sep 20 17:35:26 2009
@@ -595,6 +595,36 @@
 </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>
 <!-- _______________________________________________________________________ -->

Modified: llvm/trunk/test/Transforms/GVN/rle.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/rle.ll?rev=82408&r1=82407&r2=82408&view=diff

==============================================================================
--- llvm/trunk/test/Transforms/GVN/rle.ll (original)
+++ llvm/trunk/test/Transforms/GVN/rle.ll Sun Sep 20 17:35:26 2009
@@ -191,3 +191,24 @@
 ; 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
+}
+
+
+

Modified: llvm/trunk/utils/FileCheck/FileCheck.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/FileCheck/FileCheck.cpp?rev=82408&r1=82407&r2=82408&view=diff

==============================================================================
--- llvm/trunk/utils/FileCheck/FileCheck.cpp (original)
+++ llvm/trunk/utils/FileCheck/FileCheck.cpp Sun Sep 20 17:35:26 2009
@@ -51,6 +51,11 @@
   /// 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 @@
   // 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 @@
     
     // 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 @@
     
     // 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 @@
       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 @@
     }
     
     // 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 @@
     return true;
   }
   
+  if (!NotMatches.empty()) {
+    errs() << "error: '" << CheckPrefix
+           << "-NOT:' not supported after last check line.\n";
+    return true;
+  }
+  
   return false;
 }
 
@@ -271,7 +296,8 @@
   // 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 @@
     // 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 @@
         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.





More information about the llvm-commits mailing list