ART: Invoke Checker from run-test scripts

This patch moves Checker-based tests of the optimizing compiler into
the art/test directory and modifies the run-test scripts to dump
the CFG during compilation and to verify the graph using Checker as
part of the "running" stage. Outputs generated by running the test
and running Checker are concatenated and compared with expected.txt.

Checker is invoked only if the test's name name matches the format
"<number>-checker-*" and it's currently enabled only for optimizing +
host configs. The tests are still invoked on other configs but
without Checker.

Change-Id: Ib24da808cd4bca66f07e0dbeb913a418065f2859
diff --git a/test/441-checker-inliner/expected.txt b/test/441-checker-inliner/expected.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/441-checker-inliner/expected.txt
diff --git a/test/441-checker-inliner/info.txt b/test/441-checker-inliner/info.txt
new file mode 100644
index 0000000..66a3270
--- /dev/null
+++ b/test/441-checker-inliner/info.txt
@@ -0,0 +1 @@
+Tests inlining in the optimizing compiler.
diff --git a/compiler/optimizing/test/Inliner.java b/test/441-checker-inliner/src/Main.java
similarity index 72%
rename from compiler/optimizing/test/Inliner.java
rename to test/441-checker-inliner/src/Main.java
index 54cce62..631b140 100644
--- a/compiler/optimizing/test/Inliner.java
+++ b/test/441-checker-inliner/src/Main.java
@@ -14,14 +14,14 @@
 * limitations under the License.
 */
 
-public class Inliner {
+public class Main {
 
-  // CHECK-START: void Inliner.InlineVoid() inliner (before)
+  // CHECK-START: void Main.InlineVoid() inliner (before)
   // CHECK-DAG:     [[Const42:i\d+]] IntConstant 42
   // CHECK-DAG:                      InvokeStaticOrDirect
   // CHECK-DAG:                      InvokeStaticOrDirect [ [[Const42]] ]
 
-  // CHECK-START: void Inliner.InlineVoid() inliner (after)
+  // CHECK-START: void Main.InlineVoid() inliner (after)
   // CHECK-NOT:                      InvokeStaticOrDirect
 
   public static void InlineVoid() {
@@ -29,12 +29,12 @@
     returnVoidWithOneParameter(42);
   }
 
-  // CHECK-START: int Inliner.InlineParameter(int) inliner (before)
+  // CHECK-START: int Main.InlineParameter(int) inliner (before)
   // CHECK-DAG:     [[Param:i\d+]]  ParameterValue
   // CHECK-DAG:     [[Result:i\d+]] InvokeStaticOrDirect [ [[Param]] ]
   // CHECK-DAG:                     Return [ [[Result]] ]
 
-  // CHECK-START: int Inliner.InlineParameter(int) inliner (after)
+  // CHECK-START: int Main.InlineParameter(int) inliner (after)
   // CHECK-DAG:     [[Param:i\d+]]  ParameterValue
   // CHECK-DAG:                     Return [ [[Param]] ]
 
@@ -42,12 +42,12 @@
     return returnParameter(a);
   }
 
-  // CHECK-START: long Inliner.InlineWideParameter(long) inliner (before)
+  // CHECK-START: long Main.InlineWideParameter(long) inliner (before)
   // CHECK-DAG:     [[Param:j\d+]]  ParameterValue
   // CHECK-DAG:     [[Result:j\d+]] InvokeStaticOrDirect [ [[Param]] ]
   // CHECK-DAG:                     Return [ [[Result]] ]
 
-  // CHECK-START: long Inliner.InlineWideParameter(long) inliner (after)
+  // CHECK-START: long Main.InlineWideParameter(long) inliner (after)
   // CHECK-DAG:     [[Param:j\d+]]  ParameterValue
   // CHECK-DAG:                     Return [ [[Param]] ]
 
@@ -55,12 +55,12 @@
     return returnWideParameter(a);
   }
 
-  // CHECK-START: java.lang.Object Inliner.InlineReferenceParameter(java.lang.Object) inliner (before)
+  // CHECK-START: java.lang.Object Main.InlineReferenceParameter(java.lang.Object) inliner (before)
   // CHECK-DAG:     [[Param:l\d+]]  ParameterValue
   // CHECK-DAG:     [[Result:l\d+]] InvokeStaticOrDirect [ [[Param]] ]
   // CHECK-DAG:                     Return [ [[Result]] ]
 
