summaryrefslogtreecommitdiff
path: root/compiler
diff options
context:
space:
mode:
author Vladimir Marko <vmarko@google.com> 2017-09-28 16:32:24 +0100
committer Vladimir Marko <vmarko@google.com> 2017-09-29 11:24:51 +0100
commit7033d49488c75321ff2e40b26447722ae069c726 (patch)
treeb4474ffba397cbd05bd448e22595c44024a305ca /compiler
parent6e7e0ddf1dda35570cd9ed23751d9306f7353d7f (diff)
ART: Generalize "x >> (s & m)" simplification.
Extend the simplification from x SHIFT (s & mask), mask contains relevant bits where SHIFT is Shl/Shr/UShr/Ror to x SHIFT (s | mask), mask does not contain relevant bits, x SHIFT (s ^ mask), mask does not contain relevant bits, x SHIFT (s + mask), mask does not contain relevant bits, x SHIFT (s - mask), mask does not contain relevant bits, x SHIFT ((type)s), s is non-64-bit integral type. The simplification for the TypeConversion case is motivated by the work to introduce Uint8 and convert '& 0xff' to TypeConversion. This CL makes sure the old simplifications shall still work. The simplifications for Or/Xor/Add/Sub are added just because we can. Test: Add tests to 548-checker-instruct-simplification. Test: m test-art-host-gtest Test: testrunner.py --host --optimizing Bug: 23964345 Change-Id: I71210cb63496fae607a457a627f115260669c2c9
Diffstat (limited to 'compiler')
-rw-r--r--compiler/optimizing/instruction_simplifier.cc34
1 files changed, 26 insertions, 8 deletions
diff --git a/compiler/optimizing/instruction_simplifier.cc b/compiler/optimizing/instruction_simplifier.cc
index 1a2494a992..cf1cbd578c 100644
--- a/compiler/optimizing/instruction_simplifier.cc
+++ b/compiler/optimizing/instruction_simplifier.cc
@@ -360,18 +360,36 @@ void InstructionSimplifierVisitor::VisitShift(HBinaryOperation* instruction) {
}
// Shift operations implicitly mask the shift amount according to the type width. Get rid of
- // unnecessary explicit masking operations on the shift amount.
+ // unnecessary And/Or/Xor/Add/Sub/TypeConversion operations on the shift amount that do not
+ // affect the relevant bits.
// Replace code looking like
- // AND masked_shift, shift, <superset of implicit mask>
- // SHL dst, value, masked_shift
+ // AND adjusted_shift, shift, <superset of implicit mask>
+ // [OR/XOR/ADD/SUB adjusted_shift, shift, <value not overlapping with implicit mask>]
+ // [<conversion-from-integral-non-64-bit-type> adjusted_shift, shift]
+ // SHL dst, value, adjusted_shift
// with
// SHL dst, value, shift
- if (shift_amount->IsAnd()) {
- HAnd* and_insn = shift_amount->AsAnd();
- HConstant* mask = and_insn->GetConstantRight();
- if ((mask != nullptr) && ((Int64FromConstant(mask) & implicit_mask) == implicit_mask)) {
- instruction->ReplaceInput(and_insn->GetLeastConstantLeft(), 1);
+ if (shift_amount->IsAnd() ||
+ shift_amount->IsOr() ||
+ shift_amount->IsXor() ||
+ shift_amount->IsAdd() ||
+ shift_amount->IsSub()) {
+ int64_t required_result = shift_amount->IsAnd() ? implicit_mask : 0;
+ HBinaryOperation* bin_op = shift_amount->AsBinaryOperation();
+ HConstant* mask = bin_op->GetConstantRight();
+ if (mask != nullptr && (Int64FromConstant(mask) & implicit_mask) == required_result) {
+ instruction->ReplaceInput(bin_op->GetLeastConstantLeft(), 1);
RecordSimplification();
+ return;
+ }
+ } else if (shift_amount->IsTypeConversion()) {
+ DCHECK_NE(shift_amount->GetType(), DataType::Type::kBool); // We never convert to bool.
+ DataType::Type source_type = shift_amount->InputAt(0)->GetType();
+ // Non-integral and 64-bit source types require an explicit type conversion.
+ if (DataType::IsIntegralType(source_type) && !DataType::Is64BitType(source_type)) {
+ instruction->ReplaceInput(shift_amount->AsTypeConversion()->GetInput(), 1);
+ RecordSimplification();
+ return;
}
}
}