diff options
author | 2023-11-16 15:35:26 +0000 | |
---|---|---|
committer | 2023-11-30 14:49:43 +0000 | |
commit | 060ad735fdeb2d4b8cf5a115762e994def2eba67 (patch) | |
tree | 6c457e5508e51b5d24d0ca0949d303fc9859a477 /compiler/optimizing/constant_folding.cc | |
parent | 3cd227c95bc213183899dca912d2a96fba7307a8 (diff) |
Constant fold DivideUnsigned intrinsic
Bug: 309886589
Test: art/test/testrunner/testrunner.py --host --64 -b --optimizing
Change-Id: If60ccbea30b3fe16b86c1630409b540b05b14c56
Diffstat (limited to 'compiler/optimizing/constant_folding.cc')
-rw-r--r-- | compiler/optimizing/constant_folding.cc | 51 |
1 files changed, 51 insertions, 0 deletions
diff --git a/compiler/optimizing/constant_folding.cc b/compiler/optimizing/constant_folding.cc index 29f5d5caee..66bbf548bb 100644 --- a/compiler/optimizing/constant_folding.cc +++ b/compiler/optimizing/constant_folding.cc @@ -60,6 +60,7 @@ class HConstantFoldingVisitor final : public HGraphDelegateVisitor { void FoldReverseIntrinsic(HInvoke* invoke); void FoldReverseBytesIntrinsic(HInvoke* invoke); void FoldBitCountIntrinsic(HInvoke* invoke); + void FoldDivideUnsignedIntrinsic(HInvoke* invoke); void FoldHighestOneBitIntrinsic(HInvoke* invoke); void FoldLowestOneBitIntrinsic(HInvoke* invoke); void FoldNumberOfLeadingZerosIntrinsic(HInvoke* invoke); @@ -379,6 +380,10 @@ void HConstantFoldingVisitor::VisitInvoke(HInvoke* inst) { case Intrinsics::kLongBitCount: FoldBitCountIntrinsic(inst); break; + case Intrinsics::kIntegerDivideUnsigned: + case Intrinsics::kLongDivideUnsigned: + FoldDivideUnsignedIntrinsic(inst); + break; case Intrinsics::kIntegerHighestOneBit: case Intrinsics::kLongHighestOneBit: FoldHighestOneBitIntrinsic(inst); @@ -467,6 +472,52 @@ void HConstantFoldingVisitor::FoldBitCountIntrinsic(HInvoke* inst) { inst->GetBlock()->RemoveInstruction(inst); } +void HConstantFoldingVisitor::FoldDivideUnsignedIntrinsic(HInvoke* inst) { + DCHECK(inst->GetIntrinsic() == Intrinsics::kIntegerDivideUnsigned || + inst->GetIntrinsic() == Intrinsics::kLongDivideUnsigned); + + HInstruction* divisor = inst->InputAt(1); + if (!divisor->IsConstant()) { + return; + } + DCHECK_IMPLIES(inst->GetIntrinsic() == Intrinsics::kIntegerDivideUnsigned, + divisor->IsIntConstant()); + DCHECK_IMPLIES(inst->GetIntrinsic() == Intrinsics::kLongDivideUnsigned, + divisor->IsLongConstant()); + const bool is_int_intrinsic = inst->GetIntrinsic() == Intrinsics::kIntegerDivideUnsigned; + if ((is_int_intrinsic && divisor->AsIntConstant()->IsArithmeticZero()) || + (!is_int_intrinsic && divisor->AsLongConstant()->IsArithmeticZero())) { + // We will be throwing, don't constant fold. + inst->SetAlwaysThrows(true); + GetGraph()->SetHasAlwaysThrowingInvokes(true); + return; + } + + HInstruction* dividend = inst->InputAt(0); + if (!dividend->IsConstant()) { + return; + } + DCHECK_IMPLIES(inst->GetIntrinsic() == Intrinsics::kIntegerDivideUnsigned, + dividend->IsIntConstant()); + DCHECK_IMPLIES(inst->GetIntrinsic() == Intrinsics::kLongDivideUnsigned, + dividend->IsLongConstant()); + + if (is_int_intrinsic) { + uint32_t dividend_val = + dchecked_integral_cast<uint32_t>(dividend->AsIntConstant()->GetValueAsUint64()); + uint32_t divisor_val = + dchecked_integral_cast<uint32_t>(divisor->AsIntConstant()->GetValueAsUint64()); + inst->ReplaceWith(GetGraph()->GetIntConstant(static_cast<int32_t>(dividend_val / divisor_val))); + } else { + uint64_t dividend_val = dividend->AsLongConstant()->GetValueAsUint64(); + uint64_t divisor_val = divisor->AsLongConstant()->GetValueAsUint64(); + inst->ReplaceWith( + GetGraph()->GetLongConstant(static_cast<int64_t>(dividend_val / divisor_val))); + } + + inst->GetBlock()->RemoveInstruction(inst); +} + void HConstantFoldingVisitor::FoldHighestOneBitIntrinsic(HInvoke* inst) { DCHECK(inst->GetIntrinsic() == Intrinsics::kIntegerHighestOneBit || inst->GetIntrinsic() == Intrinsics::kLongHighestOneBit); |