From 79dc217688a774fc532584f6551a0aec8b45bc4a Mon Sep 17 00:00:00 2001 From: Vladimir Marko Date: Wed, 5 Apr 2023 10:33:07 +0000 Subject: Optimizing: Rename `As##type` to `As##type##OrNull`. The null type check in the current implementation of `HInstruction::As##type()` often cannot be optimized away by clang++. It is therefore beneficial to have two functions HInstruction::As##type() HInstruction::As##type##OrNull() where the first function never returns null but the second one can return null. The additional text "OrNull" shall also flag the possibility of yielding null to the developer which may help avoid bugs similar to what we have seen previously. This requires renaming the existing function that can return null and introducing new function that cannot. However, defining the new function `HInstruction::As##type()` in the same change as renaming the old one would risk introducing bugs by missing a rename. Therefore we simply rename the old function here and the new function shall be introduced in a separate change with all behavioral changes being explicit. Test: m test-art-host-gtest Test: testrunner.py --host --optimizing Test: buildbot-build.sh --target Bug: 181943478 Change-Id: I4defd85038e28fe3506903ba3f33f723682b3298 --- compiler/optimizing/instruction_builder.cc | 46 ++++++++++++++++++++---------- 1 file changed, 31 insertions(+), 15 deletions(-) (limited to 'compiler/optimizing/instruction_builder.cc') diff --git a/compiler/optimizing/instruction_builder.cc b/compiler/optimizing/instruction_builder.cc index 2576b02c9f..f461be9df1 100644 --- a/compiler/optimizing/instruction_builder.cc +++ b/compiler/optimizing/instruction_builder.cc @@ -268,12 +268,14 @@ void HInstructionBuilder::PropagateLocalsToCatchBlocks() { if (local_value == nullptr) { // This is the first instruction throwing into `catch_block` where // `vreg` is undefined. Delete the catch phi. - catch_block->RemovePhi(handler_value->AsPhi()); + // TODO: Remove "OrNull". + catch_block->RemovePhi(handler_value->AsPhiOrNull()); (*handler_locals)[vreg] = nullptr; } else { // Vreg has been defined at all instructions throwing into `catch_block` // encountered so far. Record the local value in the catch phi. - handler_value->AsPhi()->AddInput(local_value); + // TODO: Remove "OrNull". + handler_value->AsPhiOrNull()->AddInput(local_value); } } } @@ -321,7 +323,8 @@ void HInstructionBuilder::SetLoopHeaderPhiInputs() { for (size_t i = loop_headers_.size(); i > 0; --i) { HBasicBlock* block = loop_headers_[i - 1]; for (HInstructionIterator it(block->GetPhis()); !it.Done(); it.Advance()) { - HPhi* phi = it.Current()->AsPhi(); + // TODO: Remove "OrNull". + HPhi* phi = it.Current()->AsPhiOrNull(); size_t vreg = phi->GetRegNumber(); for (HBasicBlock* predecessor : block->GetPredecessors()) { HInstruction* value = ValueOfLocalAt(predecessor, vreg); @@ -1467,7 +1470,8 @@ void HInstructionBuilder::BuildConstructorFenceForAllocation(HInstruction* alloc // // Do not emit an HConstructorFence here since it can inhibit some String new-instance // optimizations (to pass checker tests that rely on those optimizations). - HNewInstance* new_inst = allocation->AsNewInstance(); + // TODO: Remove "OrNull". + HNewInstance* new_inst = allocation->AsNewInstanceOrNull(); HLoadClass* load_class = new_inst->GetLoadClass(); Thread* self = Thread::Current(); @@ -1836,15 +1840,20 @@ bool HInstructionBuilder::SetupInvokeArguments(HInstruction* invoke, if (invoke->IsInvokeStaticOrDirect() && HInvokeStaticOrDirect::NeedsCurrentMethodInput( - invoke->AsInvokeStaticOrDirect()->GetDispatchInfo())) { - DCHECK_EQ(argument_index, invoke->AsInvokeStaticOrDirect()->GetCurrentMethodIndex()); + // TODO: Remove "OrNull". + invoke->AsInvokeStaticOrDirectOrNull()->GetDispatchInfo())) { + // TODO: Remove "OrNull". + DCHECK_EQ(argument_index, invoke->AsInvokeStaticOrDirectOrNull()->GetCurrentMethodIndex()); DCHECK(invoke->InputAt(argument_index) == nullptr); invoke->SetRawInputAt(argument_index, graph_->GetCurrentMethod()); } if (invoke->IsInvokeInterface() && - (invoke->AsInvokeInterface()->GetHiddenArgumentLoadKind() == MethodLoadKind::kRecursive)) { - invoke->SetRawInputAt(invoke->AsInvokeInterface()->GetNumberOfArguments() - 1, + // TODO: Remove "OrNull". + (invoke->AsInvokeInterfaceOrNull()->GetHiddenArgumentLoadKind() == + MethodLoadKind::kRecursive)) { + // TODO: Remove "OrNull". + invoke->SetRawInputAt(invoke->AsInvokeInterfaceOrNull()->GetNumberOfArguments() - 1, graph_->GetCurrentMethod()); } @@ -1856,7 +1865,8 @@ bool HInstructionBuilder::HandleInvoke(HInvoke* invoke, const char* shorty, bool is_unresolved) { DCHECK_IMPLIES(invoke->IsInvokeStaticOrDirect(), - !invoke->AsInvokeStaticOrDirect()->IsStringInit()); + // TODO: Remove "OrNull". + !invoke->AsInvokeStaticOrDirectOrNull()->IsStringInit()); ReceiverArg receiver_arg = (invoke->GetInvokeType() == InvokeType::kStatic) ? ReceiverArg::kNone @@ -1914,7 +1924,8 @@ bool HInstructionBuilder::BuildSimpleIntrinsic(ArtMethod* method, case Intrinsics::kDoubleIsNaN: { // IsNaN(x) is the same as x != x. instruction = new (allocator_) HNotEqual(/*first=*/ nullptr, /*second=*/ nullptr, dex_pc); - instruction->AsCondition()->SetBias(ComparisonBias::kLtBias); + // TODO: Remove "OrNull". + instruction->AsConditionOrNull()->SetBias(ComparisonBias::kLtBias); break; } case Intrinsics::kStringCharAt: @@ -2061,7 +2072,8 @@ bool HInstructionBuilder::HandleStringInit(HInvoke* invoke, const InstructionOperands& operands, const char* shorty) { DCHECK(invoke->IsInvokeStaticOrDirect()); - DCHECK(invoke->AsInvokeStaticOrDirect()->IsStringInit()); + // TODO: Remove "OrNull". + DCHECK(invoke->AsInvokeStaticOrDirectOrNull()->IsStringInit()); if (!SetupInvokeArguments(invoke, operands, shorty, ReceiverArg::kIgnored)) { return false; @@ -2077,7 +2089,8 @@ bool HInstructionBuilder::HandleStringInit(HInvoke* invoke, // Replacing the NewInstance might render it redundant. Keep a list of these // to be visited once it is clear whether it has remaining uses. if (arg_this->IsNewInstance()) { - ssa_builder_->AddUninitializedString(arg_this->AsNewInstance()); + // TODO: Remove "OrNull". + ssa_builder_->AddUninitializedString(arg_this->AsNewInstanceOrNull()); } else { DCHECK(arg_this->IsPhi()); // We can get a phi as input of a String. if there is a loop between the @@ -2366,8 +2379,10 @@ void HInstructionBuilder::BuildCheckedDivRem(uint16_t out_vreg, } if (!second_is_constant || - (type == DataType::Type::kInt32 && second->AsIntConstant()->GetValue() == 0) || - (type == DataType::Type::kInt64 && second->AsLongConstant()->GetValue() == 0)) { + // TODO: Remove "OrNull". + (type == DataType::Type::kInt32 && second->AsIntConstantOrNull()->GetValue() == 0) || + // TODO: Remove "OrNull". + (type == DataType::Type::kInt64 && second->AsLongConstantOrNull()->GetValue() == 0)) { second = new (allocator_) HDivZeroCheck(second, dex_pc); AppendInstruction(second); } @@ -2863,7 +2878,8 @@ bool HInstructionBuilder::ProcessDexInstruction(const Instruction& instruction, uint32_t reg_number = instruction.VRegB(); HInstruction* value = (*current_locals_)[reg_number]; if (value->IsIntConstant()) { - DCHECK_EQ(value->AsIntConstant()->GetValue(), 0); + // TODO: Remove "OrNull". + DCHECK_EQ(value->AsIntConstantOrNull()->GetValue(), 0); } else if (value->IsPhi()) { DCHECK(value->GetType() == DataType::Type::kInt32 || value->GetType() == DataType::Type::kReference); -- cgit v1.2.3-59-g8ed1b