summaryrefslogtreecommitdiff
path: root/compiler/optimizing/constant_folding.cc
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/optimizing/constant_folding.cc')
-rw-r--r--compiler/optimizing/constant_folding.cc59
1 files changed, 59 insertions, 0 deletions
diff --git a/compiler/optimizing/constant_folding.cc b/compiler/optimizing/constant_folding.cc
index 686ecf08d2..e2bfffb8ec 100644
--- a/compiler/optimizing/constant_folding.cc
+++ b/compiler/optimizing/constant_folding.cc
@@ -19,6 +19,7 @@
#include <algorithm>
#include "base/bit_utils.h"
+#include "base/casts.h"
#include "base/logging.h"
#include "dex/dex_file-inl.h"
#include "intrinsics_enum.h"
@@ -56,6 +57,8 @@ class HConstantFoldingVisitor final : public HGraphDelegateVisitor {
void PropagateValue(HBasicBlock* starting_block, HInstruction* variable, HConstant* constant);
// Intrinsics foldings
+ void FoldReverseIntrinsic(HInvoke* invoke);
+ void FoldReverseBytesIntrinsic(HInvoke* invoke);
void FoldHighestOneBitIntrinsic(HInvoke* invoke);
void FoldLowestOneBitIntrinsic(HInvoke* invoke);
void FoldNumberOfLeadingZerosIntrinsic(HInvoke* invoke);
@@ -362,6 +365,15 @@ void HConstantFoldingVisitor::VisitIf(HIf* inst) {
void HConstantFoldingVisitor::VisitInvoke(HInvoke* inst) {
switch (inst->GetIntrinsic()) {
+ case Intrinsics::kIntegerReverse:
+ case Intrinsics::kLongReverse:
+ FoldReverseIntrinsic(inst);
+ break;
+ case Intrinsics::kIntegerReverseBytes:
+ case Intrinsics::kLongReverseBytes:
+ case Intrinsics::kShortReverseBytes:
+ FoldReverseBytesIntrinsic(inst);
+ break;
case Intrinsics::kIntegerHighestOneBit:
case Intrinsics::kLongHighestOneBit:
FoldHighestOneBitIntrinsic(inst);
@@ -383,6 +395,53 @@ void HConstantFoldingVisitor::VisitInvoke(HInvoke* inst) {
}
}
+void HConstantFoldingVisitor::FoldReverseIntrinsic(HInvoke* inst) {
+ DCHECK(inst->GetIntrinsic() == Intrinsics::kIntegerReverse ||
+ inst->GetIntrinsic() == Intrinsics::kLongReverse);
+
+ HInstruction* input = inst->InputAt(0);
+ if (!input->IsConstant()) {
+ return;
+ }
+
+ // Integer and Long intrinsics have different return types.
+ if (inst->GetIntrinsic() == Intrinsics::kIntegerReverse) {
+ DCHECK(input->IsIntConstant());
+ inst->ReplaceWith(
+ GetGraph()->GetIntConstant(ReverseBits32(input->AsIntConstant()->GetValue())));
+ } else {
+ DCHECK(input->IsLongConstant());
+ inst->ReplaceWith(
+ GetGraph()->GetLongConstant(ReverseBits64(input->AsLongConstant()->GetValue())));
+ }
+ inst->GetBlock()->RemoveInstruction(inst);
+}
+
+void HConstantFoldingVisitor::FoldReverseBytesIntrinsic(HInvoke* inst) {
+ DCHECK(inst->GetIntrinsic() == Intrinsics::kIntegerReverseBytes ||
+ inst->GetIntrinsic() == Intrinsics::kLongReverseBytes ||
+ inst->GetIntrinsic() == Intrinsics::kShortReverseBytes);
+
+ HInstruction* input = inst->InputAt(0);
+ if (!input->IsConstant()) {
+ return;
+ }
+
+ // Integer, Long, and Short intrinsics have different return types.
+ if (inst->GetIntrinsic() == Intrinsics::kIntegerReverseBytes) {
+ DCHECK(input->IsIntConstant());
+ inst->ReplaceWith(GetGraph()->GetIntConstant(BSWAP(input->AsIntConstant()->GetValue())));
+ } else if (inst->GetIntrinsic() == Intrinsics::kLongReverseBytes) {
+ DCHECK(input->IsLongConstant());
+ inst->ReplaceWith(GetGraph()->GetLongConstant(BSWAP(input->AsLongConstant()->GetValue())));
+ } else {
+ DCHECK(input->IsIntConstant());
+ inst->ReplaceWith(GetGraph()->GetIntConstant(
+ BSWAP(dchecked_integral_cast<int16_t>(input->AsIntConstant()->GetValue()))));
+ }
+ inst->GetBlock()->RemoveInstruction(inst);
+}
+
void HConstantFoldingVisitor::FoldHighestOneBitIntrinsic(HInvoke* inst) {
DCHECK(inst->GetIntrinsic() == Intrinsics::kIntegerHighestOneBit ||
inst->GetIntrinsic() == Intrinsics::kLongHighestOneBit);