summaryrefslogtreecommitdiff
path: root/compiler/optimizing
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/optimizing')
-rw-r--r--compiler/optimizing/block_builder.cc2
-rw-r--r--compiler/optimizing/code_generator.cc2
-rw-r--r--compiler/optimizing/code_generator.h4
-rw-r--r--compiler/optimizing/code_generator_arm64.h4
-rw-r--r--compiler/optimizing/code_generator_arm_vixl.h4
-rw-r--r--compiler/optimizing/code_generator_mips.h4
-rw-r--r--compiler/optimizing/code_generator_mips64.h2
-rw-r--r--compiler/optimizing/code_sinking.cc5
-rw-r--r--compiler/optimizing/inliner.cc12
-rw-r--r--compiler/optimizing/instruction_builder.cc2
-rw-r--r--compiler/optimizing/loop_optimization.cc169
-rw-r--r--compiler/optimizing/nodes.h2
-rw-r--r--compiler/optimizing/nodes_vector.h2
-rw-r--r--compiler/optimizing/ssa_builder.cc2
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, &notused, &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"