diff options
Diffstat (limited to 'compiler/dex/vreg_analysis.cc')
-rw-r--r-- | compiler/dex/vreg_analysis.cc | 452 |
1 files changed, 2 insertions, 450 deletions
diff --git a/compiler/dex/vreg_analysis.cc b/compiler/dex/vreg_analysis.cc index 2b78e38..948ba7b 100644 --- a/compiler/dex/vreg_analysis.cc +++ b/compiler/dex/vreg_analysis.cc @@ -23,400 +23,6 @@ namespace art { -bool MIRGraph::SetFp(int index, bool is_fp) { - bool change = false; - if (is_fp && !reg_location_[index].fp) { - reg_location_[index].fp = true; - reg_location_[index].defined = true; - change = true; - } - return change; -} - -bool MIRGraph::SetFp(int index) { - bool change = false; - if (!reg_location_[index].fp) { - reg_location_[index].fp = true; - reg_location_[index].defined = true; - change = true; - } - return change; -} - -bool MIRGraph::SetCore(int index, bool is_core) { - bool change = false; - if (is_core && !reg_location_[index].defined) { - reg_location_[index].core = true; - reg_location_[index].defined = true; - change = true; - } - return change; -} - -bool MIRGraph::SetCore(int index) { - bool change = false; - if (!reg_location_[index].defined) { - reg_location_[index].core = true; - reg_location_[index].defined = true; - change = true; - } - return change; -} - -bool MIRGraph::SetRef(int index, bool is_ref) { - bool change = false; - if (is_ref && !reg_location_[index].defined) { - reg_location_[index].ref = true; - reg_location_[index].defined = true; - change = true; - } - return change; -} - -bool MIRGraph::SetRef(int index) { - bool change = false; - if (!reg_location_[index].defined) { - reg_location_[index].ref = true; - reg_location_[index].defined = true; - change = true; - } - return change; -} - -bool MIRGraph::SetWide(int index, bool is_wide) { - bool change = false; - if (is_wide && !reg_location_[index].wide) { - reg_location_[index].wide = true; - change = true; - } - return change; -} - -bool MIRGraph::SetWide(int index) { - bool change = false; - if (!reg_location_[index].wide) { - reg_location_[index].wide = true; - change = true; - } - return change; -} - -bool MIRGraph::SetHigh(int index, bool is_high) { - bool change = false; - if (is_high && !reg_location_[index].high_word) { - reg_location_[index].high_word = true; - change = true; - } - return change; -} - -bool MIRGraph::SetHigh(int index) { - bool change = false; - if (!reg_location_[index].high_word) { - reg_location_[index].high_word = true; - change = true; - } - return change; -} - - -/* - * Infer types and sizes. We don't need to track change on sizes, - * as it doesn't propagate. We're guaranteed at least one pass through - * the cfg. - */ -bool MIRGraph::InferTypeAndSize(BasicBlock* bb, MIR* mir, bool changed) { - SSARepresentation *ssa_rep = mir->ssa_rep; - - /* - * The dex bytecode definition does not explicitly outlaw the definition of the same - * virtual register to be used in both a 32-bit and 64-bit pair context. However, dx - * does not generate this pattern (at least recently). Further, in the next revision of - * dex, we will forbid this. To support the few cases in the wild, detect this pattern - * and punt to the interpreter. - */ - bool type_mismatch = false; - - if (ssa_rep) { - uint64_t attrs = GetDataFlowAttributes(mir); - const int* uses = ssa_rep->uses; - const int* defs = ssa_rep->defs; - - // Handle defs - if (attrs & DF_DA) { - if (attrs & DF_CORE_A) { - changed |= SetCore(defs[0]); - } - if (attrs & DF_REF_A) { - changed |= SetRef(defs[0]); - } - if (attrs & DF_A_WIDE) { - reg_location_[defs[0]].wide = true; - reg_location_[defs[1]].wide = true; - reg_location_[defs[1]].high_word = true; - DCHECK_EQ(SRegToVReg(defs[0])+1, - SRegToVReg(defs[1])); - } - } - - - // Handles uses - int next = 0; - if (attrs & DF_UA) { - if (attrs & DF_CORE_A) { - changed |= SetCore(uses[next]); - } - if (attrs & DF_REF_A) { - changed |= SetRef(uses[next]); - } - if (attrs & DF_A_WIDE) { - reg_location_[uses[next]].wide = true; - reg_location_[uses[next + 1]].wide = true; - reg_location_[uses[next + 1]].high_word = true; - DCHECK_EQ(SRegToVReg(uses[next])+1, - SRegToVReg(uses[next + 1])); - next += 2; - } else { - type_mismatch |= reg_location_[uses[next]].wide; - next++; - } - } - if (attrs & DF_UB) { - if (attrs & DF_CORE_B) { - changed |= SetCore(uses[next]); - } - if (attrs & DF_REF_B) { - changed |= SetRef(uses[next]); - } - if (attrs & DF_B_WIDE) { - reg_location_[uses[next]].wide = true; - reg_location_[uses[next + 1]].wide = true; - reg_location_[uses[next + 1]].high_word = true; - DCHECK_EQ(SRegToVReg(uses[next])+1, - SRegToVReg(uses[next + 1])); - next += 2; - } else { - type_mismatch |= reg_location_[uses[next]].wide; - next++; - } - } - if (attrs & DF_UC) { - if (attrs & DF_CORE_C) { - changed |= SetCore(uses[next]); - } - if (attrs & DF_REF_C) { - changed |= SetRef(uses[next]); - } - if (attrs & DF_C_WIDE) { - reg_location_[uses[next]].wide = true; - reg_location_[uses[next + 1]].wide = true; - reg_location_[uses[next + 1]].high_word = true; - DCHECK_EQ(SRegToVReg(uses[next])+1, - SRegToVReg(uses[next + 1])); - } else { - type_mismatch |= reg_location_[uses[next]].wide; - } - } - - // Special-case return handling - if ((mir->dalvikInsn.opcode == Instruction::RETURN) || - (mir->dalvikInsn.opcode == Instruction::RETURN_WIDE) || - (mir->dalvikInsn.opcode == Instruction::RETURN_OBJECT)) { - switch (cu_->shorty[0]) { - case 'I': - type_mismatch |= reg_location_[uses[0]].wide; - changed |= SetCore(uses[0]); - break; - case 'J': - changed |= SetCore(uses[0]); - changed |= SetCore(uses[1]); - reg_location_[uses[0]].wide = true; - reg_location_[uses[1]].wide = true; - reg_location_[uses[1]].high_word = true; - break; - case 'F': - type_mismatch |= reg_location_[uses[0]].wide; - changed |= SetFp(uses[0]); - break; - case 'D': - changed |= SetFp(uses[0]); - changed |= SetFp(uses[1]); - reg_location_[uses[0]].wide = true; - reg_location_[uses[1]].wide = true; - reg_location_[uses[1]].high_word = true; - break; - case 'L': - type_mismatch |= reg_location_[uses[0]].wide; - changed |= SetRef(uses[0]); - break; - default: break; - } - } - - // Special-case handling for format 35c/3rc invokes - Instruction::Code opcode = mir->dalvikInsn.opcode; - int flags = MIR::DecodedInstruction::IsPseudoMirOp(opcode) ? - 0 : mir->dalvikInsn.FlagsOf(); - if ((flags & Instruction::kInvoke) && - (attrs & (DF_FORMAT_35C | DF_FORMAT_3RC))) { - DCHECK_EQ(next, 0); - const auto& lowering_info = GetMethodLoweringInfo(mir); - const char* shorty = GetShortyFromMethodReference(lowering_info.GetTargetMethod()); - // Handle result type if floating point - if ((shorty[0] == 'F') || (shorty[0] == 'D')) { - MIR* move_result_mir = FindMoveResult(bb, mir); - // Result might not be used at all, so no move-result - if (move_result_mir && (move_result_mir->dalvikInsn.opcode != - Instruction::MOVE_RESULT_OBJECT)) { - SSARepresentation* tgt_rep = move_result_mir->ssa_rep; - DCHECK(tgt_rep != NULL); - tgt_rep->fp_def[0] = true; - changed |= SetFp(tgt_rep->defs[0]); - if (shorty[0] == 'D') { - tgt_rep->fp_def[1] = true; - changed |= SetFp(tgt_rep->defs[1]); - } - } - } - int num_uses = mir->dalvikInsn.vA; - // If this is a non-static invoke, mark implicit "this" - if (!IsInstructionInvokeStatic(mir->dalvikInsn.opcode)) { - reg_location_[uses[next]].defined = true; - reg_location_[uses[next]].ref = true; - type_mismatch |= reg_location_[uses[next]].wide; - next++; - } - uint32_t cpos = 1; - if (strlen(shorty) > 1) { - for (int i = next; i < num_uses;) { - DCHECK_LT(cpos, strlen(shorty)); - switch (shorty[cpos++]) { - case 'D': - ssa_rep->fp_use[i] = true; - ssa_rep->fp_use[i+1] = true; - reg_location_[uses[i]].wide = true; - reg_location_[uses[i+1]].wide = true; - reg_location_[uses[i+1]].high_word = true; - DCHECK_EQ(SRegToVReg(uses[i])+1, SRegToVReg(uses[i+1])); - i++; - break; - case 'J': - reg_location_[uses[i]].wide = true; - reg_location_[uses[i+1]].wide = true; - reg_location_[uses[i+1]].high_word = true; - DCHECK_EQ(SRegToVReg(uses[i])+1, SRegToVReg(uses[i+1])); - changed |= SetCore(uses[i]); - i++; - break; - case 'F': - type_mismatch |= reg_location_[uses[i]].wide; - ssa_rep->fp_use[i] = true; - break; - case 'L': - type_mismatch |= reg_location_[uses[i]].wide; - changed |= SetRef(uses[i]); - break; - default: - type_mismatch |= reg_location_[uses[i]].wide; - changed |= SetCore(uses[i]); - break; - } - i++; - } - } - } - - for (int i = 0; ssa_rep->fp_use && i< ssa_rep->num_uses; i++) { - if (ssa_rep->fp_use[i]) { - changed |= SetFp(uses[i]); - } - } - for (int i = 0; ssa_rep->fp_def && i< ssa_rep->num_defs; i++) { - if (ssa_rep->fp_def[i]) { - changed |= SetFp(defs[i]); - } - } - // Special-case handling for moves & Phi - if (attrs & (DF_IS_MOVE | DF_NULL_TRANSFER_N)) { - /* - * If any of our inputs or outputs is defined, set all. - * Some ugliness related to Phi nodes and wide values. - * The Phi set will include all low words or all high - * words, so we have to treat them specially. - */ - bool is_phi = (static_cast<int>(mir->dalvikInsn.opcode) == kMirOpPhi); - RegLocation rl_temp = reg_location_[defs[0]]; - bool defined_fp = rl_temp.defined && rl_temp.fp; - bool defined_core = rl_temp.defined && rl_temp.core; - bool defined_ref = rl_temp.defined && rl_temp.ref; - bool is_wide = rl_temp.wide || ((attrs & DF_A_WIDE) != 0); - bool is_high = is_phi && rl_temp.wide && rl_temp.high_word; - for (int i = 0; i < ssa_rep->num_uses; i++) { - rl_temp = reg_location_[uses[i]]; - defined_fp |= rl_temp.defined && rl_temp.fp; - defined_core |= rl_temp.defined && rl_temp.core; - defined_ref |= rl_temp.defined && rl_temp.ref; - is_wide |= rl_temp.wide; - is_high |= is_phi && rl_temp.wide && rl_temp.high_word; - } - /* - * We don't normally expect to see a Dalvik register definition used both as a - * floating point and core value, though technically it could happen with constants. - * Until we have proper typing, detect this situation and disable register promotion - * (which relies on the distinction between core a fp usages). - */ - if ((defined_fp && (defined_core | defined_ref)) && - ((cu_->disable_opt & (1 << kPromoteRegs)) == 0)) { - LOG(WARNING) << PrettyMethod(cu_->method_idx, *cu_->dex_file) - << " op at block " << bb->id - << " has both fp and core/ref uses for same def."; - cu_->disable_opt |= (1 << kPromoteRegs); - } - changed |= SetFp(defs[0], defined_fp); - changed |= SetCore(defs[0], defined_core); - changed |= SetRef(defs[0], defined_ref); - changed |= SetWide(defs[0], is_wide); - changed |= SetHigh(defs[0], is_high); - if (attrs & DF_A_WIDE) { - changed |= SetWide(defs[1]); - changed |= SetHigh(defs[1]); - } - - bool has_ins = (GetNumOfInVRs() > 0); - - for (int i = 0; i < ssa_rep->num_uses; i++) { - if (has_ins && IsInVReg(uses[i])) { - // NB: The SSA name for the first def of an in-reg will be the same as - // the reg's actual name. - if (!reg_location_[uses[i]].fp && defined_fp) { - // If we were about to infer that this first def of an in-reg is a float - // when it wasn't previously (because float/int is set during SSA initialization), - // do not allow this to happen. - continue; - } - } - changed |= SetFp(uses[i], defined_fp); - changed |= SetCore(uses[i], defined_core); - changed |= SetRef(uses[i], defined_ref); - changed |= SetWide(uses[i], is_wide); - changed |= SetHigh(uses[i], is_high); - } - if (attrs & DF_A_WIDE) { - DCHECK_EQ(ssa_rep->num_uses, 2); - changed |= SetWide(uses[1]); - changed |= SetHigh(uses[1]); - } - } - } - if (type_mismatch) { - LOG(WARNING) << "Deprecated dex type mismatch, interpreting " - << PrettyMethod(cu_->method_idx, *cu_->dex_file); - LOG(INFO) << "@ 0x" << std::hex << mir->offset; - SetPuntToInterpreter(true); - } - return changed; -} - static const char* storage_name[] = {" Frame ", "PhysReg", " CompilerTemp "}; void MIRGraph::DumpRegLocTable(RegLocation* table, int count) { @@ -446,66 +52,12 @@ void MIRGraph::InitRegLocations() { loc[i] = fresh_loc; loc[i].s_reg_low = i; loc[i].is_const = false; // Constants will be marked by constant propagation pass later. - loc[i].wide = false; } - /* Treat Method* as a normal reference */ - int method_sreg = GetMethodSReg(); - loc[method_sreg].ref = true; - loc[method_sreg].location = kLocCompilerTemp; - loc[method_sreg].defined = true; + /* Mark the location of ArtMethod* as temporary */ + loc[GetMethodSReg()].location = kLocCompilerTemp; reg_location_ = loc; - - int num_regs = GetNumOfCodeVRs(); - - /* Add types of incoming arguments based on signature */ - int num_ins = GetNumOfInVRs(); - if (num_ins > 0) { - int s_reg = num_regs - num_ins; - if ((cu_->access_flags & kAccStatic) == 0) { - // For non-static, skip past "this" - reg_location_[s_reg].defined = true; - reg_location_[s_reg].ref = true; - s_reg++; - } - const char* shorty = cu_->shorty; - int shorty_len = strlen(shorty); - for (int i = 1; i < shorty_len; i++) { - switch (shorty[i]) { - case 'D': - reg_location_[s_reg].wide = true; - reg_location_[s_reg+1].high_word = true; - reg_location_[s_reg+1].fp = true; - DCHECK_EQ(SRegToVReg(s_reg)+1, SRegToVReg(s_reg+1)); - reg_location_[s_reg].fp = true; - reg_location_[s_reg].defined = true; - s_reg++; - break; - case 'J': - reg_location_[s_reg].wide = true; - reg_location_[s_reg+1].high_word = true; - DCHECK_EQ(SRegToVReg(s_reg)+1, SRegToVReg(s_reg+1)); - reg_location_[s_reg].core = true; - reg_location_[s_reg].defined = true; - s_reg++; - break; - case 'F': - reg_location_[s_reg].fp = true; - reg_location_[s_reg].defined = true; - break; - case 'L': - reg_location_[s_reg].ref = true; - reg_location_[s_reg].defined = true; - break; - default: - reg_location_[s_reg].core = true; - reg_location_[s_reg].defined = true; - break; - } - s_reg++; - } - } } /* |