Index: llvm/docs/CommandGuide/FileCheck.rst =================================================================== --- llvm/docs/CommandGuide/FileCheck.rst +++ llvm/docs/CommandGuide/FileCheck.rst @@ -226,9 +226,9 @@ Sometimes you want to match lines and would like to verify that matches happen on exactly consecutive lines with no other lines in between them. In -this case, you can use "``CHECK:``" and "``CHECK-NEXT:``" directives to specify -this. If you specified a custom check prefix, just use "``-NEXT:``". -For example, something like this works as you'd expect: +this case, you can use "``CHECK-NEXT:``" directives to specify this. If you +specified a custom check prefix, just use "``-NEXT:``". For example, +something like this works as you'd expect: .. code-block:: llvm @@ -252,14 +252,18 @@ "``CHECK-NEXT:``" directives reject the input unless there is exactly one newline between it and the previous directive. A "``CHECK-NEXT:``" cannot be -the first directive in a file. +the first positive directive (i.e. if removing all "``CHECK-NOT``" directives) +in a file. + +If the previous directive is a "``CHECK-DAG``", the "``CHECK-NEXT``" will be +relative to the "``CHECK-DAG``" that was matched last in the input file. The "CHECK-SAME:" directive ~~~~~~~~~~~~~~~~~~~~~~~~~~~ Sometimes you want to match lines and would like to verify that matches happen -on the same line as the previous match. In this case, you can use "``CHECK:``" -and "``CHECK-SAME:``" directives to specify this. If you specified a custom +on the same line as the previous match. In this case, you can use +"``CHECK-SAME:``" directives to specify this. If you specified a custom check prefix, just use "``-SAME:``". "``CHECK-SAME:``" is particularly powerful in conjunction with "``CHECK-NOT:``" @@ -277,7 +281,10 @@ "``CHECK-SAME:``" directives reject the input if there are any newlines between it and the previous directive. A "``CHECK-SAME:``" cannot be the first -directive in a file. +positive directive (i.e. if removing all "``CHECK-NOT``" directives) in a file. + +If the previous directive is a "``CHECK-DAG``", the "``CHECK-SAME``" will be +relative to the "``CHECK-DAG``" that was matched last in the input file. The "CHECK-EMPTY:" directive ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -296,7 +303,7 @@ Just like "``CHECK-NEXT:``" the directive will fail if there is more than one newline before it finds the next blank line, and it cannot be the first -directive in a file. +positive directive in a file. The "CHECK-NOT:" directive ~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -440,6 +447,27 @@ as the first pair even though the patterns are identical and even if the text of the log entries is identical because the thread ID manages to be reused. +When a DAG block is followed by a ``CHECK-SAME``, ``CHECK-NEXT`` or +``CHECK-EMPTY`` directive, those will search relative to the DAG directive that +matches last in the input file. In other words: + +.. code-block:: text + + // CHECK-DAG: mov r0, #0 + // CHECK-DAG: mov r1, #1 + // CHECK-NEXT: add r2, r0, r1 + +will successfully match with the input: + +.. code-block:: text + + mov r1, #1 + mov r0, #0 + add r2, r0, r1 + +``CHECK-DAG: mov r0, #0`` is the last DAG line from the DAG block matched in +the input file so the CHECK-NEXT is relative to that line. + The "CHECK-LABEL:" directive ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Index: llvm/lib/Support/FileCheck.cpp =================================================================== --- llvm/lib/Support/FileCheck.cpp +++ llvm/lib/Support/FileCheck.cpp @@ -841,10 +841,15 @@ Buffer = Buffer.substr(EOL); - // Verify that CHECK-NEXT/SAME/EMPTY lines have at least one CHECK line before them. + // Verify that CHECK-NEXT/SAME/EMPTY lines have at least one positive CHECK + // line (i.e. something else than CHECK-NOT) before them. if ((CheckTy == Check::CheckNext || CheckTy == Check::CheckSame || CheckTy == Check::CheckEmpty) && - CheckStrings.empty()) { + CheckStrings.empty() && + std::none_of(DagNotMatches.begin(), DagNotMatches.end(), + [](FileCheckPattern DagNotMatch) { + return DagNotMatch.getCheckTy() == Check::CheckDAG; + })) { StringRef Type = CheckTy == Check::CheckNext ? "NEXT" : CheckTy == Check::CheckEmpty ? "EMPTY" : "SAME"; Index: llvm/test/FileCheck/check-dag.txt =================================================================== --- llvm/test/FileCheck/check-dag.txt +++ llvm/test/FileCheck/check-dag.txt @@ -1,4 +1,6 @@ -; RUN: FileCheck -input-file %s %s +; RUN: FileCheck -check-prefixes CHECK,STD -input-file %s %s +; RUN: FileCheck -check-prefixes CHECK,SAME -input-file %s %s +; RUN: FileCheck -check-prefixes CHECK,NEXT -input-file %s %s add r10, r1, r2 add r11, r3, r4 @@ -17,12 +19,16 @@ xor ; CHECK-DAG: add [[REG1:r[0-9]+]], r1, r2 -; CHECK-DAG: add [[REG2:r[0-9]+]], r3, r4 -; CHECK: mul r5, [[REG1]], [[REG2]] +; CHECK-DAG: add [[REG2:r[0-9]+]], r3, +; STD: mul r5, [[REG1]], [[REG2]] +; SAME-SAME: r4 +; NEXT-NEXT: mul r5, [[REG1]], [[REG2]] -; CHECK-DAG: mul [[REG1:r[0-9]+]], r1, r2 +; CHECK-DAG: mul [[REG1:r[0-9]+]], r1, ; CHECK-DAG: mul [[REG2:r[0-9]+]], r3, r4 -; CHECK: add r5, [[REG1]], [[REG2]] +; STD: add r5, [[REG1]], [[REG2]] +; SAME-SAME: r2 +; NEXT-NEXT: add r5, [[REG1]], [[REG2]] ; CHECK-DAG: add [[REG1:r[0-9]+]], r1, r2 ; CHECK-DAG: add [[REG2:r[0-9]+]], r3, r4