-  // CHECK-START: java.lang.Object Inliner.InlineReferenceParameter(java.lang.Object) inliner (after)
+  // CHECK-START: java.lang.Object Main.InlineReferenceParameter(java.lang.Object) inliner (after)
   // CHECK-DAG:     [[Param:l\d+]]  ParameterValue
   // CHECK-DAG:                     Return [ [[Param]] ]
 
@@ -68,11 +68,11 @@
     return returnReferenceParameter(o);
   }
 
-  // CHECK-START: int Inliner.InlineInt() inliner (before)
+  // CHECK-START: int Main.InlineInt() inliner (before)
   // CHECK-DAG:     [[Result:i\d+]] InvokeStaticOrDirect
   // CHECK-DAG:                     Return [ [[Result]] ]
 
-  // CHECK-START: int Inliner.InlineInt() inliner (after)
+  // CHECK-START: int Main.InlineInt() inliner (after)
   // CHECK-DAG:     [[Const4:i\d+]] IntConstant 4
   // CHECK-DAG:                     Return [ [[Const4]] ]
 
@@ -80,11 +80,11 @@
     return returnInt();
   }
 
-  // CHECK-START: long Inliner.InlineWide() inliner (before)
+  // CHECK-START: long Main.InlineWide() inliner (before)
   // CHECK-DAG:     [[Result:j\d+]] InvokeStaticOrDirect
   // CHECK-DAG:                     Return [ [[Result]] ]
 
-  // CHECK-START: long Inliner.InlineWide() inliner (after)
+  // CHECK-START: long Main.InlineWide() inliner (after)
   // CHECK-DAG:     [[Const8:j\d+]] LongConstant 8
   // CHECK-DAG:                     Return [ [[Const8]] ]
 
@@ -92,13 +92,13 @@
     return returnWide();
   }
 
-  // CHECK-START: int Inliner.InlineAdd() inliner (before)
+  // CHECK-START: int Main.InlineAdd() inliner (before)
   // CHECK-DAG:     [[Const3:i\d+]] IntConstant 3
   // CHECK-DAG:     [[Const5:i\d+]] IntConstant 5
   // CHECK-DAG:     [[Result:i\d+]] InvokeStaticOrDirect
   // CHECK-DAG:                     Return [ [[Result]] ]
 
-  // CHECK-START: int Inliner.InlineAdd() inliner (after)
+  // CHECK-START: int Main.InlineAdd() inliner (after)
   // CHECK-DAG:     [[Const3:i\d+]] IntConstant 3
   // CHECK-DAG:     [[Const5:i\d+]] IntConstant 5
   // CHECK-DAG:     [[Add:i\d+]]    Add [ [[Const3]] [[Const5]] ]
@@ -108,25 +108,25 @@
     return returnAdd(3, 5);
   }
 
-  // CHECK-START: int Inliner.InlineFieldAccess() inliner (before)
+  // CHECK-START: int Main.InlineFieldAccess() inliner (before)
   // CHECK-DAG:     [[After:i\d+]]  InvokeStaticOrDirect
   // CHECK-DAG:                     Return [ [[After]] ]
 
-  // CHECK-START: int Inliner.InlineFieldAccess() inliner (after)
+  // CHECK-START: int Main.InlineFieldAccess() inliner (after)
   // CHECK-DAG:     [[Const1:i\d+]] IntConstant 1
   // CHECK-DAG:     [[Before:i\d+]] StaticFieldGet
   // CHECK-DAG:     [[After:i\d+]]  Add [ [[Before]] [[Const1]] ]
   // CHECK-DAG:                     StaticFieldSet [ {{l\d+}} [[After]] ]
   // CHECK-DAG:                     Return [ [[After]] ]
 
-  // CHECK-START: int Inliner.InlineFieldAccess() inliner (after)
+  // CHECK-START: int Main.InlineFieldAccess() inliner (after)
   // CHECK-NOT:                     InvokeStaticOrDirect
 
   public static int InlineFieldAccess() {
     return incCounter();
   }
 
