[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,