Merge "Only inline constructors if the receiver remains the this value."
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java b/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java
index 8ae2147..b698fc5 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java
@@ -50,7 +50,9 @@
 import com.android.tools.r8.ir.code.InvokeMethod;
 import com.android.tools.r8.ir.code.InvokeNewArray;
 import com.android.tools.r8.ir.code.InvokeVirtual;
+import com.android.tools.r8.ir.code.JumpInstruction;
 import com.android.tools.r8.ir.code.MemberType;
+import com.android.tools.r8.ir.code.Move;
 import com.android.tools.r8.ir.code.MoveType;
 import com.android.tools.r8.ir.code.NewArrayEmpty;
 import com.android.tools.r8.ir.code.NewArrayFilledData;
@@ -61,6 +63,7 @@
 import com.android.tools.r8.ir.code.StaticPut;
 import com.android.tools.r8.ir.code.Switch;
 import com.android.tools.r8.ir.code.Value;
+import com.android.tools.r8.ir.code.Xor;
 import com.android.tools.r8.ir.conversion.OptimizationFeedback;
 import com.android.tools.r8.ir.optimize.SwitchUtils.EnumSwitchInfo;
 import com.android.tools.r8.utils.InternalOptions;
@@ -1545,7 +1548,7 @@
         // First rewrite zero comparison.
         rewriteIfWithConstZero(block);
 
-        if (simplifyKnownBooleanCondition(dominator, block)) {
+        if (simplifyKnownBooleanCondition(code, dominator, block)) {
           continue;
         }
 
@@ -1608,8 +1611,19 @@
    *
    * which can be replaced by a fallthrough and the phi value can be replaced
    * with the boolean value itself.
+   *
+   * We also consider the forms:
+   *
+   *    ifeqz booleanValue       ifnez booleanValue
+   *      /        \              /        \
+   *      \        /              \        /
+   *      phi(1, 0)                phi(0, 1)
+   *
+   *  which can be replaced by a fallthrough and the phi value can be replaced
+   * by an xor instruction which is smaller.
    */
-  private boolean simplifyKnownBooleanCondition(DominatorTree dominator, BasicBlock block) {
+  private boolean simplifyKnownBooleanCondition(IRCode code, DominatorTree dominator,
+      BasicBlock block) {
     If theIf = block.exit().asIf();
     Value testValue = theIf.inValues().get(0);
     if (theIf.isZeroTest() && testValue.knownToBeBoolean()) {
@@ -1639,6 +1653,19 @@
                       falseNumber.isIntegerZero())) {
                 phi.replaceUsers(testValue);
                 deadPhis++;
+              } else if ((theIf.getType() == Type.NE &&
+                           trueNumber.isIntegerZero() &&
+                           falseNumber.isIntegerOne()) ||
+                         (theIf.getType() == Type.EQ &&
+                           trueNumber.isIntegerOne() &&
+                           falseNumber.isIntegerZero())) {
+                Value newOutValue = code.createValue(phi.outType(), phi.getLocalInfo());
+                phi.replaceUsers(newOutValue);
+                Instruction newInstruction = new Xor(NumericType.INT, newOutValue, testValue,
+                    trueNumber.isIntegerOne() ? trueValue : falseValue);
+                newInstruction.setBlock(phi.getBlock());
+                phi.getBlock().getInstructions().add(0, newInstruction);
+                deadPhis++;
               }
             }
           }
