summaryrefslogtreecommitdiff
path: root/compiler/optimizing/constant_folding.cc
diff options
context:
space:
mode:
author Santiago Aboy Solanes <solanes@google.com> 2023-11-16 15:35:26 +0000
committer Santiago Aboy Solanes <solanes@google.com> 2023-11-30 14:49:43 +0000
commit060ad735fdeb2d4b8cf5a115762e994def2eba67 (patch)
tree6c457e5508e51b5d24d0ca0949d303fc9859a477 /compiler/optimizing/constant_folding.cc
parent3cd227c95bc213183899dca912d2a96fba7307a8 (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.cc51
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);