From 060ad735fdeb2d4b8cf5a115762e994def2eba67 Mon Sep 17 00:00:00 2001 From: Santiago Aboy Solanes Date: Thu, 16 Nov 2023 15:35:26 +0000 Subject: Constant fold DivideUnsigned intrinsic Bug: 309886589 Test: art/test/testrunner/testrunner.py --host --64 -b --optimizing Change-Id: If60ccbea30b3fe16b86c1630409b540b05b14c56 --- compiler/optimizing/constant_folding.cc | 51 +++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) (limited to 'compiler/optimizing/constant_folding.cc') 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(dividend->AsIntConstant()->GetValueAsUint64()); + uint32_t divisor_val = + dchecked_integral_cast(divisor->AsIntConstant()->GetValueAsUint64()); + inst->ReplaceWith(GetGraph()->GetIntConstant(static_cast(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(dividend_val / divisor_val))); + } + + inst->GetBlock()->RemoveInstruction(inst); +} + void HConstantFoldingVisitor::FoldHighestOneBitIntrinsic(HInvoke* inst) { DCHECK(inst->GetIntrinsic() == Intrinsics::kIntegerHighestOneBit || inst->GetIntrinsic() == Intrinsics::kLongHighestOneBit); -- cgit v1.2.3-59-g8ed1b