diff --git a/src/test/java/com/android/tools/r8/jasmin/Regress63598979.java b/src/test/java/com/android/tools/r8/jasmin/Regress63598979.java
new file mode 100644
index 0000000..091a43a
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/jasmin/Regress63598979.java
@@ -0,0 +1,120 @@
+// Copyright (c) 2017, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+package com.android.tools.r8.jasmin;
+
+import static org.junit.Assert.assertEquals;
+
+import com.google.common.collect.ImmutableList;
+import org.junit.Test;
+
+public class Regress63598979 extends JasminTestBase {
+
+  @Test
+  public void testSimplifyIf() throws Exception {
+    JasminBuilder builder = new JasminBuilder();
+    JasminBuilder.ClassBuilder clazz = builder.addClass("Test");
+
+    clazz.addStaticMethod("test1", ImmutableList.of("Z"), "Z",
+        ".limit stack 2",
+        ".limit locals 2",
+        "  iload 0",
+        "  ifne L2",
+        "L1:",
+        "  iconst_1",
+        "  goto L3",
+        "L2:",
+        "  iconst_0",
+        "L3:",
+        "  ireturn");
+
+    clazz.addStaticMethod("test2", ImmutableList.of("Z"), "Z",
+        ".limit stack 2",
+        ".limit locals 2",
+        "  iload 0",
+        "  ifne L2",
+        "L1:",
+        "  iconst_0",
+        "  goto L3",
+        "L2:",
+        "  iconst_1",
+        "L3:",
+        "  ireturn");
+
+    clazz.addStaticMethod("test3", ImmutableList.of("Z"), "Z",
+        ".limit stack 2",
+        ".limit locals 2",
+        "  iload 0",
+        "  ifeq L2",
+        "L1:",
+        "  iconst_0",
+        "  goto L3",
+        "L2:",
+        "  iconst_1",
+        "L3:",
+        "  ireturn");
+
+
+    clazz.addStaticMethod("test4", ImmutableList.of("Z"), "Z",
+        ".limit stack 2",
+        ".limit locals 2",
+        "  iload 0",
+        "  ifeq L2",
+        "L1:",
+        "  iconst_1",
+        "  goto L3",
+        "L2:",
+        "  iconst_0",
+        "L3:",
+        "  ireturn");
+
+    clazz.addMainMethod(
+        ".limit stack 2",
+        ".limit locals 1",
+        "  getstatic java/lang/System/out Ljava/io/PrintStream;",
+        "  iconst_0",
+        "  invokestatic Test/test1(Z)Z",
+        "  invokestatic java/lang/Boolean/toString(Z)Ljava/lang/String;",
+        "  invokevirtual java/io/PrintStream/print(Ljava/lang/String;)V",
+        "  getstatic java/lang/System/out Ljava/io/PrintStream;",
+        "  iconst_1",
+        "  invokestatic Test/test1(Z)Z",
+        "  invokestatic java/lang/Boolean/toString(Z)Ljava/lang/String;",
+        "  invokevirtual java/io/PrintStream/print(Ljava/lang/String;)V",
+        "  getstatic java/lang/System/out Ljava/io/PrintStream;",
+        "  iconst_0",
+        "  invokestatic Test/test2(Z)Z",
+        "  invokestatic java/lang/Boolean/toString(Z)Ljava/lang/String;",
+        "  invokevirtual java/io/PrintStream/print(Ljava/lang/String;)V",
+        "  getstatic java/lang/System/out Ljava/io/PrintStream;",
+        "  iconst_1",
+        "  invokestatic Test/test2(Z)Z",
+        "  invokestatic java/lang/Boolean/toString(Z)Ljava/lang/String;",
+        "  invokevirtual java/io/PrintStream/print(Ljava/lang/String;)V",
+        "  getstatic java/lang/System/out Ljava/io/PrintStream;",
+        "  iconst_0",
+        "  invokestatic Test/test3(Z)Z",
+        "  invokestatic java/lang/Boolean/toString(Z)Ljava/lang/String;",
+        "  invokevirtual java/io/PrintStream/print(Ljava/lang/String;)V",
+        "  getstatic java/lang/System/out Ljava/io/PrintStream;",
+        "  iconst_1",
+        "  invokestatic Test/test3(Z)Z",
+        "  invokestatic java/lang/Boolean/toString(Z)Ljava/lang/String;",
+        "  invokevirtual java/io/PrintStream/print(Ljava/lang/String;)V",
+        "  getstatic java/lang/System/out Ljava/io/PrintStream;",
+        "  iconst_0",
+        "  invokestatic Test/test4(Z)Z",
+        "  invokestatic java/lang/Boolean/toString(Z)Ljava/lang/String;",
+        "  invokevirtual java/io/PrintStream/print(Ljava/lang/String;)V",
+        "  getstatic java/lang/System/out Ljava/io/PrintStream;",
+        "  iconst_1",
+        "  invokestatic Test/test4(Z)Z",
+        "  invokestatic java/lang/Boolean/toString(Z)Ljava/lang/String;",
+        "  invokevirtual java/io/PrintStream/print(Ljava/lang/String;)V",
+        "  return");
+
+    String expected = runOnJava(builder, clazz.name);
+    String artResult = runOnArtD8(builder, clazz.name);
+    assertEquals(expected, artResult);
+  }
+}
diff --git a/tools/notify.py b/tools/notify.py
new file mode 100644
index 0000000..f7ae50e
--- /dev/null
+++ b/tools/notify.py
@@ -0,0 +1,19 @@
+#!/usr/bin/env python
+# Copyright (c) 2017, the R8 project authors. Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE file.
+
+try:
+  import gi
+  from gi.repository import Notify
+  Notify.init("R8 build tools")
+
+  def notify(message):
+    try:
+      Notify.Notification.new("R8 build tools", message).show()
+    except:
+      return
+
+except ImportError:
+  def notify(message):
+    return
diff --git a/tools/test.py b/tools/test.py
index ab4b0d6..c0a1e02 100755
--- a/tools/test.py
+++ b/tools/test.py
@@ -14,6 +14,7 @@
 import sys
 import utils
 import uuid
+import notify
 
 ALL_ART_VMS = ["default", "7.0.0", "6.0.1", "5.1.1"]
 BUCKET = 'r8-test-results'
@@ -149,4 +150,9 @@
       return return_code
 
 if __name__ == '__main__':
-  sys.exit(Main())
+  return_code = Main()
+  if return_code != 0:
+    notify.notify("Tests failed.")
+  else:
+    notify.notify("Tests passed.")
+  sys.exit(return_code)