summaryrefslogtreecommitdiff
path: root/compiler/optimizing/nodes.h
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/optimizing/nodes.h')
-rw-r--r--compiler/optimizing/nodes.h514
1 files changed, 274 insertions, 240 deletions
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index 28112d176a..0efe8f4335 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -253,7 +253,7 @@ class ReferenceTypeInfo : ValueObject {
bool IsNonPrimitiveArrayClass() const REQUIRES_SHARED(Locks::mutator_lock_) {
DCHECK(IsValid());
- return GetTypeHandle()->IsArrayClass() && !GetTypeHandle()->IsPrimitiveArray();
+ return IsArrayClass() && !GetTypeHandle()->IsPrimitiveArray();
}
bool CanArrayHold(ReferenceTypeInfo rti) const REQUIRES_SHARED(Locks::mutator_lock_) {
@@ -403,7 +403,8 @@ class HGraph : public ArenaObject<kArenaAllocGraph> {
has_bounds_checks_(false),
has_try_catch_(false),
has_monitor_operations_(false),
- has_simd_(false),
+ has_traditional_simd_(false),
+ has_predicated_simd_(false),
has_loops_(false),
has_irreducible_loops_(false),
has_direct_critical_native_call_(false),
@@ -466,6 +467,7 @@ class HGraph : public ArenaObject<kArenaAllocGraph> {
void ClearLoopInformation();
void FindBackEdges(ArenaBitVector* visited);
GraphAnalysisResult BuildDominatorTree();
+ GraphAnalysisResult RecomputeDominatorTree();
void SimplifyCFG();
void SimplifyCatchBlocks();
@@ -708,8 +710,13 @@ class HGraph : public ArenaObject<kArenaAllocGraph> {
bool HasMonitorOperations() const { return has_monitor_operations_; }
void SetHasMonitorOperations(bool value) { has_monitor_operations_ = value; }
- bool HasSIMD() const { return has_simd_; }
- void SetHasSIMD(bool value) { has_simd_ = value; }
+ bool HasTraditionalSIMD() { return has_traditional_simd_; }
+ void SetHasTraditionalSIMD(bool value) { has_traditional_simd_ = value; }
+
+ bool HasPredicatedSIMD() { return has_predicated_simd_; }
+ void SetHasPredicatedSIMD(bool value) { has_predicated_simd_ = value; }
+
+ bool HasSIMD() const { return has_traditional_simd_ || has_predicated_simd_; }
bool HasLoops() const { return has_loops_; }
void SetHasLoops(bool value) { has_loops_ = value; }
@@ -822,10 +829,11 @@ class HGraph : public ArenaObject<kArenaAllocGraph> {
// DexRegisterMap to be present to allow deadlock analysis for non-debuggable code.
bool has_monitor_operations_;
- // Flag whether SIMD instructions appear in the graph. If true, the
- // code generators may have to be more careful spilling the wider
+ // Flags whether SIMD (traditional or predicated) instructions appear in the graph.
+ // If either is true, the code generators may have to be more careful spilling the wider
// contents of SIMD registers.
- bool has_simd_;
+ bool has_traditional_simd_;
+ bool has_predicated_simd_;
// Flag whether there are any loops in the graph. We can skip loop
// optimization if it's false.
@@ -1544,7 +1552,6 @@ class HLoopInformationOutwardIterator : public ValueObject {
M(If, Instruction) \
M(InstanceFieldGet, Instruction) \
M(InstanceFieldSet, Instruction) \
- M(PredicatedInstanceFieldGet, Instruction) \
M(InstanceOf, Instruction) \
M(IntConstant, Constant) \
M(IntermediateAddress, Instruction) \
@@ -1636,7 +1643,9 @@ class HLoopInformationOutwardIterator : public ValueObject {
M(VecStore, VecMemoryOperation) \
M(VecPredSetAll, VecPredSetOperation) \
M(VecPredWhile, VecPredSetOperation) \
- M(VecPredCondition, VecOperation) \
+ M(VecPredToBoolean, VecOperation) \
+ M(VecCondition, VecPredSetOperation) \
+ M(VecPredNot, VecPredSetOperation) \
#define FOR_EACH_CONCRETE_INSTRUCTION_COMMON(M) \
FOR_EACH_CONCRETE_INSTRUCTION_SCALAR_COMMON(M) \
@@ -1659,6 +1668,8 @@ class HLoopInformationOutwardIterator : public ValueObject {
#define FOR_EACH_CONCRETE_INSTRUCTION_ARM64(M)
+#define FOR_EACH_CONCRETE_INSTRUCTION_RISCV64(M)
+
#ifndef ART_ENABLE_CODEGEN_x86
#define FOR_EACH_CONCRETE_INSTRUCTION_X86(M)
#else
@@ -1715,7 +1726,7 @@ FOR_EACH_INSTRUCTION(FORWARD_DECLARATION)
const char* DebugName() const override { return #type; } \
HInstruction* Clone(ArenaAllocator* arena) const override { \
DCHECK(IsClonable()); \
- return new (arena) H##type(*this->As##type()); \
+ return new (arena) H##type(*this); \
} \
void Accept(HGraphVisitor* visitor) override
@@ -2062,12 +2073,12 @@ class HEnvironment : public ArenaObject<kArenaAllocEnvironment> {
ArtMethod* method,
uint32_t dex_pc,
HInstruction* holder)
- : vregs_(number_of_vregs, allocator->Adapter(kArenaAllocEnvironmentVRegs)),
- locations_(allocator->Adapter(kArenaAllocEnvironmentLocations)),
- parent_(nullptr),
- method_(method),
- dex_pc_(dex_pc),
- holder_(holder) {
+ : vregs_(number_of_vregs, allocator->Adapter(kArenaAllocEnvironmentVRegs)),
+ locations_(allocator->Adapter(kArenaAllocEnvironmentLocations)),
+ parent_(nullptr),
+ method_(method),
+ dex_pc_(dex_pc),
+ holder_(holder) {
}
ALWAYS_INLINE HEnvironment(ArenaAllocator* allocator,
@@ -2183,9 +2194,14 @@ class HEnvironment : public ArenaObject<kArenaAllocEnvironment> {
std::ostream& operator<<(std::ostream& os, const HInstruction& rhs);
// Iterates over the Environments
-class HEnvironmentIterator : public ValueObject,
- public std::iterator<std::forward_iterator_tag, HEnvironment*> {
+class HEnvironmentIterator : public ValueObject {
public:
+ using iterator_category = std::forward_iterator_tag;
+ using value_type = HEnvironment*;
+ using difference_type = ptrdiff_t;
+ using pointer = void;
+ using reference = void;
+
explicit HEnvironmentIterator(HEnvironment* cur) : cur_(cur) {}
HEnvironment* operator*() const {
@@ -2355,9 +2371,7 @@ class HInstruction : public ArenaObject<kArenaAllocInstruction> {
return true;
}
- virtual bool CanDoImplicitNullCheckOn(HInstruction* obj ATTRIBUTE_UNUSED) const {
- return false;
- }
+ virtual bool CanDoImplicitNullCheckOn([[maybe_unused]] HInstruction* obj) const { return false; }
// If this instruction will do an implicit null check, return the `HNullCheck` associated
// with it. Otherwise return null.
@@ -2553,7 +2567,9 @@ class HInstruction : public ArenaObject<kArenaAllocInstruction> {
#define INSTRUCTION_TYPE_CAST(type, super) \
const H##type* As##type() const; \
- H##type* As##type();
+ H##type* As##type(); \
+ const H##type* As##type##OrNull() const; \
+ H##type* As##type##OrNull();
FOR_EACH_INSTRUCTION(INSTRUCTION_TYPE_CAST)
#undef INSTRUCTION_TYPE_CAST
@@ -2568,7 +2584,7 @@ class HInstruction : public ArenaObject<kArenaAllocInstruction> {
//
// Note: HEnvironment and some other fields are not copied and are set to default values, see
// 'explicit HInstruction(const HInstruction& other)' for details.
- virtual HInstruction* Clone(ArenaAllocator* arena ATTRIBUTE_UNUSED) const {
+ virtual HInstruction* Clone([[maybe_unused]] ArenaAllocator* arena) const {
LOG(FATAL) << "Cloning is not implemented for the instruction " <<
DebugName() << " " << GetId();
UNREACHABLE();
@@ -2596,7 +2612,7 @@ class HInstruction : public ArenaObject<kArenaAllocInstruction> {
// Returns whether any data encoded in the two instructions is equal.
// This method does not look at the inputs. Both instructions must be
// of the same type, otherwise the method has undefined behavior.
- virtual bool InstructionDataEquals(const HInstruction* other ATTRIBUTE_UNUSED) const {
+ virtual bool InstructionDataEquals([[maybe_unused]] const HInstruction* other) const {
return false;
}
@@ -2729,7 +2745,7 @@ class HInstruction : public ArenaObject<kArenaAllocInstruction> {
private:
using InstructionKindField =
- BitField<InstructionKind, kFieldInstructionKind, kFieldInstructionKindSize>;
+ BitField<InstructionKind, kFieldInstructionKind, kFieldInstructionKindSize>;
void FixUpUserRecordsAfterUseInsertion(HUseList<HInstruction*>::iterator fixup_end) {
auto before_use_node = uses_.before_begin();
@@ -2904,9 +2920,14 @@ class HBackwardInstructionIterator : public ValueObject {
};
template <typename InnerIter>
-struct HSTLInstructionIterator : public ValueObject,
- public std::iterator<std::forward_iterator_tag, HInstruction*> {
+struct HSTLInstructionIterator : public ValueObject {
public:
+ using iterator_category = std::forward_iterator_tag;
+ using value_type = HInstruction*;
+ using difference_type = ptrdiff_t;
+ using pointer = void;
+ using reference = void;
+
static_assert(std::is_same_v<InnerIter, HBackwardInstructionIterator> ||
std::is_same_v<InnerIter, HInstructionIterator> ||
std::is_same_v<InnerIter, HInstructionIteratorHandleChanges>,
@@ -3164,7 +3185,7 @@ class HPhi final : public HVariableInputSizeInstruction {
bool IsVRegEquivalentOf(const HInstruction* other) const {
return other != nullptr
&& other->IsPhi()
- && other->AsPhi()->GetBlock() == GetBlock()
+ && other->GetBlock() == GetBlock()
&& other->AsPhi()->GetRegNumber() == GetRegNumber();
}
@@ -3270,7 +3291,7 @@ class HConstant : public HExpression<0> {
class HNullConstant final : public HConstant {
public:
- bool InstructionDataEquals(const HInstruction* other ATTRIBUTE_UNUSED) const override {
+ bool InstructionDataEquals([[maybe_unused]] const HInstruction* other) const override {
return true;
}
@@ -3497,7 +3518,9 @@ class HDoubleConstant final : public HConstant {
class HIf final : public HExpression<1> {
public:
explicit HIf(HInstruction* input, uint32_t dex_pc = kNoDexPc)
- : HExpression(kIf, SideEffects::None(), dex_pc) {
+ : HExpression(kIf, SideEffects::None(), dex_pc),
+ true_count_(std::numeric_limits<uint16_t>::max()),
+ false_count_(std::numeric_limits<uint16_t>::max()) {
SetRawInputAt(0, input);
}
@@ -3512,10 +3535,20 @@ class HIf final : public HExpression<1> {
return GetBlock()->GetSuccessors()[1];
}
+ void SetTrueCount(uint16_t count) { true_count_ = count; }
+ uint16_t GetTrueCount() const { return true_count_; }
+
+ void SetFalseCount(uint16_t count) { false_count_ = count; }
+ uint16_t GetFalseCount() const { return false_count_; }
+
DECLARE_INSTRUCTION(If);
protected:
DEFAULT_COPY_CONSTRUCTOR(If);
+
+ private:
+ uint16_t true_count_;
+ uint16_t false_count_;
};
@@ -3639,7 +3672,8 @@ class HDeoptimize final : public HVariableInputSizeInstruction {
bool CanBeMoved() const override { return GetPackedFlag<kFieldCanBeMoved>(); }
bool InstructionDataEquals(const HInstruction* other) const override {
- return (other->CanBeMoved() == CanBeMoved()) && (other->AsDeoptimize()->GetKind() == GetKind());
+ return (other->CanBeMoved() == CanBeMoved()) &&
+ (other->AsDeoptimize()->GetDeoptimizationKind() == GetDeoptimizationKind());
}
bool NeedsEnvironment() const override { return true; }
@@ -3827,7 +3861,7 @@ class HUnaryOperation : public HExpression<1> {
DataType::Type GetResultType() const { return GetType(); }
bool CanBeMoved() const override { return true; }
- bool InstructionDataEquals(const HInstruction* other ATTRIBUTE_UNUSED) const override {
+ bool InstructionDataEquals([[maybe_unused]] const HInstruction* other) const override {
return true;
}
@@ -3836,6 +3870,9 @@ class HUnaryOperation : public HExpression<1> {
// be evaluated as a constant, return null.
HConstant* TryStaticEvaluation() const;
+ // Same but for `input` instead of GetInput().
+ HConstant* TryStaticEvaluation(HInstruction* input) const;
+
// Apply this operation to `x`.
virtual HConstant* Evaluate(HIntConstant* x) const = 0;
virtual HConstant* Evaluate(HLongConstant* x) const = 0;
@@ -3903,7 +3940,7 @@ class HBinaryOperation : public HExpression<2> {
}
bool CanBeMoved() const override { return true; }
- bool InstructionDataEquals(const HInstruction* other ATTRIBUTE_UNUSED) const override {
+ bool InstructionDataEquals([[maybe_unused]] const HInstruction* other) const override {
return true;
}
@@ -3912,16 +3949,19 @@ class HBinaryOperation : public HExpression<2> {
// be evaluated as a constant, return null.
HConstant* TryStaticEvaluation() const;
+ // Same but for `left` and `right` instead of GetLeft() and GetRight().
+ HConstant* TryStaticEvaluation(HInstruction* left, HInstruction* right) const;
+
// Apply this operation to `x` and `y`.
- virtual HConstant* Evaluate(HNullConstant* x ATTRIBUTE_UNUSED,
- HNullConstant* y ATTRIBUTE_UNUSED) const {
+ virtual HConstant* Evaluate([[maybe_unused]] HNullConstant* x,
+ [[maybe_unused]] HNullConstant* y) const {
LOG(FATAL) << DebugName() << " is not defined for the (null, null) case.";
UNREACHABLE();
}
virtual HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const = 0;
virtual HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const = 0;
- virtual HConstant* Evaluate(HLongConstant* x ATTRIBUTE_UNUSED,
- HIntConstant* y ATTRIBUTE_UNUSED) const {
+ virtual HConstant* Evaluate([[maybe_unused]] HLongConstant* x,
+ [[maybe_unused]] HIntConstant* y) const {
LOG(FATAL) << DebugName() << " is not defined for the (long, int) case.";
UNREACHABLE();
}
@@ -4049,8 +4089,8 @@ class HEqual final : public HCondition {
bool IsCommutative() const override { return true; }
- HConstant* Evaluate(HNullConstant* x ATTRIBUTE_UNUSED,
- HNullConstant* y ATTRIBUTE_UNUSED) const override {
+ HConstant* Evaluate([[maybe_unused]] HNullConstant* x,
+ [[maybe_unused]] HNullConstant* y) const override {
return MakeConstantCondition(true, GetDexPc());
}
HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const override {
@@ -4096,8 +4136,8 @@ class HNotEqual final : public HCondition {
bool IsCommutative() const override { return true; }
- HConstant* Evaluate(HNullConstant* x ATTRIBUTE_UNUSED,
- HNullConstant* y ATTRIBUTE_UNUSED) const override {
+ HConstant* Evaluate([[maybe_unused]] HNullConstant* x,
+ [[maybe_unused]] HNullConstant* y) const override {
return MakeConstantCondition(false, GetDexPc());
}
HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const override {
@@ -4303,13 +4343,13 @@ class HBelow final : public HCondition {
HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const override {
return MakeConstantCondition(Compute(x->GetValue(), y->GetValue()), GetDexPc());
}
- HConstant* Evaluate(HFloatConstant* x ATTRIBUTE_UNUSED,
- HFloatConstant* y ATTRIBUTE_UNUSED) const override {
+ HConstant* Evaluate([[maybe_unused]] HFloatConstant* x,
+ [[maybe_unused]] HFloatConstant* y) const override {
LOG(FATAL) << DebugName() << " is not defined for float values";
UNREACHABLE();
}
- HConstant* Evaluate(HDoubleConstant* x ATTRIBUTE_UNUSED,
- HDoubleConstant* y ATTRIBUTE_UNUSED) const override {
+ HConstant* Evaluate([[maybe_unused]] HDoubleConstant* x,
+ [[maybe_unused]] HDoubleConstant* y) const override {
LOG(FATAL) << DebugName() << " is not defined for double values";
UNREACHABLE();
}
@@ -4345,13 +4385,13 @@ class HBelowOrEqual final : public HCondition {
HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const override {
return MakeConstantCondition(Compute(x->GetValue(), y->GetValue()), GetDexPc());
}
- HConstant* Evaluate(HFloatConstant* x ATTRIBUTE_UNUSED,
- HFloatConstant* y ATTRIBUTE_UNUSED) const override {
+ HConstant* Evaluate([[maybe_unused]] HFloatConstant* x,
+ [[maybe_unused]] HFloatConstant* y) const override {
LOG(FATAL) << DebugName() << " is not defined for float values";
UNREACHABLE();
}
- HConstant* Evaluate(HDoubleConstant* x ATTRIBUTE_UNUSED,
- HDoubleConstant* y ATTRIBUTE_UNUSED) const override {
+ HConstant* Evaluate([[maybe_unused]] HDoubleConstant* x,
+ [[maybe_unused]] HDoubleConstant* y) const override {
LOG(FATAL) << DebugName() << " is not defined for double values";
UNREACHABLE();
}
@@ -4387,13 +4427,13 @@ class HAbove final : public HCondition {
HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const override {
return MakeConstantCondition(Compute(x->GetValue(), y->GetValue()), GetDexPc());
}
- HConstant* Evaluate(HFloatConstant* x ATTRIBUTE_UNUSED,
- HFloatConstant* y ATTRIBUTE_UNUSED) const override {
+ HConstant* Evaluate([[maybe_unused]] HFloatConstant* x,
+ [[maybe_unused]] HFloatConstant* y) const override {
LOG(FATAL) << DebugName() << " is not defined for float values";
UNREACHABLE();
}
- HConstant* Evaluate(HDoubleConstant* x ATTRIBUTE_UNUSED,
- HDoubleConstant* y ATTRIBUTE_UNUSED) const override {
+ HConstant* Evaluate([[maybe_unused]] HDoubleConstant* x,
+ [[maybe_unused]] HDoubleConstant* y) const override {
LOG(FATAL) << DebugName() << " is not defined for double values";
UNREACHABLE();
}
@@ -4429,13 +4469,13 @@ class HAboveOrEqual final : public HCondition {
HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const override {
return MakeConstantCondition(Compute(x->GetValue(), y->GetValue()), GetDexPc());
}
- HConstant* Evaluate(HFloatConstant* x ATTRIBUTE_UNUSED,
- HFloatConstant* y ATTRIBUTE_UNUSED) const override {
+ HConstant* Evaluate([[maybe_unused]] HFloatConstant* x,
+ [[maybe_unused]] HFloatConstant* y) const override {
LOG(FATAL) << DebugName() << " is not defined for float values";
UNREACHABLE();
}
- HConstant* Evaluate(HDoubleConstant* x ATTRIBUTE_UNUSED,
- HDoubleConstant* y ATTRIBUTE_UNUSED) const override {
+ HConstant* Evaluate([[maybe_unused]] HDoubleConstant* x,
+ [[maybe_unused]] HDoubleConstant* y) const override {
LOG(FATAL) << DebugName() << " is not defined for double values";
UNREACHABLE();
}
@@ -4522,7 +4562,7 @@ class HCompare final : public HBinaryOperation {
return GetBias() == ComparisonBias::kGtBias;
}
- static SideEffects SideEffectsForArchRuntimeCalls(DataType::Type type ATTRIBUTE_UNUSED) {
+ static SideEffects SideEffectsForArchRuntimeCalls([[maybe_unused]] DataType::Type type) {
// Comparisons do not require a runtime call in any back end.
return SideEffects::None();
}
@@ -4859,8 +4899,7 @@ class HInvokePolymorphic final : public HInvoke {
// to pass intrinsic information to the HInvokePolymorphic node.
ArtMethod* resolved_method,
MethodReference resolved_method_reference,
- dex::ProtoIndex proto_idx,
- bool enable_intrinsic_opt)
+ dex::ProtoIndex proto_idx)
: HInvoke(kInvokePolymorphic,
allocator,
number_of_arguments,
@@ -4871,9 +4910,8 @@ class HInvokePolymorphic final : public HInvoke {
resolved_method,
resolved_method_reference,
kPolymorphic,
- enable_intrinsic_opt),
- proto_idx_(proto_idx) {
- }
+ /* enable_intrinsic_opt= */ true),
+ proto_idx_(proto_idx) {}
bool IsClonable() const override { return true; }
@@ -5015,15 +5053,13 @@ class HInvokeStaticOrDirect final : public HInvoke {
return input_records;
}
- bool CanDoImplicitNullCheckOn(HInstruction* obj ATTRIBUTE_UNUSED) const override {
+ bool CanDoImplicitNullCheckOn([[maybe_unused]] HInstruction* obj) const override {
// We do not access the method via object reference, so we cannot do an implicit null check.
// TODO: for intrinsics we can generate implicit null checks.
return false;
}
- bool CanBeNull() const override {
- return GetType() == DataType::Type::kReference && !IsStringInit();
- }
+ bool CanBeNull() const override;
MethodLoadKind GetMethodLoadKind() const { return dispatch_info_.method_load_kind; }
CodePtrLocation GetCodePtrLocation() const {
@@ -5599,10 +5635,14 @@ class HMin final : public HBinaryOperation {
ComputeIntegral(x->GetValue(), y->GetValue()), GetDexPc());
}
// TODO: Evaluation for floating-point values.
- HConstant* Evaluate(HFloatConstant* x ATTRIBUTE_UNUSED,
- HFloatConstant* y ATTRIBUTE_UNUSED) const override { return nullptr; }
- HConstant* Evaluate(HDoubleConstant* x ATTRIBUTE_UNUSED,
- HDoubleConstant* y ATTRIBUTE_UNUSED) const override { return nullptr; }
+ HConstant* Evaluate([[maybe_unused]] HFloatConstant* x,
+ [[maybe_unused]] HFloatConstant* y) const override {
+ return nullptr;
+ }
+ HConstant* Evaluate([[maybe_unused]] HDoubleConstant* x,
+ [[maybe_unused]] HDoubleConstant* y) const override {
+ return nullptr;
+ }
DECLARE_INSTRUCTION(Min);
@@ -5634,10 +5674,14 @@ class HMax final : public HBinaryOperation {
ComputeIntegral(x->GetValue(), y->GetValue()), GetDexPc());
}
// TODO: Evaluation for floating-point values.
- HConstant* Evaluate(HFloatConstant* x ATTRIBUTE_UNUSED,
- HFloatConstant* y ATTRIBUTE_UNUSED) const override { return nullptr; }
- HConstant* Evaluate(HDoubleConstant* x ATTRIBUTE_UNUSED,
- HDoubleConstant* y ATTRIBUTE_UNUSED) const override { return nullptr; }
+ HConstant* Evaluate([[maybe_unused]] HFloatConstant* x,
+ [[maybe_unused]] HFloatConstant* y) const override {
+ return nullptr;
+ }
+ HConstant* Evaluate([[maybe_unused]] HDoubleConstant* x,
+ [[maybe_unused]] HDoubleConstant* y) const override {
+ return nullptr;
+ }
DECLARE_INSTRUCTION(Max);
@@ -5699,7 +5743,7 @@ class HDivZeroCheck final : public HExpression<1> {
bool IsClonable() const override { return true; }
bool CanBeMoved() const override { return true; }
- bool InstructionDataEquals(const HInstruction* other ATTRIBUTE_UNUSED) const override {
+ bool InstructionDataEquals([[maybe_unused]] const HInstruction* other) const override {
return true;
}
@@ -5736,18 +5780,18 @@ class HShl final : public HBinaryOperation {
return GetBlock()->GetGraph()->GetLongConstant(
Compute(value->GetValue(), distance->GetValue(), kMaxLongShiftDistance), GetDexPc());
}
- HConstant* Evaluate(HLongConstant* value ATTRIBUTE_UNUSED,
- HLongConstant* distance ATTRIBUTE_UNUSED) const override {
+ HConstant* Evaluate([[maybe_unused]] HLongConstant* value,
+ [[maybe_unused]] HLongConstant* distance) const override {
LOG(FATAL) << DebugName() << " is not defined for the (long, long) case.";
UNREACHABLE();
}
- HConstant* Evaluate(HFloatConstant* value ATTRIBUTE_UNUSED,
- HFloatConstant* distance ATTRIBUTE_UNUSED) const override {
+ HConstant* Evaluate([[maybe_unused]] HFloatConstant* value,
+ [[maybe_unused]] HFloatConstant* distance) const override {
LOG(FATAL) << DebugName() << " is not defined for float values";
UNREACHABLE();
}
- HConstant* Evaluate(HDoubleConstant* value ATTRIBUTE_UNUSED,
- HDoubleConstant* distance ATTRIBUTE_UNUSED) const override {
+ HConstant* Evaluate([[maybe_unused]] HDoubleConstant* value,
+ [[maybe_unused]] HDoubleConstant* distance) const override {
LOG(FATAL) << DebugName() << " is not defined for double values";
UNREACHABLE();
}
@@ -5782,18 +5826,18 @@ class HShr final : public HBinaryOperation {
return GetBlock()->GetGraph()->GetLongConstant(
Compute(value->GetValue(), distance->GetValue(), kMaxLongShiftDistance), GetDexPc());
}
- HConstant* Evaluate(HLongConstant* value ATTRIBUTE_UNUSED,
- HLongConstant* distance ATTRIBUTE_UNUSED) const override {
+ HConstant* Evaluate([[maybe_unused]] HLongConstant* value,
+ [[maybe_unused]] HLongConstant* distance) const override {
LOG(FATAL) << DebugName() << " is not defined for the (long, long) case.";
UNREACHABLE();
}
- HConstant* Evaluate(HFloatConstant* value ATTRIBUTE_UNUSED,
- HFloatConstant* distance ATTRIBUTE_UNUSED) const override {
+ HConstant* Evaluate([[maybe_unused]] HFloatConstant* value,
+ [[maybe_unused]] HFloatConstant* distance) const override {
LOG(FATAL) << DebugName() << " is not defined for float values";
UNREACHABLE();
}
- HConstant* Evaluate(HDoubleConstant* value ATTRIBUTE_UNUSED,
- HDoubleConstant* distance ATTRIBUTE_UNUSED) const override {
+ HConstant* Evaluate([[maybe_unused]] HDoubleConstant* value,
+ [[maybe_unused]] HDoubleConstant* distance) const override {
LOG(FATAL) << DebugName() << " is not defined for double values";
UNREACHABLE();
}
@@ -5830,18 +5874,18 @@ class HUShr final : public HBinaryOperation {
return GetBlock()->GetGraph()->GetLongConstant(
Compute(value->GetValue(), distance->GetValue(), kMaxLongShiftDistance), GetDexPc());
}
- HConstant* Evaluate(HLongConstant* value ATTRIBUTE_UNUSED,
- HLongConstant* distance ATTRIBUTE_UNUSED) const override {
+ HConstant* Evaluate([[maybe_unused]] HLongConstant* value,
+ [[maybe_unused]] HLongConstant* distance) const override {
LOG(FATAL) << DebugName() << " is not defined for the (long, long) case.";
UNREACHABLE();
}
- HConstant* Evaluate(HFloatConstant* value ATTRIBUTE_UNUSED,
- HFloatConstant* distance ATTRIBUTE_UNUSED) const override {
+ HConstant* Evaluate([[maybe_unused]] HFloatConstant* value,
+ [[maybe_unused]] HFloatConstant* distance) const override {
LOG(FATAL) << DebugName() << " is not defined for float values";
UNREACHABLE();
}
- HConstant* Evaluate(HDoubleConstant* value ATTRIBUTE_UNUSED,
- HDoubleConstant* distance ATTRIBUTE_UNUSED) const override {
+ HConstant* Evaluate([[maybe_unused]] HDoubleConstant* value,
+ [[maybe_unused]] HDoubleConstant* distance) const override {
LOG(FATAL) << DebugName() << " is not defined for double values";
UNREACHABLE();
}
@@ -5873,13 +5917,13 @@ class HAnd final : public HBinaryOperation {
return GetBlock()->GetGraph()->GetLongConstant(
Compute(x->GetValue(), y->GetValue()), GetDexPc());
}
- HConstant* Evaluate(HFloatConstant* x ATTRIBUTE_UNUSED,
- HFloatConstant* y ATTRIBUTE_UNUSED) const override {
+ HConstant* Evaluate([[maybe_unused]] HFloatConstant* x,
+ [[maybe_unused]] HFloatConstant* y) const override {
LOG(FATAL) << DebugName() << " is not defined for float values";
UNREACHABLE();
}
- HConstant* Evaluate(HDoubleConstant* x ATTRIBUTE_UNUSED,
- HDoubleConstant* y ATTRIBUTE_UNUSED) const override {
+ HConstant* Evaluate([[maybe_unused]] HDoubleConstant* x,
+ [[maybe_unused]] HDoubleConstant* y) const override {
LOG(FATAL) << DebugName() << " is not defined for double values";
UNREACHABLE();
}
@@ -5911,13 +5955,13 @@ class HOr final : public HBinaryOperation {
return GetBlock()->GetGraph()->GetLongConstant(
Compute(x->GetValue(), y->GetValue()), GetDexPc());
}
- HConstant* Evaluate(HFloatConstant* x ATTRIBUTE_UNUSED,
- HFloatConstant* y ATTRIBUTE_UNUSED) const override {
+ HConstant* Evaluate([[maybe_unused]] HFloatConstant* x,
+ [[maybe_unused]] HFloatConstant* y) const override {
LOG(FATAL) << DebugName() << " is not defined for float values";
UNREACHABLE();
}
- HConstant* Evaluate(HDoubleConstant* x ATTRIBUTE_UNUSED,
- HDoubleConstant* y ATTRIBUTE_UNUSED) const override {
+ HConstant* Evaluate([[maybe_unused]] HDoubleConstant* x,
+ [[maybe_unused]] HDoubleConstant* y) const override {
LOG(FATAL) << DebugName() << " is not defined for double values";
UNREACHABLE();
}
@@ -5949,13 +5993,13 @@ class HXor final : public HBinaryOperation {
return GetBlock()->GetGraph()->GetLongConstant(
Compute(x->GetValue(), y->GetValue()), GetDexPc());
}
- HConstant* Evaluate(HFloatConstant* x ATTRIBUTE_UNUSED,
- HFloatConstant* y ATTRIBUTE_UNUSED) const override {
+ HConstant* Evaluate([[maybe_unused]] HFloatConstant* x,
+ [[maybe_unused]] HFloatConstant* y) const override {
LOG(FATAL) << DebugName() << " is not defined for float values";
UNREACHABLE();
}
- HConstant* Evaluate(HDoubleConstant* x ATTRIBUTE_UNUSED,
- HDoubleConstant* y ATTRIBUTE_UNUSED) const override {
+ HConstant* Evaluate([[maybe_unused]] HDoubleConstant* x,
+ [[maybe_unused]] HDoubleConstant* y) const override {
LOG(FATAL) << DebugName() << " is not defined for double values";
UNREACHABLE();
}
@@ -5993,18 +6037,18 @@ class HRor final : public HBinaryOperation {
return GetBlock()->GetGraph()->GetLongConstant(
Compute(value->GetValue(), distance->GetValue(), kMaxLongShiftDistance), GetDexPc());
}
- HConstant* Evaluate(HLongConstant* value ATTRIBUTE_UNUSED,
- HLongConstant* distance ATTRIBUTE_UNUSED) const override {
+ HConstant* Evaluate([[maybe_unused]] HLongConstant* value,
+ [[maybe_unused]] HLongConstant* distance) const override {
LOG(FATAL) << DebugName() << " is not defined for the (long, long) case.";
UNREACHABLE();
}
- HConstant* Evaluate(HFloatConstant* value ATTRIBUTE_UNUSED,
- HFloatConstant* distance ATTRIBUTE_UNUSED) const override {
+ HConstant* Evaluate([[maybe_unused]] HFloatConstant* value,
+ [[maybe_unused]] HFloatConstant* distance) const override {
LOG(FATAL) << DebugName() << " is not defined for float values";
UNREACHABLE();
}
- HConstant* Evaluate(HDoubleConstant* value ATTRIBUTE_UNUSED,
- HDoubleConstant* distance ATTRIBUTE_UNUSED) const override {
+ HConstant* Evaluate([[maybe_unused]] HDoubleConstant* value,
+ [[maybe_unused]] HDoubleConstant* distance) const override {
LOG(FATAL) << DebugName() << " is not defined for double values";
UNREACHABLE();
}
@@ -6067,7 +6111,7 @@ class HNot final : public HUnaryOperation {
}
bool CanBeMoved() const override { return true; }
- bool InstructionDataEquals(const HInstruction* other ATTRIBUTE_UNUSED) const override {
+ bool InstructionDataEquals([[maybe_unused]] const HInstruction* other) const override {
return true;
}
@@ -6079,11 +6123,11 @@ class HNot final : public HUnaryOperation {
HConstant* Evaluate(HLongConstant* x) const override {
return GetBlock()->GetGraph()->GetLongConstant(Compute(x->GetValue()), GetDexPc());
}
- HConstant* Evaluate(HFloatConstant* x ATTRIBUTE_UNUSED) const override {
+ HConstant* Evaluate([[maybe_unused]] HFloatConstant* x) const override {
LOG(FATAL) << DebugName() << " is not defined for float values";
UNREACHABLE();
}
- HConstant* Evaluate(HDoubleConstant* x ATTRIBUTE_UNUSED) const override {
+ HConstant* Evaluate([[maybe_unused]] HDoubleConstant* x) const override {
LOG(FATAL) << DebugName() << " is not defined for double values";
UNREACHABLE();
}
@@ -6101,7 +6145,7 @@ class HBooleanNot final : public HUnaryOperation {
}
bool CanBeMoved() const override { return true; }
- bool InstructionDataEquals(const HInstruction* other ATTRIBUTE_UNUSED) const override {
+ bool InstructionDataEquals([[maybe_unused]] const HInstruction* other) const override {
return true;
}
@@ -6113,15 +6157,15 @@ class HBooleanNot final : public HUnaryOperation {
HConstant* Evaluate(HIntConstant* x) const override {
return GetBlock()->GetGraph()->GetIntConstant(Compute(x->GetValue()), GetDexPc());
}
- HConstant* Evaluate(HLongConstant* x ATTRIBUTE_UNUSED) const override {
+ HConstant* Evaluate([[maybe_unused]] HLongConstant* x) const override {
LOG(FATAL) << DebugName() << " is not defined for long values";
UNREACHABLE();
}
- HConstant* Evaluate(HFloatConstant* x ATTRIBUTE_UNUSED) const override {
+ HConstant* Evaluate([[maybe_unused]] HFloatConstant* x) const override {
LOG(FATAL) << DebugName() << " is not defined for float values";
UNREACHABLE();
}
- HConstant* Evaluate(HDoubleConstant* x ATTRIBUTE_UNUSED) const override {
+ HConstant* Evaluate([[maybe_unused]] HDoubleConstant* x) const override {
LOG(FATAL) << DebugName() << " is not defined for double values";
UNREACHABLE();
}
@@ -6148,7 +6192,7 @@ class HTypeConversion final : public HExpression<1> {
bool IsClonable() const override { return true; }
bool CanBeMoved() const override { return true; }
- bool InstructionDataEquals(const HInstruction* other ATTRIBUTE_UNUSED) const override {
+ bool InstructionDataEquals([[maybe_unused]] const HInstruction* other) const override {
return true;
}
// Return whether the conversion is implicit. This includes conversion to the same type.
@@ -6160,6 +6204,9 @@ class HTypeConversion final : public HExpression<1> {
// containing the result. If the input cannot be converted, return nullptr.
HConstant* TryStaticEvaluation() const;
+ // Same but for `input` instead of GetInput().
+ HConstant* TryStaticEvaluation(HInstruction* input) const;
+
DECLARE_INSTRUCTION(TypeConversion);
protected:
@@ -6180,7 +6227,7 @@ class HNullCheck final : public HExpression<1> {
bool IsClonable() const override { return true; }
bool CanBeMoved() const override { return true; }
- bool InstructionDataEquals(const HInstruction* other ATTRIBUTE_UNUSED) const override {
+ bool InstructionDataEquals([[maybe_unused]] const HInstruction* other) const override {
return true;
}
@@ -6321,96 +6368,6 @@ class HInstanceFieldGet final : public HExpression<1> {
const FieldInfo field_info_;
};
-class HPredicatedInstanceFieldGet final : public HExpression<2> {
- public:
- HPredicatedInstanceFieldGet(HInstanceFieldGet* orig,
- HInstruction* target,
- HInstruction* default_val)
- : HExpression(kPredicatedInstanceFieldGet,
- orig->GetFieldType(),
- orig->GetSideEffects(),
- orig->GetDexPc()),
- field_info_(orig->GetFieldInfo()) {
- // NB Default-val is at 0 so we can avoid doing a move.
- SetRawInputAt(1, target);
- SetRawInputAt(0, default_val);
- }
-
- HPredicatedInstanceFieldGet(HInstruction* value,
- ArtField* field,
- HInstruction* default_value,
- DataType::Type field_type,
- MemberOffset field_offset,
- bool is_volatile,
- uint32_t field_idx,
- uint16_t declaring_class_def_index,
- const DexFile& dex_file,
- uint32_t dex_pc)
- : HExpression(kPredicatedInstanceFieldGet,
- field_type,
- SideEffects::FieldReadOfType(field_type, is_volatile),
- dex_pc),
- field_info_(field,
- field_offset,
- field_type,
- is_volatile,
- field_idx,
- declaring_class_def_index,
- dex_file) {
- SetRawInputAt(1, value);
- SetRawInputAt(0, default_value);
- }
-
- bool IsClonable() const override {
- return true;
- }
- bool CanBeMoved() const override {
- return !IsVolatile();
- }
-
- HInstruction* GetDefaultValue() const {
- return InputAt(0);
- }
- HInstruction* GetTarget() const {
- return InputAt(1);
- }
-
- bool InstructionDataEquals(const HInstruction* other) const override {
- const HPredicatedInstanceFieldGet* other_get = other->AsPredicatedInstanceFieldGet();
- return GetFieldOffset().SizeValue() == other_get->GetFieldOffset().SizeValue() &&
- GetDefaultValue() == other_get->GetDefaultValue();
- }
-
- bool CanDoImplicitNullCheckOn(HInstruction* obj) const override {
- return (obj == InputAt(0)) && art::CanDoImplicitNullCheckOn(GetFieldOffset().Uint32Value());
- }
-
- size_t ComputeHashCode() const override {
- return (HInstruction::ComputeHashCode() << 7) | GetFieldOffset().SizeValue();
- }
-
- bool IsFieldAccess() const override { return true; }
- const FieldInfo& GetFieldInfo() const override { return field_info_; }
- MemberOffset GetFieldOffset() const { return field_info_.GetFieldOffset(); }
- DataType::Type GetFieldType() const { return field_info_.GetFieldType(); }
- bool IsVolatile() const { return field_info_.IsVolatile(); }
-
- void SetType(DataType::Type new_type) {
- DCHECK(DataType::IsIntegralType(GetType()));
- DCHECK(DataType::IsIntegralType(new_type));
- DCHECK_EQ(DataType::Size(GetType()), DataType::Size(new_type));
- SetPackedField<TypeField>(new_type);
- }
-
- DECLARE_INSTRUCTION(PredicatedInstanceFieldGet);
-
- protected:
- DEFAULT_COPY_CONSTRUCTOR(PredicatedInstanceFieldGet);
-
- private:
- const FieldInfo field_info_;
-};
-
enum class WriteBarrierKind {
// Emit the write barrier, with a runtime optimization which checks if the value that it is being
// set is null.
@@ -6455,7 +6412,6 @@ class HInstanceFieldSet final : public HExpression<2> {
declaring_class_def_index,
dex_file) {
SetPackedFlag<kFlagValueCanBeNull>(true);
- SetPackedFlag<kFlagIsPredicatedSet>(false);
SetPackedField<WriteBarrierKindField>(WriteBarrierKind::kEmitWithNullCheck);
SetRawInputAt(0, object);
SetRawInputAt(1, value);
@@ -6475,8 +6431,6 @@ class HInstanceFieldSet final : public HExpression<2> {
HInstruction* GetValue() const { return InputAt(1); }
bool GetValueCanBeNull() const { return GetPackedFlag<kFlagValueCanBeNull>(); }
void ClearValueCanBeNull() { SetPackedFlag<kFlagValueCanBeNull>(false); }
- bool GetIsPredicatedSet() const { return GetPackedFlag<kFlagIsPredicatedSet>(); }
- void SetIsPredicatedSet(bool value = true) { SetPackedFlag<kFlagIsPredicatedSet>(value); }
WriteBarrierKind GetWriteBarrierKind() { return GetPackedField<WriteBarrierKindField>(); }
void SetWriteBarrierKind(WriteBarrierKind kind) {
DCHECK(kind != WriteBarrierKind::kEmitWithNullCheck)
@@ -6491,8 +6445,7 @@ class HInstanceFieldSet final : public HExpression<2> {
private:
static constexpr size_t kFlagValueCanBeNull = kNumberOfGenericPackedBits;
- static constexpr size_t kFlagIsPredicatedSet = kFlagValueCanBeNull + 1;
- static constexpr size_t kWriteBarrierKind = kFlagIsPredicatedSet + 1;
+ static constexpr size_t kWriteBarrierKind = kFlagValueCanBeNull + 1;
static constexpr size_t kWriteBarrierKindSize =
MinimumBitsToStore(static_cast<size_t>(WriteBarrierKind::kLast));
static constexpr size_t kNumberOfInstanceFieldSetPackedBits =
@@ -6511,12 +6464,12 @@ class HArrayGet final : public HExpression<2> {
HInstruction* index,
DataType::Type type,
uint32_t dex_pc)
- : HArrayGet(array,
- index,
- type,
- SideEffects::ArrayReadOfType(type),
- dex_pc,
- /* is_string_char_at= */ false) {
+ : HArrayGet(array,
+ index,
+ type,
+ SideEffects::ArrayReadOfType(type),
+ dex_pc,
+ /* is_string_char_at= */ false) {
}
HArrayGet(HInstruction* array,
@@ -6533,10 +6486,10 @@ class HArrayGet final : public HExpression<2> {
bool IsClonable() const override { return true; }
bool CanBeMoved() const override { return true; }
- bool InstructionDataEquals(const HInstruction* other ATTRIBUTE_UNUSED) const override {
+ bool InstructionDataEquals([[maybe_unused]] const HInstruction* other) const override {
return true;
}
- bool CanDoImplicitNullCheckOn(HInstruction* obj ATTRIBUTE_UNUSED) const override {
+ bool CanDoImplicitNullCheckOn([[maybe_unused]] HInstruction* obj) const override {
// TODO: We can be smarter here.
// Currently, unless the array is the result of NewArray, the array access is always
// preceded by some form of null NullCheck necessary for the bounds check, usually
@@ -6640,7 +6593,7 @@ class HArraySet final : public HExpression<3> {
// Can throw ArrayStoreException.
bool CanThrow() const override { return NeedsTypeCheck(); }
- bool CanDoImplicitNullCheckOn(HInstruction* obj ATTRIBUTE_UNUSED) const override {
+ bool CanDoImplicitNullCheckOn([[maybe_unused]] HInstruction* obj) const override {
// TODO: Same as for ArrayGet.
return false;
}
@@ -6746,7 +6699,7 @@ class HArrayLength final : public HExpression<1> {
bool IsClonable() const override { return true; }
bool CanBeMoved() const override { return true; }
- bool InstructionDataEquals(const HInstruction* other ATTRIBUTE_UNUSED) const override {
+ bool InstructionDataEquals([[maybe_unused]] const HInstruction* other) const override {
return true;
}
bool CanDoImplicitNullCheckOn(HInstruction* obj) const override {
@@ -6790,7 +6743,7 @@ class HBoundsCheck final : public HExpression<2> {
bool IsClonable() const override { return true; }
bool CanBeMoved() const override { return true; }
- bool InstructionDataEquals(const HInstruction* other ATTRIBUTE_UNUSED) const override {
+ bool InstructionDataEquals([[maybe_unused]] const HInstruction* other) const override {
return true;
}
@@ -7000,17 +6953,15 @@ class HLoadClass final : public HInstruction {
bool CanCallRuntime() const {
return NeedsAccessCheck() ||
MustGenerateClinitCheck() ||
- GetLoadKind() == LoadKind::kRuntimeCall ||
- GetLoadKind() == LoadKind::kBssEntry;
+ NeedsBss() ||
+ GetLoadKind() == LoadKind::kRuntimeCall;
}
bool CanThrow() const override {
return NeedsAccessCheck() ||
MustGenerateClinitCheck() ||
// If the class is in the boot image, the lookup in the runtime call cannot throw.
- ((GetLoadKind() == LoadKind::kRuntimeCall ||
- GetLoadKind() == LoadKind::kBssEntry) &&
- !IsInBootImage());
+ ((GetLoadKind() == LoadKind::kRuntimeCall || NeedsBss()) && !IsInBootImage());
}
ReferenceTypeInfo GetLoadedClassRTI() {
@@ -7362,6 +7313,16 @@ class HLoadMethodHandle final : public HInstruction {
class HLoadMethodType final : public HInstruction {
public:
+ // Determines how to load the MethodType.
+ enum class LoadKind {
+ // Load from an entry in the .bss section using a PC-relative load.
+ kBssEntry,
+ // Load using a single runtime call.
+ kRuntimeCall,
+
+ kLast = kRuntimeCall,
+ };
+
HLoadMethodType(HCurrentMethod* current_method,
dex::ProtoIndex proto_index,
const DexFile& dex_file,
@@ -7373,6 +7334,7 @@ class HLoadMethodType final : public HInstruction {
special_input_(HUserRecord<HInstruction*>(current_method)),
proto_index_(proto_index),
dex_file_(dex_file) {
+ SetPackedField<LoadKindField>(LoadKind::kRuntimeCall);
}
using HInstruction::GetInputRecords; // Keep the const version visible.
@@ -7383,6 +7345,12 @@ class HLoadMethodType final : public HInstruction {
bool IsClonable() const override { return true; }
+ void SetLoadKind(LoadKind load_kind);
+
+ LoadKind GetLoadKind() const {
+ return GetPackedField<LoadKindField>();
+ }
+
dex::ProtoIndex GetProtoIndex() const { return proto_index_; }
const DexFile& GetDexFile() const { return dex_file_; }
@@ -7401,6 +7369,14 @@ class HLoadMethodType final : public HInstruction {
DEFAULT_COPY_CONSTRUCTOR(LoadMethodType);
private:
+ static constexpr size_t kFieldLoadKind = kNumberOfGenericPackedBits;
+ static constexpr size_t kFieldLoadKindSize =
+ MinimumBitsToStore(static_cast<size_t>(LoadKind::kLast));
+ static constexpr size_t kNumberOfLoadMethodTypePackedBits = kFieldLoadKind + kFieldLoadKindSize;
+ static_assert(kNumberOfLoadMethodTypePackedBits <= kMaxNumberOfPackedBits,
+ "Too many packed fields.");
+ using LoadKindField = BitField<LoadKind, kFieldLoadKind, kFieldLoadKindSize>;
+
// The special input is the HCurrentMethod for kRuntimeCall.
HUserRecord<HInstruction*> special_input_;
@@ -7408,6 +7384,17 @@ class HLoadMethodType final : public HInstruction {
const DexFile& dex_file_;
};
+std::ostream& operator<<(std::ostream& os, HLoadMethodType::LoadKind rhs);
+
+// Note: defined outside class to see operator<<(., HLoadMethodType::LoadKind).
+inline void HLoadMethodType::SetLoadKind(LoadKind load_kind) {
+ // The load kind should be determined before inserting the instruction to the graph.
+ DCHECK(GetBlock() == nullptr);
+ DCHECK(GetEnvironment() == nullptr);
+ DCHECK_EQ(GetLoadKind(), LoadKind::kRuntimeCall);
+ SetPackedField<LoadKindField>(load_kind);
+}
+
/**
* Performs an initialization check on its Class object input.
*/
@@ -7423,7 +7410,7 @@ class HClinitCheck final : public HExpression<1> {
}
// TODO: Make ClinitCheck clonable.
bool CanBeMoved() const override { return true; }
- bool InstructionDataEquals(const HInstruction* other ATTRIBUTE_UNUSED) const override {
+ bool InstructionDataEquals([[maybe_unused]] const HInstruction* other) const override {
return true;
}
@@ -8343,7 +8330,7 @@ class HSelect final : public HExpression<3> {
HInstruction* GetCondition() const { return InputAt(2); }
bool CanBeMoved() const override { return true; }
- bool InstructionDataEquals(const HInstruction* other ATTRIBUTE_UNUSED) const override {
+ bool InstructionDataEquals([[maybe_unused]] const HInstruction* other) const override {
return true;
}
@@ -8351,6 +8338,12 @@ class HSelect final : public HExpression<3> {
return GetTrueValue()->CanBeNull() || GetFalseValue()->CanBeNull();
}
+ void UpdateType() {
+ DCHECK_EQ(HPhi::ToPhiType(GetTrueValue()->GetType()),
+ HPhi::ToPhiType(GetFalseValue()->GetType()));
+ SetPackedField<TypeField>(HPhi::ToPhiType(GetTrueValue()->GetType()));
+ }
+
DECLARE_INSTRUCTION(Select);
protected:
@@ -8513,7 +8506,7 @@ class HIntermediateAddress final : public HExpression<2> {
bool IsClonable() const override { return true; }
bool CanBeMoved() const override { return true; }
- bool InstructionDataEquals(const HInstruction* other ATTRIBUTE_UNUSED) const override {
+ bool InstructionDataEquals([[maybe_unused]] const HInstruction* other) const override {
return true;
}
bool IsActualObject() const override { return false; }
@@ -8550,7 +8543,7 @@ class HGraphVisitor : public ValueObject {
graph_(graph) {}
virtual ~HGraphVisitor() {}
- virtual void VisitInstruction(HInstruction* instruction ATTRIBUTE_UNUSED) {}
+ virtual void VisitInstruction([[maybe_unused]] HInstruction* instruction) {}
virtual void VisitBasicBlock(HBasicBlock* block);
// Visit the graph following basic block insertion order.
@@ -8623,7 +8616,7 @@ class CloneAndReplaceInstructionVisitor final : public HGraphDelegateVisitor {
DISALLOW_COPY_AND_ASSIGN(CloneAndReplaceInstructionVisitor);
};
-// Iterator over the blocks that art part of the loop. Includes blocks part
+// Iterator over the blocks that are part of the loop; includes blocks which are part
// of an inner loop. The order in which the blocks are iterated is on their
// block id.
class HBlocksInLoopIterator : public ValueObject {
@@ -8656,7 +8649,7 @@ class HBlocksInLoopIterator : public ValueObject {
DISALLOW_COPY_AND_ASSIGN(HBlocksInLoopIterator);
};
-// Iterator over the blocks that art part of the loop. Includes blocks part
+// Iterator over the blocks that are part of the loop; includes blocks which are part
// of an inner loop. The order in which the blocks are iterated is reverse
// post order.
class HBlocksInLoopReversePostOrderIterator : public ValueObject {
@@ -8689,6 +8682,39 @@ class HBlocksInLoopReversePostOrderIterator : public ValueObject {
DISALLOW_COPY_AND_ASSIGN(HBlocksInLoopReversePostOrderIterator);
};
+// Iterator over the blocks that are part of the loop; includes blocks which are part
+// of an inner loop. The order in which the blocks are iterated is post order.
+class HBlocksInLoopPostOrderIterator : public ValueObject {
+ public:
+ explicit HBlocksInLoopPostOrderIterator(const HLoopInformation& info)
+ : blocks_in_loop_(info.GetBlocks()),
+ blocks_(info.GetHeader()->GetGraph()->GetReversePostOrder()),
+ index_(blocks_.size() - 1) {
+ if (!blocks_in_loop_.IsBitSet(blocks_[index_]->GetBlockId())) {
+ Advance();
+ }
+ }
+
+ bool Done() const { return index_ < 0; }
+ HBasicBlock* Current() const { return blocks_[index_]; }
+ void Advance() {
+ --index_;
+ for (; index_ >= 0; --index_) {
+ if (blocks_in_loop_.IsBitSet(blocks_[index_]->GetBlockId())) {
+ break;
+ }
+ }
+ }
+
+ private:
+ const BitVector& blocks_in_loop_;
+ const ArenaVector<HBasicBlock*>& blocks_;
+
+ int32_t index_;
+
+ DISALLOW_COPY_AND_ASSIGN(HBlocksInLoopPostOrderIterator);
+};
+
// Returns int64_t value of a properly typed constant.
inline int64_t Int64FromConstant(HConstant* constant) {
if (constant->IsIntConstant()) {
@@ -8752,10 +8778,18 @@ inline bool IsZeroBitPattern(HInstruction* instruction) {
#define INSTRUCTION_TYPE_CAST(type, super) \
inline const H##type* HInstruction::As##type() const { \
- return Is##type() ? down_cast<const H##type*>(this) : nullptr; \
+ DCHECK(Is##type()); \
+ return down_cast<const H##type*>(this); \
} \
inline H##type* HInstruction::As##type() { \
- return Is##type() ? static_cast<H##type*>(this) : nullptr; \
+ DCHECK(Is##type()); \
+ return down_cast<H##type*>(this); \
+ } \
+ inline const H##type* HInstruction::As##type##OrNull() const { \
+ return Is##type() ? down_cast<const H##type*>(this) : nullptr; \
+ } \
+ inline H##type* HInstruction::As##type##OrNull() { \
+ return Is##type() ? down_cast<H##type*>(this) : nullptr; \
}
FOR_EACH_INSTRUCTION(INSTRUCTION_TYPE_CAST)