diff options
Diffstat (limited to 'compiler/optimizing')
| -rw-r--r-- | compiler/optimizing/block_builder.cc | 2 | ||||
| -rw-r--r-- | compiler/optimizing/code_generator.cc | 2 | ||||
| -rw-r--r-- | compiler/optimizing/code_generator.h | 4 | ||||
| -rw-r--r-- | compiler/optimizing/code_generator_arm64.h | 4 | ||||
| -rw-r--r-- | compiler/optimizing/code_generator_arm_vixl.h | 4 | ||||
| -rw-r--r-- | compiler/optimizing/code_generator_mips.h | 4 | ||||
| -rw-r--r-- | compiler/optimizing/code_generator_mips64.h | 2 | ||||
| -rw-r--r-- | compiler/optimizing/code_sinking.cc | 5 | ||||
| -rw-r--r-- | compiler/optimizing/inliner.cc | 12 | ||||
| -rw-r--r-- | compiler/optimizing/instruction_builder.cc | 2 | ||||
| -rw-r--r-- | compiler/optimizing/loop_optimization.cc | 169 | ||||
| -rw-r--r-- | compiler/optimizing/nodes.h | 2 | ||||
| -rw-r--r-- | compiler/optimizing/nodes_vector.h | 2 | ||||
| -rw-r--r-- | compiler/optimizing/ssa_builder.cc | 2 |
14 files changed, 133 insertions, 83 deletions
diff --git a/compiler/optimizing/block_builder.cc b/compiler/optimizing/block_builder.cc index 2b568bcffd..95f2e98ac6 100644 --- a/compiler/optimizing/block_builder.cc +++ b/compiler/optimizing/block_builder.cc @@ -17,7 +17,7 @@ #include "block_builder.h" #include "base/logging.h" // FOR VLOG. -#include "bytecode_utils.h" +#include "dex/bytecode_utils.h" #include "dex/code_item_accessors-inl.h" #include "dex/dex_file_exception_helpers.h" #include "quicken_info.h" diff --git a/compiler/optimizing/code_generator.cc b/compiler/optimizing/code_generator.cc index 0fcc9c6d05..c2ae7646b5 100644 --- a/compiler/optimizing/code_generator.cc +++ b/compiler/optimizing/code_generator.cc @@ -44,9 +44,9 @@ #include "base/bit_utils_iterator.h" #include "base/casts.h" #include "base/leb128.h" -#include "bytecode_utils.h" #include "class_linker.h" #include "compiled_method.h" +#include "dex/bytecode_utils.h" #include "dex/code_item_accessors-inl.h" #include "dex/verified_method.h" #include "driver/compiler_driver.h" diff --git a/compiler/optimizing/code_generator.h b/compiler/optimizing/code_generator.h index 7031483a77..a4873202b2 100644 --- a/compiler/optimizing/code_generator.h +++ b/compiler/optimizing/code_generator.h @@ -24,6 +24,8 @@ #include "base/bit_field.h" #include "base/bit_utils.h" #include "base/enums.h" +#include "dex/string_reference.h" +#include "dex/type_reference.h" #include "globals.h" #include "graph_visualizer.h" #include "locations.h" @@ -33,8 +35,6 @@ #include "read_barrier_option.h" #include "stack.h" #include "stack_map.h" -#include "string_reference.h" -#include "type_reference.h" #include "utils/label.h" namespace art { diff --git a/compiler/optimizing/code_generator_arm64.h b/compiler/optimizing/code_generator_arm64.h index b59ccd9034..a8a9802f9a 100644 --- a/compiler/optimizing/code_generator_arm64.h +++ b/compiler/optimizing/code_generator_arm64.h @@ -21,11 +21,11 @@ #include "code_generator.h" #include "common_arm64.h" #include "dex/dex_file_types.h" +#include "dex/string_reference.h" +#include "dex/type_reference.h" #include "driver/compiler_options.h" #include "nodes.h" #include "parallel_move_resolver.h" -#include "string_reference.h" -#include "type_reference.h" #include "utils/arm64/assembler_arm64.h" // TODO(VIXL): Make VIXL compile with -Wshadow. diff --git a/compiler/optimizing/code_generator_arm_vixl.h b/compiler/optimizing/code_generator_arm_vixl.h index 2d8f6a6c78..6a07e36022 100644 --- a/compiler/optimizing/code_generator_arm_vixl.h +++ b/compiler/optimizing/code_generator_arm_vixl.h @@ -20,11 +20,11 @@ #include "base/enums.h" #include "code_generator.h" #include "common_arm.h" +#include "dex/string_reference.h" +#include "dex/type_reference.h" #include "driver/compiler_options.h" #include "nodes.h" #include "parallel_move_resolver.h" -#include "string_reference.h" -#include "type_reference.h" #include "utils/arm/assembler_arm_vixl.h" // TODO(VIXL): make vixl clean wrt -Wshadow. diff --git a/compiler/optimizing/code_generator_mips.h b/compiler/optimizing/code_generator_mips.h index d90689695b..1f1743ff9e 100644 --- a/compiler/optimizing/code_generator_mips.h +++ b/compiler/optimizing/code_generator_mips.h @@ -19,11 +19,11 @@ #include "code_generator.h" #include "dex/dex_file_types.h" +#include "dex/string_reference.h" +#include "dex/type_reference.h" #include "driver/compiler_options.h" #include "nodes.h" #include "parallel_move_resolver.h" -#include "string_reference.h" -#include "type_reference.h" #include "utils/mips/assembler_mips.h" namespace art { diff --git a/compiler/optimizing/code_generator_mips64.h b/compiler/optimizing/code_generator_mips64.h index d1da1cec15..74c947e5d5 100644 --- a/compiler/optimizing/code_generator_mips64.h +++ b/compiler/optimizing/code_generator_mips64.h @@ -18,10 +18,10 @@ #define ART_COMPILER_OPTIMIZING_CODE_GENERATOR_MIPS64_H_ #include "code_generator.h" +#include "dex/type_reference.h" #include "driver/compiler_options.h" #include "nodes.h" #include "parallel_move_resolver.h" -#include "type_reference.h" #include "utils/mips64/assembler_mips64.h" namespace art { diff --git a/compiler/optimizing/code_sinking.cc b/compiler/optimizing/code_sinking.cc index f4760d661f..2e31d35584 100644 --- a/compiler/optimizing/code_sinking.cc +++ b/compiler/optimizing/code_sinking.cc @@ -214,6 +214,11 @@ static HInstruction* FindIdealPosition(HInstruction* instruction, DCHECK(target_block != nullptr); } + // Bail if the instruction can throw and we are about to move into a catch block. + if (instruction->CanThrow() && target_block->GetTryCatchInformation() != nullptr) { + return nullptr; + } + // Find insertion position. No need to filter anymore, as we have found a // target block. HInstruction* insert_pos = nullptr; diff --git a/compiler/optimizing/inliner.cc b/compiler/optimizing/inliner.cc index 4fc7262265..8b10a78212 100644 --- a/compiler/optimizing/inliner.cc +++ b/compiler/optimizing/inliner.cc @@ -147,10 +147,11 @@ void HInliner::Run() { // that this method is actually inlined; // - if a method's name contains the substring "$noinline$", do not // inline that method. - // We limit this to AOT compilation, as the JIT may or may not inline + // We limit the latter to AOT compilation, as the JIT may or may not inline // depending on the state of classes at runtime. - const bool honor_inlining_directives = - IsCompilingWithCoreImage() && Runtime::Current()->IsAotCompiler(); + const bool honor_noinline_directives = IsCompilingWithCoreImage(); + const bool honor_inline_directives = + honor_noinline_directives && Runtime::Current()->IsAotCompiler(); // Keep a copy of all blocks when starting the visit. ArenaVector<HBasicBlock*> blocks = graph_->GetReversePostOrder(); @@ -164,18 +165,19 @@ void HInliner::Run() { HInvoke* call = instruction->AsInvoke(); // As long as the call is not intrinsified, it is worth trying to inline. if (call != nullptr && call->GetIntrinsic() == Intrinsics::kNone) { - if (honor_inlining_directives) { + if (honor_noinline_directives) { // Debugging case: directives in method names control or assert on inlining. std::string callee_name = outer_compilation_unit_.GetDexFile()->PrettyMethod( call->GetDexMethodIndex(), /* with_signature */ false); // Tests prevent inlining by having $noinline$ in their method names. if (callee_name.find("$noinline$") == std::string::npos) { - if (!TryInline(call)) { + if (!TryInline(call) && honor_inline_directives) { bool should_have_inlined = (callee_name.find("$inline$") != std::string::npos); CHECK(!should_have_inlined) << "Could not inline " << callee_name; } } } else { + DCHECK(!honor_inline_directives); // Normal case: try to inline. TryInline(call); } diff --git a/compiler/optimizing/instruction_builder.cc b/compiler/optimizing/instruction_builder.cc index a38e2717cf..c7aef3779d 100644 --- a/compiler/optimizing/instruction_builder.cc +++ b/compiler/optimizing/instruction_builder.cc @@ -20,9 +20,9 @@ #include "base/arena_bit_vector.h" #include "base/bit_vector-inl.h" #include "block_builder.h" -#include "bytecode_utils.h" #include "class_linker.h" #include "data_type-inl.h" +#include "dex/bytecode_utils.h" #include "dex/dex_instruction-inl.h" #include "driver/compiler_driver-inl.h" #include "driver/dex_compilation_unit.h" diff --git a/compiler/optimizing/loop_optimization.cc b/compiler/optimizing/loop_optimization.cc index abd644ae9b..758aca2d0c 100644 --- a/compiler/optimizing/loop_optimization.cc +++ b/compiler/optimizing/loop_optimization.cc @@ -36,10 +36,6 @@ static constexpr bool kEnableVectorization = true; // No loop unrolling factor (just one copy of the loop-body). static constexpr uint32_t kNoUnrollingFactor = 1; -// Values that indicate unbounded end. -static constexpr int64_t kNoLo = std::numeric_limits<int64_t>::min(); -static constexpr int64_t kNoHi = std::numeric_limits<int64_t>::max(); - // // Static helpers. // @@ -338,69 +334,116 @@ static bool IsAddConst(HInstruction* instruction, // Detect clipped [lo, hi] range for nested MIN-MAX operations on a clippee, // such as MIN(hi, MAX(lo, clippee)) for an arbitrary clippee expression. // Example: MIN(10, MIN(20, MAX(0, x))) yields [0, 10] with clippee x. -static bool IsClipped(HInstruction* instruction, - /*out*/ int64_t* lo, - /*out*/ int64_t* hi, - /*out*/ HInstruction** clippee) { - // Recurse into MIN-MAX expressions and 'tighten' the range [lo, hi]. - if (instruction->IsMin() || instruction->IsMax()) { - // Find MIN-MAX(const, ..) or MIN-MAX(.., const). - for (int i = 0; i < 2; i++) { - int64_t c = 0; - if (IsInt64AndGet(instruction->InputAt(i), &c)) { - if (instruction->IsMin()) { - *hi = std::min(*hi, c); - } else { - *lo = std::max(*lo, c); - } - return IsClipped(instruction->InputAt(1 - i), lo, hi, clippee); - } +static HInstruction* FindClippee(HInstruction* instruction, + /*out*/ int64_t* lo, + /*out*/ int64_t* hi) { + // Iterate into MIN(.., c)-MAX(.., c) expressions and 'tighten' the range [lo, hi]. + while (instruction->IsMin() || instruction->IsMax()) { + HBinaryOperation* min_max = instruction->AsBinaryOperation(); + DCHECK(min_max->GetType() == DataType::Type::kInt32 || + min_max->GetType() == DataType::Type::kInt64); + // Process the constant. + HConstant* right = min_max->GetConstantRight(); + if (right == nullptr) { + break; + } else if (instruction->IsMin()) { + *hi = std::min(*hi, Int64FromConstant(right)); + } else { + *lo = std::max(*lo, Int64FromConstant(right)); } - // Recursion fails at any MIN/MAX that does not have one constant - // argument, e.g. MIN(x, y) or MAX(2 * x, f()). - return false; + instruction = min_max->GetLeastConstantLeft(); } - // Recursion ends in any other expression. At this point we record the leaf - // expression as the clippee and report success on the range [lo, hi]. - DCHECK(*clippee == nullptr); - *clippee = instruction; - return true; + // Iteration ends in any other expression (possibly MIN/MAX without constant). + // This leaf expression is the clippee with range [lo, hi]. + return instruction; } -// Accept various saturated addition forms. -static bool IsSaturatedAdd(DataType::Type type, int64_t lo, int64_t hi, bool is_unsigned) { - // MIN(r + s, 255) => SAT_ADD_unsigned - // MAX(MIN(r + s, 127), -128) => SAT_ADD_signed etc. +// Set value range for type (or fail). +static bool CanSetRange(DataType::Type type, + /*out*/ int64_t* uhi, + /*out*/ int64_t* slo, + /*out*/ int64_t* shi) { if (DataType::Size(type) == 1) { - return is_unsigned - ? (lo <= 0 && hi == std::numeric_limits<uint8_t>::max()) - : (lo == std::numeric_limits<int8_t>::min() && - hi == std::numeric_limits<int8_t>::max()); + *uhi = std::numeric_limits<uint8_t>::max(); + *slo = std::numeric_limits<int8_t>::min(); + *shi = std::numeric_limits<int8_t>::max(); + return true; } else if (DataType::Size(type) == 2) { - return is_unsigned - ? (lo <= 0 && hi == std::numeric_limits<uint16_t>::max()) - : (lo == std::numeric_limits<int16_t>::min() && - hi == std::numeric_limits<int16_t>::max()); + *uhi = std::numeric_limits<uint16_t>::max(); + *slo = std::numeric_limits<int16_t>::min(); + *shi = std::numeric_limits<int16_t>::max(); + return true; } return false; } +// Accept various saturated addition forms. +static bool IsSaturatedAdd(HInstruction* clippee, + DataType::Type type, + int64_t lo, + int64_t hi, + bool is_unsigned) { + int64_t ulo = 0, uhi = 0, slo = 0, shi = 0; + if (!CanSetRange(type, &uhi, &slo, &shi)) { + return false; + } + // Tighten the range for signed single clipping on constant. + if (!is_unsigned) { + int64_t c = 0; + HInstruction* notused = nullptr; + if (IsAddConst(clippee, ¬used, &c)) { + // For c in proper range and narrower operand r: + // MIN(r + c, 127) c > 0 + // or MAX(r + c, -128) c < 0 (and possibly redundant bound). + if (0 < c && c <= shi && hi == shi) { + if (lo <= (slo + c)) { + return true; + } + } else if (slo <= c && c < 0 && lo == slo) { + if (hi >= (shi + c)) { + return true; + } + } + } + } + // Detect for narrower operands r and s: + // MIN(r + s, 255) => SAT_ADD_unsigned + // MAX(MIN(r + s, 127), -128) => SAT_ADD_signed. + return is_unsigned ? (lo <= ulo && hi == uhi) : (lo == slo && hi == shi); +} + // Accept various saturated subtraction forms. -static bool IsSaturatedSub(DataType::Type type, int64_t lo, int64_t hi, bool is_unsigned) { - // MAX(r - s, 0) => SAT_SUB_unsigned - // MIN(MAX(r - s, -128), 127) => SAT_ADD_signed etc. - if (DataType::Size(type) == 1) { - return is_unsigned - ? (lo == 0 && hi >= std::numeric_limits<uint8_t>::max()) - : (lo == std::numeric_limits<int8_t>::min() && - hi == std::numeric_limits<int8_t>::max()); - } else if (DataType::Size(type) == 2) { - return is_unsigned - ? (lo == 0 && hi >= std::numeric_limits<uint16_t>::min()) - : (lo == std::numeric_limits<int16_t>::min() && - hi == std::numeric_limits<int16_t>::max()); +static bool IsSaturatedSub(HInstruction* clippee, + DataType::Type type, + int64_t lo, + int64_t hi, + bool is_unsigned) { + int64_t ulo = 0, uhi = 0, slo = 0, shi = 0; + if (!CanSetRange(type, &uhi, &slo, &shi)) { + return false; } - return false; + // Tighten the range for signed single clipping on constant. + if (!is_unsigned) { + int64_t c = 0; + if (IsInt64AndGet(clippee->InputAt(0), /*out*/ &c)) { + // For c in proper range and narrower operand r: + // MIN(c - r, 127) c > 0 + // or MAX(c - r, -128) c < 0 (and possibly redundant bound). + if (0 < c && c <= shi && hi == shi) { + if (lo <= (c - shi)) { + return true; + } + } else if (slo <= c && c < 0 && lo == slo) { + if (hi >= (c - slo)) { + return true; + } + } + } + } + // Detect for narrower operands r and s: + // MAX(r - s, 0) => SAT_SUB_unsigned + // MIN(MAX(r - s, -128), 127) => SAT_ADD_signed. + return is_unsigned ? (lo == ulo && hi >= uhi) : (lo == slo && hi == shi); } // Detect reductions of the following forms, @@ -1896,15 +1939,15 @@ bool HLoopOptimization::VectorizeSaturationIdiom(LoopNode* node, if (HasVectorRestrictions(restrictions, kNoSaturation)) { return false; } - // Search for clipping of a clippee. - int64_t lo = kNoLo; - int64_t hi = kNoHi; - HInstruction* clippee = nullptr; - if (!IsClipped(instruction, &lo, &hi, &clippee)) { + // Restrict type (generalize if one day we generalize allowed MIN/MAX integral types). + if (instruction->GetType() != DataType::Type::kInt32 && + instruction->GetType() != DataType::Type::kInt64) { return false; } - CHECK(clippee != nullptr); // Clipped addition or subtraction? + int64_t lo = std::numeric_limits<int64_t>::min(); + int64_t hi = std::numeric_limits<int64_t>::max(); + HInstruction* clippee = FindClippee(instruction, &lo, &hi); bool is_add = true; if (clippee->IsAdd()) { is_add = true; @@ -1918,8 +1961,8 @@ bool HLoopOptimization::VectorizeSaturationIdiom(LoopNode* node, HInstruction* s = nullptr; bool is_unsigned = false; if (IsNarrowerOperands(clippee->InputAt(0), clippee->InputAt(1), type, &r, &s, &is_unsigned) && - (is_add ? IsSaturatedAdd(type, lo, hi, is_unsigned) - : IsSaturatedSub(type, lo, hi, is_unsigned))) { + (is_add ? IsSaturatedAdd(clippee, type, lo, hi, is_unsigned) + : IsSaturatedSub(clippee, type, lo, hi, is_unsigned))) { DCHECK(r != nullptr); DCHECK(s != nullptr); } else { diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h index cbf748d4fd..a8fcea2097 100644 --- a/compiler/optimizing/nodes.h +++ b/compiler/optimizing/nodes.h @@ -34,12 +34,12 @@ #include "dex/dex_file.h" #include "dex/dex_file_types.h" #include "dex/invoke_type.h" +#include "dex/method_reference.h" #include "entrypoints/quick/quick_entrypoints_enum.h" #include "handle.h" #include "handle_scope.h" #include "intrinsics_enum.h" #include "locations.h" -#include "method_reference.h" #include "mirror/class.h" #include "offsets.h" #include "utils/intrusive_forward_list.h" diff --git a/compiler/optimizing/nodes_vector.h b/compiler/optimizing/nodes_vector.h index 523bca8d25..9b114eb1f7 100644 --- a/compiler/optimizing/nodes_vector.h +++ b/compiler/optimizing/nodes_vector.h @@ -325,7 +325,7 @@ class HVecReplicateScalar FINAL : public HVecUnaryOperation { uint32_t dex_pc) : HVecUnaryOperation( kVecReplicateScalar, allocator, scalar, packed_type, vector_length, dex_pc) { - DCHECK(!scalar->IsVecOperation()); + DCHECK(!ReturnsSIMDValue(scalar)); } // A replicate needs to stay in place, since SIMD registers are not diff --git a/compiler/optimizing/ssa_builder.cc b/compiler/optimizing/ssa_builder.cc index cb384768b7..dd54468217 100644 --- a/compiler/optimizing/ssa_builder.cc +++ b/compiler/optimizing/ssa_builder.cc @@ -16,8 +16,8 @@ #include "ssa_builder.h" -#include "bytecode_utils.h" #include "data_type-inl.h" +#include "dex/bytecode_utils.h" #include "mirror/class-inl.h" #include "nodes.h" #include "reference_type_propagation.h" |