-  // CHECK-START: int Inliner.InlineWithControlFlow(boolean) inliner (before)
+  // CHECK-START: int Main.InlineWithControlFlow(boolean) inliner (before)
   // CHECK-DAG:     [[Const1:i\d+]] IntConstant 1
   // CHECK-DAG:     [[Const3:i\d+]] IntConstant 3
   // CHECK-DAG:     [[Const5:i\d+]] IntConstant 5
@@ -135,7 +135,7 @@
   // CHECK-DAG:     [[Phi:i\d+]]    Phi [ [[Add]] [[Sub]] ]
   // CHECK-DAG:                     Return [ [[Phi]] ]
 
-  // CHECK-START: int Inliner.InlineWithControlFlow(boolean) inliner (after)
+  // CHECK-START: int Main.InlineWithControlFlow(boolean) inliner (after)
   // CHECK-DAG:     [[Const1:i\d+]] IntConstant 1
   // CHECK-DAG:     [[Const3:i\d+]] IntConstant 3
   // CHECK-DAG:     [[Const5:i\d+]] IntConstant 5
@@ -199,4 +199,44 @@
   private static int incCounter() {
     return ++counter;
   }
+
+  public static void main(String[] args) {
+    InlineVoid();
+
+    if (InlineInt() != 4) {
+      throw new Error();
+    }
+
+    if (InlineWide() != 8L) {
+      throw new Error();
+    }
+
+    if (InlineParameter(42) != 42) {
+      throw new Error();
+    }
+
+    if (InlineWideParameter(0x100000001L) != 0x100000001L) {
+      throw new Error();
+    }
+
+    if (InlineReferenceParameter(Main.class) != Main.class) {
+      throw new Error();
+    }
+
+    if (InlineAdd() != 8) {
+      throw new Error();
+    }
+
+    if (InlineFieldAccess() != 43 || InlineFieldAccess() != 44) {
+      throw new Error();
+    }
+
+    if (InlineWithControlFlow(true) != 4) {
+      throw new Error();
+    }
+
+    if (InlineWithControlFlow(false) != 2) {
+      throw new Error();
+    }
+  }
 }
diff --git a/test/442-checker-constant-folding/expected.txt b/test/442-checker-constant-folding/expected.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/442-checker-constant-folding/expected.txt
diff --git a/test/442-checker-constant-folding/info.txt b/test/442-checker-constant-folding/info.txt
new file mode 100644
index 0000000..5073972
--- /dev/null
+++ b/test/442-checker-constant-folding/info.txt
@@ -0,0 +1 @@
+Tests constant folding in the optimizing compiler.
diff --git a/compiler/optimizing/test/ConstantFolding.java b/test/442-checker-constant-folding/src/Main.java
similarity index 68%
rename from compiler/optimizing/test/ConstantFolding.java
rename to test/442-checker-constant-folding/src/Main.java
index d08006b..de2c5c7 100644
--- a/compiler/optimizing/test/ConstantFolding.java
+++ b/test/442-checker-constant-folding/src/Main.java
@@ -14,19 +14,19 @@
 * limitations under the License.
 */
 
