summaryrefslogtreecommitdiff
path: root/compiler
diff options
context:
space:
mode:
author Vladimir Marko <vmarko@google.com> 2015-09-29 16:33:44 +0000
committer Gerrit Code Review <noreply-gerritcodereview@google.com> 2015-09-29 16:33:44 +0000
commitf6860a5f12a8fe974b8f25e67a19a71bf0378d62 (patch)
tree040cb5be85ad86a6e1e87be7bedb3de70eb0f6d0 /compiler
parenta2d8b187e7b6631692fa1243e86ef16c428fa9da (diff)
parent452c1b60120aee0883c3339b363f820b8d69c299 (diff)
Merge "Optimizing: Simplify UShr+And, Shr+And."
Diffstat (limited to 'compiler')
-rw-r--r--compiler/optimizing/instruction_simplifier.cc47
1 files changed, 39 insertions, 8 deletions
diff --git a/compiler/optimizing/instruction_simplifier.cc b/compiler/optimizing/instruction_simplifier.cc
index 30dc9b303a..22bca2f111 100644
--- a/compiler/optimizing/instruction_simplifier.cc
+++ b/compiler/optimizing/instruction_simplifier.cc
@@ -507,14 +507,45 @@ void InstructionSimplifierVisitor::VisitAnd(HAnd* instruction) {
HConstant* input_cst = instruction->GetConstantRight();
HInstruction* input_other = instruction->GetLeastConstantLeft();
- if ((input_cst != nullptr) && AreAllBitsSet(input_cst)) {
- // Replace code looking like
- // AND dst, src, 0xFFF...FF
- // with
- // src
- instruction->ReplaceWith(input_other);
- instruction->GetBlock()->RemoveInstruction(instruction);
- return;
+ if (input_cst != nullptr) {
+ int64_t value = Int64FromConstant(input_cst);
+ if (value == -1) {
+ // Replace code looking like
+ // AND dst, src, 0xFFF...FF
+ // with
+ // src
+ instruction->ReplaceWith(input_other);
+ instruction->GetBlock()->RemoveInstruction(instruction);
+ RecordSimplification();
+ return;
+ }
+ // Eliminate And from UShr+And if the And-mask contains all the bits that
+ // can be non-zero after UShr. Transform Shr+And to UShr if the And-mask
+ // precisely clears the shifted-in sign bits.
+ if ((input_other->IsUShr() || input_other->IsShr()) && input_other->InputAt(1)->IsConstant()) {
+ size_t reg_bits = (instruction->GetResultType() == Primitive::kPrimLong) ? 64 : 32;
+ size_t shift = Int64FromConstant(input_other->InputAt(1)->AsConstant()) & (reg_bits - 1);
+ size_t num_tail_bits_set = CTZ(value + 1);
+ if ((num_tail_bits_set >= reg_bits - shift) && input_other->IsUShr()) {
+ // This AND clears only bits known to be clear, for example "(x >>> 24) & 0xff".
+ instruction->ReplaceWith(input_other);
+ instruction->GetBlock()->RemoveInstruction(instruction);
+ RecordSimplification();
+ return;
+ } else if ((num_tail_bits_set == reg_bits - shift) && IsPowerOfTwo(value + 1) &&
+ input_other->HasOnlyOneNonEnvironmentUse()) {
+ DCHECK(input_other->IsShr()); // For UShr, we would have taken the branch above.
+ // Replace SHR+AND with USHR, for example "(x >> 24) & 0xff" -> "x >>> 24".
+ HUShr* ushr = new (GetGraph()->GetArena()) HUShr(instruction->GetType(),
+ input_other->InputAt(0),
+ input_other->InputAt(1),
+ input_other->GetDexPc());
+ instruction->GetBlock()->ReplaceAndRemoveInstructionWith(instruction, ushr);
+ input_other->GetBlock()->RemoveInstruction(input_other);
+ RecordSimplification();
+ return;
+ }
+ }
}
// We assume that GVN has run before, so we only perform a pointer comparison.