[vm, compiler] Predicate boolean loads.

TEST=ci
Bug: https://github.com/dart-lang/sdk/issues/29908
Change-Id: I5a5c57a8a79dbe4f2ee5303a4b9436bd36e8d7be
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/189921
Commit-Queue: Ryan Macnak <rmacnak@google.com>
Reviewed-by: Alexander Markov <alexmarkov@google.com>
diff --git a/runtime/vm/compiler/backend/il_arm64.cc b/runtime/vm/compiler/backend/il_arm64.cc
index 6b18881..ce2a0a9 100644
--- a/runtime/vm/compiler/backend/il_arm64.cc
+++ b/runtime/vm/compiler/backend/il_arm64.cc
@@ -6912,19 +6912,27 @@
   compiler::Label is_true, is_false;
   BranchLabels labels = {&is_true, &is_false, &is_false};
   Condition true_condition = EmitComparisonCode(compiler, labels);
-  const Register result = this->locs()->out(0).reg();
 
-  // TODO(dartbug.com/29908): Use csel here for better branch prediction?
-  if (true_condition != kInvalidCondition) {
-    EmitBranchOnCondition(compiler, true_condition, labels);
+  const Register result = this->locs()->out(0).reg();
+  if (is_true.IsLinked() || is_false.IsLinked()) {
+    if (true_condition != kInvalidCondition) {
+      EmitBranchOnCondition(compiler, true_condition, labels);
+    }
+    compiler::Label done;
+    __ Bind(&is_false);
+    __ LoadObject(result, Bool::False());
+    __ b(&done);
+    __ Bind(&is_true);
+    __ LoadObject(result, Bool::True());
+    __ Bind(&done);
+  } else {
+    // If EmitComparisonCode did not use the labels and just returned
+    // a condition we can avoid the branch and use conditional loads.
+    ASSERT(true_condition != kInvalidCondition);
+    __ LoadObject(TMP, Bool::True());
+    __ LoadObject(TMP2, Bool::False());
+    __ csel(result, TMP, TMP2, true_condition);
   }
-  compiler::Label done;
-  __ Bind(&is_false);
-  __ LoadObject(result, Bool::False());
-  __ b(&done);
-  __ Bind(&is_true);
-  __ LoadObject(result, Bool::True());
-  __ Bind(&done);
 }
 
 void ComparisonInstr::EmitBranchCode(FlowGraphCompiler* compiler,
diff --git a/runtime/vm/compiler/backend/il_x64.cc b/runtime/vm/compiler/backend/il_x64.cc
index 5d55d70..379ba84 100644
--- a/runtime/vm/compiler/backend/il_x64.cc
+++ b/runtime/vm/compiler/backend/il_x64.cc
@@ -931,17 +931,31 @@
   compiler::Label is_true, is_false;
   BranchLabels labels = {&is_true, &is_false, &is_false};
   Condition true_condition = EmitComparisonCode(compiler, labels);
-  if (true_condition != kInvalidCondition) {
-    EmitBranchOnCondition(compiler, true_condition, labels);
-  }
+
   Register result = locs()->out(0).reg();
-  compiler::Label done;
-  __ Bind(&is_false);
-  __ LoadObject(result, Bool::False());
-  __ jmp(&done);
-  __ Bind(&is_true);
-  __ LoadObject(result, Bool::True());
-  __ Bind(&done);
+  if (is_true.IsLinked() || is_false.IsLinked()) {
+    if (true_condition != kInvalidCondition) {
+      EmitBranchOnCondition(compiler, true_condition, labels);
+    }
+    compiler::Label done;
+    __ Bind(&is_false);
+    __ LoadObject(result, Bool::False());
+    __ jmp(&done, compiler::Assembler::kNearJump);
+    __ Bind(&is_true);
+    __ LoadObject(result, Bool::True());
+    __ Bind(&done);
+  } else {
+    // If EmitComparisonCode did not use the labels and just returned
+    // a condition we can avoid the branch and use conditional loads.
+    ASSERT(true_condition != kInvalidCondition);
+    __ setcc(InvertCondition(true_condition), ByteRegisterOf(result));
+    __ movzxb(result, result);
+    __ movq(result,
+            compiler::Address(THR, result, TIMES_8,
+                              compiler::target::Thread::bool_true_offset()));
+    ASSERT(compiler::target::Thread::bool_true_offset() + 8 ==
+           compiler::target::Thread::bool_false_offset());
+  }
 }
 
 void ComparisonInstr::EmitBranchCode(FlowGraphCompiler* compiler,