Support GenSelect for x86
kMirOpSelect is an extended MIR that has been generated in order
to remove trivial diamond shapes where the conditional is an
if-eqz or if-nez and on each of the paths there is a move or
const bytecode with same destination register.
This patch enables x86 to generate code for this extended MIR.
A) Handling the constant specialization of kMirOpSelect:
1) When the true case is zero and result_reg is not same as src_reg:
xor result_reg, result_reg
cmp $0, src_reg
mov t1, $false_case
cmovnz result_reg, t1
2) When the false case is zero and result_reg is not same as src_reg:
xor result_reg, result_reg
cmp $0, src_reg
mov t1, $true_case
cmovz result_reg, t1
3) All other cases (we do compare first to set eflags):
cmp $0, src_reg
mov result_reg, $true_case
mov t1, $false_case
cmovnz result_reg, t1
B) Handling the move specialization of kMirOpSelect:
1) When true case is already in place:
cmp $0, src_reg
cmovnz result_reg, false_reg
2) When false case is already in place:
cmp $0, src_reg
cmovz result_reg, true_reg
3) When neither cases are in place:
cmp $0, src_reg
mov result_reg, true_reg
cmovnz result_reg, false_reg
Change-Id: Ic7c50823208fe82019916476a0a77c6a271679fe
Signed-off-by: Razvan A Lupusoru <razvan.a.lupusoru@intel.com>
diff --git a/compiler/dex/mir_optimization.cc b/compiler/dex/mir_optimization.cc
index 5c41520..0d53d4c 100644
--- a/compiler/dex/mir_optimization.cc
+++ b/compiler/dex/mir_optimization.cc
@@ -323,9 +323,10 @@
break;
}
// Is this the select pattern?
- // TODO: flesh out support for Mips and X86. NOTE: llvm's select op doesn't quite work here.
+ // TODO: flesh out support for Mips. NOTE: llvm's select op doesn't quite work here.
// TUNING: expand to support IF_xx compare & branches
- if (!(cu_->compiler_backend == kPortable) && (cu_->instruction_set == kThumb2) &&
+ if ((cu_->compiler_backend != kPortable) &&
+ (cu_->instruction_set == kThumb2 || cu_->instruction_set == kX86) &&
((mir->dalvikInsn.opcode == Instruction::IF_EQZ) ||
(mir->dalvikInsn.opcode == Instruction::IF_NEZ))) {
BasicBlock* ft = GetBasicBlock(bb->fall_through);
@@ -391,6 +392,11 @@
}
}
if (const_form) {
+ /*
+ * TODO: If both constants are the same value, then instead of generating
+ * a select, we should simply generate a const bytecode. This should be
+ * considered after inlining which can lead to CFG of this form.
+ */
// "true" set val in vB
mir->dalvikInsn.vB = if_true->dalvikInsn.vB;
// "false" set val in vC