Clean up MIRGraph::CanThrow().
Merge with the code from CombineBlocks().
Change-Id: I73c71286acba1b6042f85f0bd19c525450ce9c05
diff --git a/compiler/dex/mir_optimization.cc b/compiler/dex/mir_optimization.cc
index 6e9844c..238377c 100644
--- a/compiler/dex/mir_optimization.cc
+++ b/compiler/dex/mir_optimization.cc
@@ -788,43 +788,9 @@
MIR* mir = bb->last_mir_insn;
DCHECK(bb->first_mir_insn != nullptr);
- // Grab the attributes from the paired opcode.
+ // Get the paired insn and check if it can still throw.
MIR* throw_insn = mir->meta.throw_insn;
- uint64_t df_attributes = GetDataFlowAttributes(throw_insn);
-
- // Don't combine if the throw_insn can still throw NPE.
- if ((df_attributes & DF_HAS_NULL_CHKS) != 0 &&
- (throw_insn->optimization_flags & MIR_IGNORE_NULL_CHECK) == 0) {
- break;
- }
- // Now whitelist specific instructions.
- bool ok = false;
- if ((df_attributes & DF_IFIELD) != 0) {
- // Combine only if fast, otherwise weird things can happen.
- const MirIFieldLoweringInfo& field_info = GetIFieldLoweringInfo(throw_insn);
- ok = (df_attributes & DF_DA) ? field_info.FastGet() : field_info.FastPut();
- } else if ((df_attributes & DF_SFIELD) != 0) {
- // Combine only if fast, otherwise weird things can happen.
- const MirSFieldLoweringInfo& field_info = GetSFieldLoweringInfo(throw_insn);
- bool fast = ((df_attributes & DF_DA) ? field_info.FastGet() : field_info.FastPut());
- // Don't combine if the SGET/SPUT can call <clinit>().
- bool clinit = !field_info.IsClassInitialized() &&
- (throw_insn->optimization_flags & MIR_CLASS_IS_INITIALIZED) == 0;
- ok = fast && !clinit;
- } else if ((df_attributes & DF_HAS_RANGE_CHKS) != 0) {
- // Only AGET/APUT have range checks. We have processed the AGET/APUT null check above.
- DCHECK_NE(throw_insn->optimization_flags & MIR_IGNORE_NULL_CHECK, 0);
- ok = ((throw_insn->optimization_flags & MIR_IGNORE_RANGE_CHECK) != 0);
- } else if ((throw_insn->dalvikInsn.FlagsOf() & Instruction::kThrow) == 0) {
- // We can encounter a non-throwing insn here thanks to inlining or other optimizations.
- ok = true;
- } else if (throw_insn->dalvikInsn.opcode == Instruction::ARRAY_LENGTH ||
- throw_insn->dalvikInsn.opcode == Instruction::FILL_ARRAY_DATA ||
- static_cast<int>(throw_insn->dalvikInsn.opcode) == kMirOpNullCheck) {
- // No more checks for these (null check was processed above).
- ok = true;
- }
- if (!ok) {
+ if (CanThrow(throw_insn)) {
break;
}
@@ -1719,32 +1685,37 @@
const int opt_flags = mir->optimization_flags;
uint64_t df_attributes = GetDataFlowAttributes(mir);
+ // First, check if the insn can still throw NPE.
if (((df_attributes & DF_HAS_NULL_CHKS) != 0) && ((opt_flags & MIR_IGNORE_NULL_CHECK) == 0)) {
return true;
}
+
+ // Now process specific instructions.
if ((df_attributes & DF_IFIELD) != 0) {
- // The IGET/IPUT family.
+ // The IGET/IPUT family. We have processed the IGET/IPUT null check above.
+ DCHECK_NE(opt_flags & MIR_IGNORE_NULL_CHECK, 0);
+ // If not fast, weird things can happen and the insn can throw.
const MirIFieldLoweringInfo& field_info = GetIFieldLoweringInfo(mir);
- bool fast = (df_attributes & DF_DA) ? field_info.FastGet() : field_info.FastPut();
- // Already processed null check above.
- if (fast) {
- return false;
- }
- } else if ((df_attributes & DF_HAS_RANGE_CHKS) != 0) {
- // The AGET/APUT family.
- // Already processed null check above.
- if ((opt_flags & MIR_IGNORE_RANGE_CHECK) != 0) {
- return false;
- }
+ bool fast = (df_attributes & DF_DA) != 0 ? field_info.FastGet() : field_info.FastPut();
+ return !fast;
} else if ((df_attributes & DF_SFIELD) != 0) {
- // The SGET/SPUT family.
+ // The SGET/SPUT family. Check for potentially throwing class initialization.
+ // Also, if not fast, weird things can happen and the insn can throw.
const MirSFieldLoweringInfo& field_info = GetSFieldLoweringInfo(mir);
- bool fast = (df_attributes & DF_DA) ? field_info.FastGet() : field_info.FastPut();
+ bool fast = (df_attributes & DF_DA) != 0 ? field_info.FastGet() : field_info.FastPut();
bool is_class_initialized = field_info.IsClassInitialized() ||
((mir->optimization_flags & MIR_CLASS_IS_INITIALIZED) != 0);
- if (fast && is_class_initialized) {
- return false;
- }
+ return !(fast && is_class_initialized);
+ } else if ((df_attributes & DF_HAS_RANGE_CHKS) != 0) {
+ // Only AGET/APUT have range checks. We have processed the AGET/APUT null check above.
+ DCHECK_NE(opt_flags & MIR_IGNORE_NULL_CHECK, 0);
+ // Non-throwing only if range check has been eliminated.
+ return ((opt_flags & MIR_IGNORE_RANGE_CHECK) == 0);
+ } else if (mir->dalvikInsn.opcode == Instruction::ARRAY_LENGTH ||
+ mir->dalvikInsn.opcode == Instruction::FILL_ARRAY_DATA ||
+ static_cast<int>(mir->dalvikInsn.opcode) == kMirOpNullCheck) {
+ // No more checks for these (null check was processed above).
+ return false;
}
return true;
}