summaryrefslogtreecommitdiffstats
path: root/compiler
diff options
context:
space:
mode:
authorSerban Constantinescu <serban.constantinescu@arm.com>2014-05-28 13:21:45 +0100
committerSerban Constantinescu <serban.constantinescu@arm.com>2014-05-30 11:00:34 +0100
commit05e27ff942b42e123ea9519d13d31070ab96f0ac (patch)
tree08c17a04fb8f55c3e0cb9a601978bb66d2d50013 /compiler
parent29b53d3d715b1ec19349e8cbf7c5e4ff529bd5fe (diff)
downloadart-05e27ff942b42e123ea9519d13d31070ab96f0ac.zip
art-05e27ff942b42e123ea9519d13d31070ab96f0ac.tar.gz
art-05e27ff942b42e123ea9519d13d31070ab96f0ac.tar.bz2
AArch64: Enable extended MIR
This patch enables all the extended MIR opcodes for ARM64. Please note that currently the compiler will never generate these opcodes since the BB optimisations are not enabled. Change-Id: Ia712b071f62301db868297d37567795128b5bf2e Signed-off-by: Serban Constantinescu <serban.constantinescu@arm.com>
Diffstat (limited to 'compiler')
-rw-r--r--compiler/dex/frontend.cc25
-rw-r--r--compiler/dex/mir_optimization.cc5
-rw-r--r--compiler/dex/quick/arm64/codegen_arm64.h2
-rw-r--r--compiler/dex/quick/arm64/int_arm64.cc159
4 files changed, 48 insertions, 143 deletions
diff --git a/compiler/dex/frontend.cc b/compiler/dex/frontend.cc
index 1d4a9bb..c204ba5 100644
--- a/compiler/dex/frontend.cc
+++ b/compiler/dex/frontend.cc
@@ -393,21 +393,22 @@ int arm64_support_list[] = {
// Instruction::UNUSED_FE,
// Instruction::UNUSED_FF,
+ // TODO(Arm64): Enable compiler pass
// ----- ExtendedMIROpcode -----
- // kMirOpPhi,
- // kMirOpCopy,
- // kMirOpFusedCmplFloat,
- // kMirOpFusedCmpgFloat,
- // kMirOpFusedCmplDouble,
- // kMirOpFusedCmpgDouble,
- // kMirOpFusedCmpLong,
- // kMirOpNop,
- // kMirOpNullCheck,
- // kMirOpRangeCheck,
+ kMirOpPhi,
+ kMirOpCopy,
+ kMirOpFusedCmplFloat,
+ kMirOpFusedCmpgFloat,
+ kMirOpFusedCmplDouble,
+ kMirOpFusedCmpgDouble,
+ kMirOpFusedCmpLong,
+ kMirOpNop,
+ kMirOpNullCheck,
+ kMirOpRangeCheck,
kMirOpDivZeroCheck,
kMirOpCheck,
- // kMirOpCheckPart2,
- // kMirOpSelect,
+ kMirOpCheckPart2,
+ kMirOpSelect,
// kMirOpLast,
};
diff --git a/compiler/dex/mir_optimization.cc b/compiler/dex/mir_optimization.cc
index 256686e..1bd9049 100644
--- a/compiler/dex/mir_optimization.cc
+++ b/compiler/dex/mir_optimization.cc
@@ -417,7 +417,8 @@ bool MIRGraph::BasicBlockOpt(BasicBlock* bb) {
// 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->IsPortable() &&
- (cu_->instruction_set == kThumb2 || cu_->instruction_set == kX86 || cu_->instruction_set == kX86_64) &&
+ (cu_->instruction_set == kArm64 || cu_->instruction_set == kThumb2 ||
+ cu_->instruction_set == kX86 || cu_->instruction_set == kX86_64) &&
IsInstructionIfCcZ(mir->dalvikInsn.opcode)) {
BasicBlock* ft = GetBasicBlock(bb->fall_through);
DCHECK(ft != NULL);
@@ -443,6 +444,8 @@ bool MIRGraph::BasicBlockOpt(BasicBlock* bb) {
if (SelectKind(tk->last_mir_insn) == kSelectGoto) {
tk->last_mir_insn->optimization_flags |= (MIR_IGNORE_SUSPEND_CHECK);
}
+
+ // TODO: Add logic for LONG.
// Are the block bodies something we can handle?
if ((ft->first_mir_insn == ft->last_mir_insn) &&
(tk->first_mir_insn != tk->last_mir_insn) &&
diff --git a/compiler/dex/quick/arm64/codegen_arm64.h b/compiler/dex/quick/arm64/codegen_arm64.h
index fddbfd7..16bb701 100644
--- a/compiler/dex/quick/arm64/codegen_arm64.h
+++ b/compiler/dex/quick/arm64/codegen_arm64.h
@@ -222,8 +222,6 @@ class Arm64Mir2Lir : public Mir2Lir {
bool skip_this);
private:
- void GenFusedLongCmpImmBranch(BasicBlock* bb, RegLocation rl_src1, int64_t val,
- ConditionCode ccode);
LIR* LoadFPConstantValue(int r_dest, int32_t value);
LIR* LoadFPConstantValueWide(int r_dest, int64_t value);
void ReplaceFixup(LIR* prev_lir, LIR* orig_lir, LIR* new_lir);
diff --git a/compiler/dex/quick/arm64/int_arm64.cc b/compiler/dex/quick/arm64/int_arm64.cc
index 8dad90a..d9428f9 100644
--- a/compiler/dex/quick/arm64/int_arm64.cc
+++ b/compiler/dex/quick/arm64/int_arm64.cc
@@ -29,7 +29,6 @@ LIR* Arm64Mir2Lir::OpCmpBranch(ConditionCode cond, RegStorage src1, RegStorage s
return OpCondBranch(cond, target);
}
-// TODO(Arm64): remove this.
LIR* Arm64Mir2Lir::OpIT(ConditionCode ccode, const char* guide) {
LOG(FATAL) << "Unexpected use of OpIT for Arm64";
return NULL;
@@ -85,154 +84,58 @@ void Arm64Mir2Lir::GenShiftOpLong(Instruction::Code opcode, RegLocation rl_dest,
StoreValueWide(rl_dest, rl_result);
}
-void Arm64Mir2Lir::GenFusedLongCmpImmBranch(BasicBlock* bb, RegLocation rl_src1,
- int64_t val, ConditionCode ccode) {
- LIR* taken = &block_label_list_[bb->taken];
- rl_src1 = LoadValueWide(rl_src1, kCoreReg);
-
- if (val == 0 && (ccode == kCondEq || ccode == kCondNe)) {
- ArmOpcode opcode = (ccode == kCondEq) ? kA64Cbz2rt : kA64Cbnz2rt;
- LIR* branch = NewLIR2(WIDE(opcode), rl_src1.reg.GetLowReg(), 0);
- branch->target = taken;
- } else {
- OpRegImm64(kOpCmp, rl_src1.reg, val);
- OpCondBranch(ccode, taken);
- }
-}
-
void Arm64Mir2Lir::GenSelect(BasicBlock* bb, MIR* mir) {
- // TODO(Arm64): implement this.
- UNIMPLEMENTED(FATAL);
-
RegLocation rl_result;
RegLocation rl_src = mir_graph_->GetSrc(mir, 0);
RegLocation rl_dest = mir_graph_->GetDest(mir);
rl_src = LoadValue(rl_src, kCoreReg);
- ConditionCode ccode = mir->meta.ccode;
- if (mir->ssa_rep->num_uses == 1) {
- // CONST case
- int true_val = mir->dalvikInsn.vB;
- int false_val = mir->dalvikInsn.vC;
- rl_result = EvalLoc(rl_dest, kCoreReg, true);
- // Change kCondNe to kCondEq for the special cases below.
- if (ccode == kCondNe) {
- ccode = kCondEq;
- std::swap(true_val, false_val);
- }
- bool cheap_false_val = InexpensiveConstantInt(false_val);
- if (cheap_false_val && ccode == kCondEq && (true_val == 0 || true_val == -1)) {
- OpRegRegImm(kOpSub, rl_result.reg, rl_src.reg, -true_val);
- DCHECK(last_lir_insn_->u.m.def_mask & ENCODE_CCODE);
- OpIT(true_val == 0 ? kCondNe : kCondUge, "");
- LoadConstant(rl_result.reg, false_val);
- GenBarrier(); // Add a scheduling barrier to keep the IT shadow intact
- } else if (cheap_false_val && ccode == kCondEq && true_val == 1) {
- OpRegRegImm(kOpRsub, rl_result.reg, rl_src.reg, 1);
- DCHECK(last_lir_insn_->u.m.def_mask & ENCODE_CCODE);
- OpIT(kCondLs, "");
- LoadConstant(rl_result.reg, false_val);
- GenBarrier(); // Add a scheduling barrier to keep the IT shadow intact
- } else if (cheap_false_val && InexpensiveConstantInt(true_val)) {
- OpRegImm(kOpCmp, rl_src.reg, 0);
- OpIT(ccode, "E");
- LoadConstant(rl_result.reg, true_val);
- LoadConstant(rl_result.reg, false_val);
- GenBarrier(); // Add a scheduling barrier to keep the IT shadow intact
- } else {
- // Unlikely case - could be tuned.
- RegStorage t_reg1 = AllocTemp();
- RegStorage t_reg2 = AllocTemp();
- LoadConstant(t_reg1, true_val);
- LoadConstant(t_reg2, false_val);
- OpRegImm(kOpCmp, rl_src.reg, 0);
- OpIT(ccode, "E");
- OpRegCopy(rl_result.reg, t_reg1);
- OpRegCopy(rl_result.reg, t_reg2);
- GenBarrier(); // Add a scheduling barrier to keep the IT shadow intact
- }
- } else {
- // MOVE case
- RegLocation rl_true = mir_graph_->reg_location_[mir->ssa_rep->uses[1]];
- RegLocation rl_false = mir_graph_->reg_location_[mir->ssa_rep->uses[2]];
- rl_true = LoadValue(rl_true, kCoreReg);
- rl_false = LoadValue(rl_false, kCoreReg);
- rl_result = EvalLoc(rl_dest, kCoreReg, true);
- OpRegImm(kOpCmp, rl_src.reg, 0);
- if (rl_result.reg.GetReg() == rl_true.reg.GetReg()) { // Is the "true" case already in place?
- OpIT(NegateComparison(ccode), "");
- OpRegCopy(rl_result.reg, rl_false.reg);
- } else if (rl_result.reg.GetReg() == rl_false.reg.GetReg()) { // False case in place?
- OpIT(ccode, "");
- OpRegCopy(rl_result.reg, rl_true.reg);
- } else { // Normal - select between the two.
- OpIT(ccode, "E");
- OpRegCopy(rl_result.reg, rl_true.reg);
- OpRegCopy(rl_result.reg, rl_false.reg);
- }
- GenBarrier(); // Add a scheduling barrier to keep the IT shadow intact
- }
+ ArmConditionCode code = ArmConditionEncoding(mir->meta.ccode);
+
+ RegLocation rl_true = mir_graph_->reg_location_[mir->ssa_rep->uses[1]];
+ RegLocation rl_false = mir_graph_->reg_location_[mir->ssa_rep->uses[2]];
+ rl_true = LoadValue(rl_true, kCoreReg);
+ rl_false = LoadValue(rl_false, kCoreReg);
+ rl_result = EvalLoc(rl_dest, kCoreReg, true);
+ OpRegImm(kOpCmp, rl_src.reg, 0);
+ NewLIR4(kA64Csel4rrrc, rl_result.reg.GetReg(), rl_true.reg.GetReg(),
+ rl_false.reg.GetReg(), code);
StoreValue(rl_dest, rl_result);
}
void Arm64Mir2Lir::GenFusedLongCmpBranch(BasicBlock* bb, MIR* mir) {
- // TODO(Arm64): implement this.
- UNIMPLEMENTED(FATAL);
-
RegLocation rl_src1 = mir_graph_->GetSrcWide(mir, 0);
RegLocation rl_src2 = mir_graph_->GetSrcWide(mir, 2);
+ LIR* taken = &block_label_list_[bb->taken];
+ LIR* not_taken = &block_label_list_[bb->fall_through];
+ rl_src1 = LoadValueWide(rl_src1, kCoreReg);
// Normalize such that if either operand is constant, src2 will be constant.
ConditionCode ccode = mir->meta.ccode;
if (rl_src1.is_const) {
std::swap(rl_src1, rl_src2);
ccode = FlipComparisonOrder(ccode);
}
+
if (rl_src2.is_const) {
- RegLocation rl_temp = UpdateLocWide(rl_src2);
- // Do special compare/branch against simple const operand if not already in registers.
+ rl_src2 = UpdateLocWide(rl_src2);
int64_t val = mir_graph_->ConstantValueWide(rl_src2);
- if ((rl_temp.location != kLocPhysReg)
- /*&& ((ModifiedImmediate(Low32Bits(val)) >= 0) && (ModifiedImmediate(High32Bits(val)) >= 0))*/) {
- GenFusedLongCmpImmBranch(bb, rl_src1, val, ccode);
+ // Special handling using cbz & cbnz.
+ if (val == 0 && (ccode == kCondEq || ccode == kCondNe)) {
+ OpCmpImmBranch(ccode, rl_src1.reg, 0, taken);
+ OpCmpImmBranch(NegateComparison(ccode), rl_src1.reg, 0, not_taken);
+ return;
+ // Only handle Imm if src2 is not already in a register.
+ } else if (rl_src2.location != kLocPhysReg) {
+ OpRegImm64(kOpCmp, rl_src1.reg, val);
+ OpCondBranch(ccode, taken);
+ OpCondBranch(NegateComparison(ccode), not_taken);
return;
}
}
- LIR* taken = &block_label_list_[bb->taken];
- LIR* not_taken = &block_label_list_[bb->fall_through];
- rl_src1 = LoadValueWide(rl_src1, kCoreReg);
+
rl_src2 = LoadValueWide(rl_src2, kCoreReg);
- OpRegReg(kOpCmp, rl_src1.reg.GetHigh(), rl_src2.reg.GetHigh());
- switch (ccode) {
- case kCondEq:
- OpCondBranch(kCondNe, not_taken);
- break;
- case kCondNe:
- OpCondBranch(kCondNe, taken);
- break;
- case kCondLt:
- OpCondBranch(kCondLt, taken);
- OpCondBranch(kCondGt, not_taken);
- ccode = kCondUlt;
- break;
- case kCondLe:
- OpCondBranch(kCondLt, taken);
- OpCondBranch(kCondGt, not_taken);
- ccode = kCondLs;
- break;
- case kCondGt:
- OpCondBranch(kCondGt, taken);
- OpCondBranch(kCondLt, not_taken);
- ccode = kCondHi;
- break;
- case kCondGe:
- OpCondBranch(kCondGt, taken);
- OpCondBranch(kCondLt, not_taken);
- ccode = kCondUge;
- break;
- default:
- LOG(FATAL) << "Unexpected ccode: " << ccode;
- }
- OpRegReg(kOpCmp, rl_src1.reg.GetLow(), rl_src2.reg.GetLow());
+ OpRegReg(kOpCmp, rl_src1.reg, rl_src2.reg);
OpCondBranch(ccode, taken);
+ OpCondBranch(NegateComparison(ccode), not_taken);
}
/*
@@ -468,7 +371,7 @@ bool Arm64Mir2Lir::GenInlinedMinMaxInt(CallInfo* info, bool is_min) {
RegLocation rl_dest = InlineTarget(info);
RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true);
OpRegReg(kOpCmp, rl_src1.reg, rl_src2.reg);
- OpIT((is_min) ? kCondGt : kCondLt, "E");
+ // OpIT((is_min) ? kCondGt : kCondLt, "E");
OpRegReg(kOpMov, rl_result.reg, rl_src2.reg);
OpRegReg(kOpMov, rl_result.reg, rl_src1.reg);
GenBarrier();
@@ -668,7 +571,7 @@ bool Arm64Mir2Lir::GenInlinedCas(CallInfo* info, bool is_long, bool is_object) {
NewLIR3(kA64Ldxr2rX, r_tmp.GetReg(), r_ptr.GetReg(), 0);
OpRegReg(kOpSub, r_tmp, rl_expected.reg);
DCHECK(last_lir_insn_->u.m.def_mask & ENCODE_CCODE);
- OpIT(kCondEq, "T");
+ // OpIT(kCondEq, "T");
NewLIR4(kA64Stxr3wrX /* eq */, r_tmp.GetReg(), rl_new_value.reg.GetReg(), r_ptr.GetReg(), 0);
}
@@ -684,7 +587,7 @@ bool Arm64Mir2Lir::GenInlinedCas(CallInfo* info, bool is_long, bool is_object) {
RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true);
OpRegRegImm(kOpRsub, rl_result.reg, r_tmp, 1);
DCHECK(last_lir_insn_->u.m.def_mask & ENCODE_CCODE);
- OpIT(kCondUlt, "");
+ // OpIT(kCondUlt, "");
LoadConstant(rl_result.reg, 0); /* cc */
FreeTemp(r_tmp); // Now unneeded.