summaryrefslogtreecommitdiff
path: root/compiler/optimizing/nodes.cc
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/optimizing/nodes.cc')
-rw-r--r--compiler/optimizing/nodes.cc141
1 files changed, 83 insertions, 58 deletions
diff --git a/compiler/optimizing/nodes.cc b/compiler/optimizing/nodes.cc
index 3790058879..2cfe5b3ae2 100644
--- a/compiler/optimizing/nodes.cc
+++ b/compiler/optimizing/nodes.cc
@@ -35,7 +35,9 @@
#include "class_root-inl.h"
#include "code_generator.h"
#include "common_dominator.h"
+#include "intrinsic_objects.h"
#include "intrinsics.h"
+#include "intrinsics_list.h"
#include "mirror/class-inl.h"
#include "scoped_thread_state_change-inl.h"
#include "ssa_builder.h"
@@ -254,6 +256,14 @@ GraphAnalysisResult HGraph::BuildDominatorTree() {
return kAnalysisSuccess;
}
+GraphAnalysisResult HGraph::RecomputeDominatorTree() {
+ DCHECK(!HasIrreducibleLoops()) << "Recomputing loop information in graphs with irreducible loops "
+ << "is unsupported, as it could lead to loop header changes";
+ ClearLoopInformation();
+ ClearDominanceInformation();
+ return BuildDominatorTree();
+}
+
void HGraph::ClearDominanceInformation() {
for (HBasicBlock* block : GetActiveBlocks()) {
block->ClearDominanceInformation();
@@ -1488,12 +1498,12 @@ bool HInstructionList::FoundBefore(const HInstruction* instruction1,
const HInstruction* instruction2) const {
DCHECK_EQ(instruction1->GetBlock(), instruction2->GetBlock());
for (HInstructionIterator it(*this); !it.Done(); it.Advance()) {
- if (it.Current() == instruction1) {
- return true;
- }
if (it.Current() == instruction2) {
return false;
}
+ if (it.Current() == instruction1) {
+ return true;
+ }
}
LOG(FATAL) << "Did not find an order between two instructions of the same block.";
UNREACHABLE();
@@ -1815,10 +1825,12 @@ void HGraphVisitor::VisitBasicBlock(HBasicBlock* block) {
}
}
-HConstant* HTypeConversion::TryStaticEvaluation() const {
- HGraph* graph = GetBlock()->GetGraph();
- if (GetInput()->IsIntConstant()) {
- int32_t value = GetInput()->AsIntConstant()->GetValue();
+HConstant* HTypeConversion::TryStaticEvaluation() const { return TryStaticEvaluation(GetInput()); }
+
+HConstant* HTypeConversion::TryStaticEvaluation(HInstruction* input) const {
+ HGraph* graph = input->GetBlock()->GetGraph();
+ if (input->IsIntConstant()) {
+ int32_t value = input->AsIntConstant()->GetValue();
switch (GetResultType()) {
case DataType::Type::kInt8:
return graph->GetIntConstant(static_cast<int8_t>(value), GetDexPc());
@@ -1837,8 +1849,8 @@ HConstant* HTypeConversion::TryStaticEvaluation() const {
default:
return nullptr;
}
- } else if (GetInput()->IsLongConstant()) {
- int64_t value = GetInput()->AsLongConstant()->GetValue();
+ } else if (input->IsLongConstant()) {
+ int64_t value = input->AsLongConstant()->GetValue();
switch (GetResultType()) {
case DataType::Type::kInt8:
return graph->GetIntConstant(static_cast<int8_t>(value), GetDexPc());
@@ -1857,8 +1869,8 @@ HConstant* HTypeConversion::TryStaticEvaluation() const {
default:
return nullptr;
}
- } else if (GetInput()->IsFloatConstant()) {
- float value = GetInput()->AsFloatConstant()->GetValue();
+ } else if (input->IsFloatConstant()) {
+ float value = input->AsFloatConstant()->GetValue();
switch (GetResultType()) {
case DataType::Type::kInt32:
if (std::isnan(value))
@@ -1881,8 +1893,8 @@ HConstant* HTypeConversion::TryStaticEvaluation() const {
default:
return nullptr;
}
- } else if (GetInput()->IsDoubleConstant()) {
- double value = GetInput()->AsDoubleConstant()->GetValue();
+ } else if (input->IsDoubleConstant()) {
+ double value = input->AsDoubleConstant()->GetValue();
switch (GetResultType()) {
case DataType::Type::kInt32:
if (std::isnan(value))
@@ -1909,41 +1921,47 @@ HConstant* HTypeConversion::TryStaticEvaluation() const {
return nullptr;
}
-HConstant* HUnaryOperation::TryStaticEvaluation() const {
- if (GetInput()->IsIntConstant()) {
- return Evaluate(GetInput()->AsIntConstant());
- } else if (GetInput()->IsLongConstant()) {
- return Evaluate(GetInput()->AsLongConstant());
+HConstant* HUnaryOperation::TryStaticEvaluation() const { return TryStaticEvaluation(GetInput()); }
+
+HConstant* HUnaryOperation::TryStaticEvaluation(HInstruction* input) const {
+ if (input->IsIntConstant()) {
+ return Evaluate(input->AsIntConstant());
+ } else if (input->IsLongConstant()) {
+ return Evaluate(input->AsLongConstant());
} else if (kEnableFloatingPointStaticEvaluation) {
- if (GetInput()->IsFloatConstant()) {
- return Evaluate(GetInput()->AsFloatConstant());
- } else if (GetInput()->IsDoubleConstant()) {
- return Evaluate(GetInput()->AsDoubleConstant());
+ if (input->IsFloatConstant()) {
+ return Evaluate(input->AsFloatConstant());
+ } else if (input->IsDoubleConstant()) {
+ return Evaluate(input->AsDoubleConstant());
}
}
return nullptr;
}
HConstant* HBinaryOperation::TryStaticEvaluation() const {
- if (GetLeft()->IsIntConstant() && GetRight()->IsIntConstant()) {
- return Evaluate(GetLeft()->AsIntConstant(), GetRight()->AsIntConstant());
- } else if (GetLeft()->IsLongConstant()) {
- if (GetRight()->IsIntConstant()) {
+ return TryStaticEvaluation(GetLeft(), GetRight());
+}
+
+HConstant* HBinaryOperation::TryStaticEvaluation(HInstruction* left, HInstruction* right) const {
+ if (left->IsIntConstant() && right->IsIntConstant()) {
+ return Evaluate(left->AsIntConstant(), right->AsIntConstant());
+ } else if (left->IsLongConstant()) {
+ if (right->IsIntConstant()) {
// The binop(long, int) case is only valid for shifts and rotations.
DCHECK(IsShl() || IsShr() || IsUShr() || IsRor()) << DebugName();
- return Evaluate(GetLeft()->AsLongConstant(), GetRight()->AsIntConstant());
- } else if (GetRight()->IsLongConstant()) {
- return Evaluate(GetLeft()->AsLongConstant(), GetRight()->AsLongConstant());
+ return Evaluate(left->AsLongConstant(), right->AsIntConstant());
+ } else if (right->IsLongConstant()) {
+ return Evaluate(left->AsLongConstant(), right->AsLongConstant());
}
- } else if (GetLeft()->IsNullConstant() && GetRight()->IsNullConstant()) {
+ } else if (left->IsNullConstant() && right->IsNullConstant()) {
// The binop(null, null) case is only valid for equal and not-equal conditions.
DCHECK(IsEqual() || IsNotEqual()) << DebugName();
- return Evaluate(GetLeft()->AsNullConstant(), GetRight()->AsNullConstant());
+ return Evaluate(left->AsNullConstant(), right->AsNullConstant());
} else if (kEnableFloatingPointStaticEvaluation) {
- if (GetLeft()->IsFloatConstant() && GetRight()->IsFloatConstant()) {
- return Evaluate(GetLeft()->AsFloatConstant(), GetRight()->AsFloatConstant());
- } else if (GetLeft()->IsDoubleConstant() && GetRight()->IsDoubleConstant()) {
- return Evaluate(GetLeft()->AsDoubleConstant(), GetRight()->AsDoubleConstant());
+ if (left->IsFloatConstant() && right->IsFloatConstant()) {
+ return Evaluate(left->AsFloatConstant(), right->AsFloatConstant());
+ } else if (left->IsDoubleConstant() && right->IsDoubleConstant()) {
+ return Evaluate(left->AsDoubleConstant(), right->AsDoubleConstant());
}
}
return nullptr;
@@ -2797,8 +2815,11 @@ HInstruction* HGraph::InlineInto(HGraph* outer_graph, HInvoke* invoke) {
if (HasMonitorOperations()) {
outer_graph->SetHasMonitorOperations(true);
}
- if (HasSIMD()) {
- outer_graph->SetHasSIMD(true);
+ if (HasTraditionalSIMD()) {
+ outer_graph->SetHasTraditionalSIMD(true);
+ }
+ if (HasPredicatedSIMD()) {
+ outer_graph->SetHasPredicatedSIMD(true);
}
if (HasAlwaysThrowingInvokes()) {
outer_graph->SetHasAlwaysThrowingInvokes(true);
@@ -2989,12 +3010,7 @@ HInstruction* HGraph::InlineInto(HGraph* outer_graph, HInvoke* invoke) {
}
}
if (rerun_loop_analysis) {
- DCHECK(!outer_graph->HasIrreducibleLoops())
- << "Recomputing loop information in graphs with irreducible loops "
- << "is unsupported, as it could lead to loop header changes";
- outer_graph->ClearLoopInformation();
- outer_graph->ClearDominanceInformation();
- outer_graph->BuildDominatorTree();
+ outer_graph->RecomputeDominatorTree();
} else if (rerun_dominance) {
outer_graph->ClearDominanceInformation();
outer_graph->ComputeDominanceInformation();
@@ -3026,9 +3042,9 @@ HInstruction* HGraph::InlineInto(HGraph* outer_graph, HInvoke* invoke) {
replacement = outer_graph->GetDoubleConstant(
current->AsDoubleConstant()->GetValue(), current->GetDexPc());
} else if (current->IsParameterValue()) {
- if (kIsDebugBuild
- && invoke->IsInvokeStaticOrDirect()
- && invoke->AsInvokeStaticOrDirect()->IsStaticWithExplicitClinitCheck()) {
+ if (kIsDebugBuild &&
+ invoke->IsInvokeStaticOrDirect() &&
+ invoke->AsInvokeStaticOrDirect()->IsStaticWithExplicitClinitCheck()) {
// Ensure we do not use the last input of `invoke`, as it
// contains a clinit check which is not an actual argument.
size_t last_input_index = invoke->InputCount() - 1;
@@ -3125,6 +3141,8 @@ void HGraph::TransformLoopHeaderForBCE(HBasicBlock* header) {
new_pre_header, old_pre_header, /* replace_if_back_edge= */ false);
}
+// Creates a new two-basic-block loop and inserts it between original loop header and
+// original loop exit; also adjusts dominators, post order and new LoopInformation.
HBasicBlock* HGraph::TransformLoopForVectorization(HBasicBlock* header,
HBasicBlock* body,
HBasicBlock* exit) {
@@ -3346,6 +3364,21 @@ std::ostream& operator<<(std::ostream& os, HInvokeStaticOrDirect::ClinitCheckReq
}
}
+bool HInvokeStaticOrDirect::CanBeNull() const {
+ if (GetType() != DataType::Type::kReference || IsStringInit()) {
+ return false;
+ }
+ switch (GetIntrinsic()) {
+#define DEFINE_BOXED_CASE(name, unused1, unused2, unused3, unused4) \
+ case Intrinsics::k##name##ValueOf: \
+ return false;
+ BOXED_TYPES(DEFINE_BOXED_CASE)
+#undef DEFINE_BOXED_CASE
+ default:
+ return true;
+ }
+}
+
bool HInvokeVirtual::CanDoImplicitNullCheckOn(HInstruction* obj) const {
if (obj != InputAt(0)) {
return false;
@@ -3518,9 +3551,7 @@ std::ostream& operator<<(std::ostream& os, TypeCheckKind rhs) {
static_assert( \
static_cast<uint32_t>(Intrinsics::k ## Name) <= (kAccIntrinsicBits >> CTZ(kAccIntrinsicBits)), \
"Instrinsics enumeration space overflow.");
-#include "intrinsics_list.h"
- INTRINSICS_LIST(CHECK_INTRINSICS_ENUM_VALUES)
-#undef INTRINSICS_LIST
+ ART_INTRINSICS_LIST(CHECK_INTRINSICS_ENUM_VALUES)
#undef CHECK_INTRINSICS_ENUM_VALUES
// Function that returns whether an intrinsic needs an environment or not.
@@ -3531,9 +3562,7 @@ static inline IntrinsicNeedsEnvironment NeedsEnvironmentIntrinsic(Intrinsics i)
#define OPTIMIZING_INTRINSICS(Name, InvokeType, NeedsEnv, SideEffects, Exceptions, ...) \
case Intrinsics::k ## Name: \
return NeedsEnv;
-#include "intrinsics_list.h"
- INTRINSICS_LIST(OPTIMIZING_INTRINSICS)
-#undef INTRINSICS_LIST
+ ART_INTRINSICS_LIST(OPTIMIZING_INTRINSICS)
#undef OPTIMIZING_INTRINSICS
}
return kNeedsEnvironment;
@@ -3547,9 +3576,7 @@ static inline IntrinsicSideEffects GetSideEffectsIntrinsic(Intrinsics i) {
#define OPTIMIZING_INTRINSICS(Name, InvokeType, NeedsEnv, SideEffects, Exceptions, ...) \
case Intrinsics::k ## Name: \
return SideEffects;
-#include "intrinsics_list.h"
- INTRINSICS_LIST(OPTIMIZING_INTRINSICS)
-#undef INTRINSICS_LIST
+ ART_INTRINSICS_LIST(OPTIMIZING_INTRINSICS)
#undef OPTIMIZING_INTRINSICS
}
return kAllSideEffects;
@@ -3563,9 +3590,7 @@ static inline IntrinsicExceptions GetExceptionsIntrinsic(Intrinsics i) {
#define OPTIMIZING_INTRINSICS(Name, InvokeType, NeedsEnv, SideEffects, Exceptions, ...) \
case Intrinsics::k ## Name: \
return Exceptions;
-#include "intrinsics_list.h"
- INTRINSICS_LIST(OPTIMIZING_INTRINSICS)
-#undef INTRINSICS_LIST
+ ART_INTRINSICS_LIST(OPTIMIZING_INTRINSICS)
#undef OPTIMIZING_INTRINSICS
}
return kCanThrow;