-public class ConstantFolding {
+public class Main {
 
   /**
    * Tiny three-register program exercising int constant folding
    * on negation.
    */
 
-  // CHECK-START: int ConstantFolding.IntNegation() constant_folding (before)
+  // CHECK-START: int Main.IntNegation() constant_folding (before)
   // CHECK-DAG:     [[Const42:i\d+]]  IntConstant 42
   // CHECK-DAG:     [[Neg:i\d+]]      Neg [ [[Const42]] ]
   // CHECK-DAG:                       Return [ [[Neg]] ]
 
-  // CHECK-START: int ConstantFolding.IntNegation() constant_folding (after)
+  // CHECK-START: int Main.IntNegation() constant_folding (after)
   // CHECK-DAG:     [[ConstN42:i\d+]] IntConstant -42
   // CHECK-DAG:                       Return [ [[ConstN42]] ]
 
@@ -42,13 +42,13 @@
    * on addition.
    */
 
-  // CHECK-START: int ConstantFolding.IntAddition1() constant_folding (before)
+  // CHECK-START: int Main.IntAddition1() constant_folding (before)
   // CHECK-DAG:     [[Const1:i\d+]]  IntConstant 1
   // CHECK-DAG:     [[Const2:i\d+]]  IntConstant 2
   // CHECK-DAG:     [[Add:i\d+]]     Add [ [[Const1]] [[Const2]] ]
   // CHECK-DAG:                      Return [ [[Add]] ]
 
-  // CHECK-START: int ConstantFolding.IntAddition1() constant_folding (after)
+  // CHECK-START: int Main.IntAddition1() constant_folding (after)
   // CHECK-DAG:     [[Const3:i\d+]]  IntConstant 3
   // CHECK-DAG:                      Return [ [[Const3]] ]
 
@@ -65,7 +65,7 @@
   * on addition.
   */
 
-  // CHECK-START: int ConstantFolding.IntAddition2() constant_folding (before)
+  // CHECK-START: int Main.IntAddition2() constant_folding (before)
   // CHECK-DAG:     [[Const1:i\d+]]  IntConstant 1
   // CHECK-DAG:     [[Const2:i\d+]]  IntConstant 2
   // CHECK-DAG:     [[Const5:i\d+]]  IntConstant 5
@@ -75,7 +75,7 @@
   // CHECK-DAG:     [[Add3:i\d+]]    Add [ [[Add1]] [[Add2]] ]
   // CHECK-DAG:                      Return [ [[Add3]] ]
 
-  // CHECK-START: int ConstantFolding.IntAddition2() constant_folding (after)
+  // CHECK-START: int Main.IntAddition2() constant_folding (after)
   // CHECK-DAG:     [[Const14:i\d+]] IntConstant 14
   // CHECK-DAG:                      Return [ [[Const14]] ]
 
@@ -96,19 +96,19 @@
    * on subtraction.
    */
 
-  // CHECK-START: int ConstantFolding.IntSubtraction() constant_folding (before)
-  // CHECK-DAG:     [[Const5:i\d+]]  IntConstant 5
+  // CHECK-START: int Main.IntSubtraction() constant_folding (before)
+  // CHECK-DAG:     [[Const6:i\d+]]  IntConstant 6
   // CHECK-DAG:     [[Const2:i\d+]]  IntConstant 2
-  // CHECK-DAG:     [[Sub:i\d+]]     Sub [ [[Const5]] [[Const2]] ]
+  // CHECK-DAG:     [[Sub:i\d+]]     Sub [ [[Const6]] [[Const2]] ]
   // CHECK-DAG:                      Return [ [[Sub]] ]
 
-  // CHECK-START: int ConstantFolding.IntSubtraction() constant_folding (after)
-  // CHECK-DAG:     [[Const3:i\d+]]  IntConstant 3
-  // CHECK-DAG:                      Return [ [[Const3]] ]
+  // CHECK-START: int Main.IntSubtraction() constant_folding (after)
+  // CHECK-DAG:     [[Const4:i\d+]]  IntConstant 4
+  // CHECK-DAG:                      Return [ [[Const4]] ]
 
   public static int IntSubtraction() {
     int a, b, c;
-    a = 5;
+    a = 6;
     b = 2;
     c = a - b;
     return c;
@@ -119,13 +119,13 @@
    * on addition.
    */
 
-  // CHECK-START: long ConstantFolding.LongAddition() constant_folding (before)
+  // CHECK-START: long Main.LongAddition() constant_folding (before)
   // CHECK-DAG:     [[Const1:j\d+]]  LongConstant 1
   // CHECK-DAG:     [[Const2:j\d+]]  LongConstant 2
   // CHECK-DAG:     [[Add:j\d+]]     Add [ [[Const1]] [[Const2]] ]
   // CHECK-DAG:                      Return [ [[Add]] ]
 
-  // CHECK-START: long ConstantFolding.LongAddition() constant_folding (after)
+  // CHECK-START: long Main.LongAddition() constant_folding (after)
   // CHECK-DAG:     [[Const3:j\d+]]  LongConstant 3
   // CHECK-DAG:                      Return [ [[Const3]] ]
 
@@ -142,19 +142,19 @@
    * on subtraction.
    */
 
-  // CHECK-START: long ConstantFolding.LongSubtraction() constant_folding (before)
-  // CHECK-DAG:     [[Const5:j\d+]]  LongConstant 5
+  // CHECK-START: long Main.LongSubtraction() constant_folding (before)
+  // CHECK-DAG:     [[Const6:j\d+]]  LongConstant 6
   // CHECK-DAG:     [[Const2:j\d+]]  LongConstant 2
-  // CHECK-DAG:     [[Sub:j\d+]]     Sub [ [[Const5]] [[Const2]] ]
+  // CHECK-DAG:     [[Sub:j\d+]]     Sub [ [[Const6]] [[Const2]] ]
   // CHECK-DAG:                      Return [ [[Sub]] ]
 
-  // CHECK-START: long ConstantFolding.LongSubtraction() constant_folding (after)
-  // CHECK-DAG:     [[Const3:j\d+]]  LongConstant 3
-  // CHECK-DAG:                      Return [ [[Const3]] ]
+  // CHECK-START: long Main.LongSubtraction() constant_folding (after)
+  // CHECK-DAG:     [[Const4:j\d+]]  LongConstant 4
+  // CHECK-DAG:                      Return [ [[Const4]] ]
 
   public static long LongSubtraction() {
     long a, b, c;
-    a = 5L;
+    a = 6L;
     b = 2L;
     c = a - b;
     return c;
@@ -164,19 +164,19 @@
    * Three-register program with a constant (static) condition.
    */
 
-  // CHECK-START: int ConstantFolding.StaticCondition() constant_folding (before)
-  // CHECK-DAG:     [[Const5:i\d+]]  IntConstant 5
+  // CHECK-START: int Main.StaticCondition() constant_folding (before)
+  // CHECK-DAG:     [[Const7:i\d+]]  IntConstant 7
   // CHECK-DAG:     [[Const2:i\d+]]  IntConstant 2
-  // CHECK-DAG:     [[Cond:z\d+]]    GreaterThanOrEqual [ [[Const5]] [[Const2]] ]
+  // CHECK-DAG:     [[Cond:z\d+]]    GreaterThanOrEqual [ [[Const7]] [[Const2]] ]
   // CHECK-DAG:                      If [ [[Cond]] ]
 
-  // CHECK-START: int ConstantFolding.StaticCondition() constant_folding (after)
+  // CHECK-START: int Main.StaticCondition() constant_folding (after)
   // CHECK-DAG:     [[Const1:i\d+]]  IntConstant 1
   // CHECK-DAG:                      If [ [[Const1]] ]
 
   public static int StaticCondition() {
     int a, b, c;
-    a = 5;
+    a = 7;
     b = 2;
     if (a < b)
       c = a + b;
@@ -194,7 +194,7 @@
    * (forward) post-order traversal of the the dominator tree.
    */
 
-  // CHECK-START: int ConstantFolding.JumpsAndConditionals(boolean) constant_folding (before)
+  // CHECK-START: int Main.JumpsAndConditionals(boolean) constant_folding (before)
   // CHECK-DAG:     [[Const2:i\d+]]  IntConstant 2
   // CHECK-DAG:     [[Const5:i\d+]]  IntConstant 5
   // CHECK-DAG:     [[Add:i\d+]]     Add [ [[Const5]] [[Const2]] ]
@@ -202,7 +202,7 @@
   // CHECK-DAG:     [[Phi:i\d+]]     Phi [ [[Add]] [[Sub]] ]
   // CHECK-DAG:                      Return [ [[Phi]] ]
 
-  // CHECK-START: int ConstantFolding.JumpsAndConditionals(boolean) constant_folding (after)
+  // CHECK-START: int Main.JumpsAndConditionals(boolean) constant_folding (after)
   // CHECK-DAG:     [[Const3:i\d+]]  IntConstant 3
   // CHECK-DAG:     [[Const7:i\d+]]  IntConstant 7
   // CHECK-DAG:     [[Phi:i\d+]]     Phi [ [[Const7]] [[Const3]] ]
@@ -218,4 +218,42 @@
       c = a - b;
     return c;
   }
+
+  public static void main(String[] args) {
+    if (IntNegation() != -42) {
+      throw new Error();
+    }
+
+    if (IntAddition1() != 3) {
+      throw new Error();
+    }
+
+    if (IntAddition2() != 14) {
+      throw new Error();
+    }
+
+    if (IntSubtraction() != 4) {
+      throw new Error();
+    }
+
+    if (LongAddition() != 3L) {
+      throw new Error();
+    }
+
+    if (LongSubtraction() != 4L) {
+      throw new Error();
+    }
+
+    if (StaticCondition() != 5) {
+      throw new Error();
+    }
+
+    if (JumpsAndConditionals(true) != 7) {
+      throw new Error();
+    }
+
+    if (JumpsAndConditionals(false) != 3) {
+      throw new Error();
+    }
+  }
 }
diff --git a/test/Android.run-test.mk b/test/Android.run-test.mk
index 04c590e..bd9941d 100644
--- a/test/Android.run-test.mk
+++ b/test/Android.run-test.mk
@@ -303,6 +303,20 @@
 
 TEST_ART_BROKEN_DEFAULT_RUN_TESTS :=
 
+# Tests known to be broken for the optimizing compiler on 32-bit targets due to
+# inability to allocate registers for methods with long values.
+TEST_ART_BROKEN_OPTIMIZING_32_RUN_TESTS := \
+  441-checker-inliner \
+  442-checker-constant-folding \
+
+ifneq (,$(filter optimizing,$(COMPILER_TYPES)))
+  ART_TEST_KNOWN_BROKEN += $(call all-run-test-names,$(TARGET_TYPES),$(RUN_TYPES),$(PREBUILD_TYPES), \
+      optimizing,$(RELOCATE_TYPES),$(TRACE_TYPES),$(GC_TYPES),$(JNI_TYPES), \
+      $(IMAGE_TYPES),$(PICTEST_TYPES),$(TEST_ART_BROKEN_OPTIMIZING_32_RUN_TESTS),32)
+endif
+
+TEST_ART_BROKEN_OPTIMIZING_32_RUN_TESTS :=
+
 # Known broken tests for the arm64 optimizing compiler backend.
 TEST_ART_BROKEN_OPTIMIZING_ARM64_RUN_TESTS :=
 
diff --git a/test/etc/default-build b/test/etc/default-build
index 6731ad3..58c9564 100755
--- a/test/etc/default-build
+++ b/test/etc/default-build
@@ -17,6 +17,22 @@
 # Stop if something fails.
 set -e
 
+DX_FLAGS=""
+
+while true; do
+  if [ "x$1" = "x--dx-option" ]; then
+    shift
+    option="$1"
+    DX_FLAGS="${DX_FLAGS} $option"
+    shift
+  elif expr "x$1" : "x--" >/dev/null 2>&1; then
+    echo "unknown $0 option: $1" 1>&2
+    exit 1
+  else
+    break
+  fi
+done
+
 if [ -e classes.dex ]; then
   zip $TEST_NAME.jar classes.dex
   exit 0
@@ -30,7 +46,8 @@
 fi
 
 if [ ${NEED_DEX} = "true" ]; then
-  ${DX} -JXmx256m --debug --dex --dump-to=classes.lst --output=classes.dex --dump-width=1000 classes
+  ${DX} -JXmx256m --debug --dex --dump-to=classes.lst --output=classes.dex \
+    --dump-width=1000 ${DX_FLAGS} classes
 fi
 
 if [ -d smali ]; then
@@ -43,7 +60,8 @@
   mkdir classes-ex
   ${JAVAC} -d classes-ex -cp classes `find src-ex -name '*.java'`
   if [ ${NEED_DEX} = "true" ]; then
-    ${DX} -JXmx256m --debug --dex --dump-to=classes-ex.lst --output=classes-ex.dex --dump-width=1000 classes-ex
+    ${DX} -JXmx256m --debug --dex --dump-to=classes-ex.lst --output=classes-ex.dex \
+      --dump-width=1000 ${DX_FLAGS} classes-ex
 
     # quick shuffle so that the stored name is "classes.dex"
     mv classes.dex classes-1.dex
diff --git a/test/run-test b/test/run-test
index 2802b75..8ef3e3e 100755
--- a/test/run-test
+++ b/test/run-test
@@ -39,6 +39,7 @@
 else
   tmp_dir="${TMPDIR}/$USER/${test_dir}"
 fi
+checker="${progdir}/../tools/checker.py"
 
 export JAVA="java"
 export JAVAC="javac -g"
@@ -74,8 +75,10 @@
 check_cmd="check"
 output="output.txt"
 build_output="build-output.txt"
+cfg_output="cfg-output.txt"
 lib="libartd.so"
 run_args="--quiet"
+build_args=""
 
 prebuild_mode="yes"
 target_mode="yes"
@@ -503,6 +506,21 @@
 
 export TEST_NAME=`basename ${test_dir}`
 
+# Tests named '<number>-checker-*' will also have their CFGs verified with
+# Checker when compiled with Optimizing on host.
+if [[ "$TEST_NAME" =~ ^[0-9]+-checker- ]]; then
+  # Build Checker DEX files without dx's optimizations so the input to dex2oat
+  # better resembles the Java source. We always build the DEX the same way, even
+  # if Checker is not invoked and the test only runs the program.
+  build_args="${build_args} --dx-option --no-optimize"
+
+  if [ "$runtime" = "art" -a "$image_suffix" = "-optimizing" -a "$target_mode" = "no" ]; then
+    run_checker="yes"
+    run_args="${run_args} -Xcompiler-option --dump-cfg=$tmp_dir/$cfg_output \
+                          -Xcompiler-option -j1"
+  fi
+fi
+
 # To cause tests to fail fast, limit the file sizes created by dx, dex2oat and ART output to 2MB.
 file_size_limit=2048
 if echo "$test_dir" | grep 089; then
@@ -518,7 +536,7 @@
 good_build="yes"
 good_run="yes"
 if [ "$dev_mode" = "yes" ]; then
-    "./${build}" 2>&1
+    "./${build}" $build_args 2>&1
     build_exit="$?"
     echo "build exit status: $build_exit" 1>&2
     if [ "$build_exit" = '0' ]; then
@@ -531,11 +549,14 @@
         fi
     fi
 elif [ "$update_mode" = "yes" ]; then
-    "./${build}" >"$build_output" 2>&1
+    "./${build}" $build_args >"$build_output" 2>&1
     build_exit="$?"
     if [ "$build_exit" = '0' ]; then
         echo "${test_dir}: running..." 1>&2
         "./${run}" $run_args "$@" >"$output" 2>&1
+        if [ "$run_checker" = "yes" ]; then
+          "$checker" -q "$cfg_output" "$tmp_dir" >> "$output" 2>&1
+        fi
         sed -e 's/[[:cntrl:]]$//g' < "$output" >"${td_expected}"
         good="yes"
     else
@@ -544,7 +565,7 @@
     fi
 elif [ "$build_only" = "yes" ]; then
     good="yes"
-    "./${build}" >"$build_output" 2>&1
+    "./${build}" $build_args >"$build_output" 2>&1
     build_exit="$?"
     if [ "$build_exit" '!=' '0' ]; then
         cp "$build_output" "$output"
@@ -559,7 +580,7 @@
     find $tmp_dir -mindepth 1  ! -regex ".*/\(.*jar\|$output\|$expected\)" | xargs rm -rf
     exit 0
 else
-    "./${build}" >"$build_output" 2>&1
+    "./${build}" $build_args >"$build_output" 2>&1
     build_exit="$?"
     if [ "$build_exit" = '0' ]; then
         echo "${test_dir}: running..." 1>&2
@@ -568,6 +589,15 @@
         if [ "$run_exit" != "0" ]; then
             echo "run exit status: $run_exit" 1>&2
             good_run="no"
+        elif [ "$run_checker" = "yes" ]; then
+            "$checker" -q "$cfg_output" "$tmp_dir" >> "$output" 2>&1
+            checker_exit="$?"
+            if [ "$checker_exit" != "0" ]; then
+                echo "checker exit status: $checker_exit" 1>&2
+                good_run="no"
+            else
+                good_run="yes"
+            fi
         else
             good_run="yes"
         fi