diff options
author | 2017-10-02 09:20:07 +0000 | |
---|---|---|
committer | 2017-10-02 09:20:07 +0000 | |
commit | cd9903db5d0cdb9664d42c11ab04954a829206c8 (patch) | |
tree | 5b0cc2ba94f25617acc634522df6a6a32ee3c2f1 /compiler | |
parent | f67f115423c9ef5aa62a33c12670cd8f89457c9c (diff) | |
parent | 7033d49488c75321ff2e40b26447722ae069c726 (diff) |
Merge "ART: Generalize "x >> (s & m)" simplification."
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/optimizing/instruction_simplifier.cc | 34 |
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; } } } |