14a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko/* 24a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko * Copyright (C) 2015 The Android Open Source Project 34a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko * 44a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko * Licensed under the Apache License, Version 2.0 (the "License"); 54a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko * you may not use this file except in compliance with the License. 64a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko * You may obtain a copy of the License at 74a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko * 84a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko * http://www.apache.org/licenses/LICENSE-2.0 94a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko * 104a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko * Unless required by applicable law or agreed to in writing, software 114a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko * distributed under the License is distributed on an "AS IS" BASIS, 124a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 134a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko * See the License for the specific language governing permissions and 144a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko * limitations under the License. 154a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko */ 164a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko 174a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko#include "instruction_simplifier_shared.h" 184a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko 194a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenkonamespace art { 204a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko 214a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenkonamespace { 224a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko 234a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenkobool TrySimpleMultiplyAccumulatePatterns(HMul* mul, 244a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko HBinaryOperation* input_binop, 254a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko HInstruction* input_other) { 264a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko DCHECK(Primitive::IsIntOrLongType(mul->GetType())); 274a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko DCHECK(input_binop->IsAdd() || input_binop->IsSub()); 284a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko DCHECK_NE(input_binop, input_other); 294a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko if (!input_binop->HasOnlyOneNonEnvironmentUse()) { 304a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko return false; 314a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko } 324a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko 334a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko // Try to interpret patterns like 344a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko // a * (b <+/-> 1) 354a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko // as 364a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko // (a * b) <+/-> a 374a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko HInstruction* input_a = input_other; 384a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko HInstruction* input_b = nullptr; // Set to a non-null value if we found a pattern to optimize. 394a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko HInstruction::InstructionKind op_kind; 404a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko 414a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko if (input_binop->IsAdd()) { 424a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko if ((input_binop->GetConstantRight() != nullptr) && input_binop->GetConstantRight()->IsOne()) { 434a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko // Interpret 444a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko // a * (b + 1) 454a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko // as 464a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko // (a * b) + a 474a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko input_b = input_binop->GetLeastConstantLeft(); 484a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko op_kind = HInstruction::kAdd; 494a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko } 504a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko } else { 514a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko DCHECK(input_binop->IsSub()); 524a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko if (input_binop->GetRight()->IsConstant() && 534a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko input_binop->GetRight()->AsConstant()->IsMinusOne()) { 544a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko // Interpret 554a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko // a * (b - (-1)) 564a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko // as 574a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko // a + (a * b) 584a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko input_b = input_binop->GetLeft(); 594a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko op_kind = HInstruction::kAdd; 604a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko } else if (input_binop->GetLeft()->IsConstant() && 614a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko input_binop->GetLeft()->AsConstant()->IsOne()) { 624a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko // Interpret 634a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko // a * (1 - b) 644a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko // as 654a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko // a - (a * b) 664a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko input_b = input_binop->GetRight(); 674a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko op_kind = HInstruction::kSub; 684a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko } 694a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko } 704a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko 714a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko if (input_b == nullptr) { 724a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko // We did not find a pattern we can optimize. 734a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko return false; 744a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko } 754a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko 764a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko ArenaAllocator* arena = mul->GetBlock()->GetGraph()->GetArena(); 774a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko HMultiplyAccumulate* mulacc = new(arena) HMultiplyAccumulate( 784a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko mul->GetType(), op_kind, input_a, input_a, input_b, mul->GetDexPc()); 794a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko 804a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko mul->GetBlock()->ReplaceAndRemoveInstructionWith(mul, mulacc); 814a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko input_binop->GetBlock()->RemoveInstruction(input_binop); 824a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko 834a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko return true; 844a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko} 854a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko 864a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko} // namespace 874a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko 884a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenkobool TryCombineMultiplyAccumulate(HMul* mul, InstructionSet isa) { 894a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko Primitive::Type type = mul->GetType(); 904a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko switch (isa) { 914a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko case kArm: 924a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko case kThumb2: 934a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko if (type != Primitive::kPrimInt) { 944a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko return false; 954a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko } 964a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko break; 974a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko case kArm64: 984a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko if (!Primitive::IsIntOrLongType(type)) { 994a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko return false; 1004a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko } 1014a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko break; 1024a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko default: 1034a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko return false; 1044a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko } 1054a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko 1064a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko ArenaAllocator* arena = mul->GetBlock()->GetGraph()->GetArena(); 1074a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko 1084a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko if (mul->HasOnlyOneNonEnvironmentUse()) { 109d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko HInstruction* use = mul->GetUses().front().GetUser(); 1104a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko if (use->IsAdd() || use->IsSub()) { 1114a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko // Replace code looking like 1124a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko // MUL tmp, x, y 1134a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko // SUB dst, acc, tmp 1144a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko // with 1154a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko // MULSUB dst, acc, x, y 1164a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko // Note that we do not want to (unconditionally) perform the merge when the 1174a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko // multiplication has multiple uses and it can be merged in all of them. 1184a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko // Multiple uses could happen on the same control-flow path, and we would 1194a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko // then increase the amount of work. In the future we could try to evaluate 1204a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko // whether all uses are on different control-flow paths (using dominance and 1214a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko // reverse-dominance information) and only perform the merge when they are. 1224a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko HInstruction* accumulator = nullptr; 1234a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko HBinaryOperation* binop = use->AsBinaryOperation(); 1244a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko HInstruction* binop_left = binop->GetLeft(); 1254a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko HInstruction* binop_right = binop->GetRight(); 1264a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko // Be careful after GVN. This should not happen since the `HMul` has only 1274a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko // one use. 1284a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko DCHECK_NE(binop_left, binop_right); 1294a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko if (binop_right == mul) { 1304a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko accumulator = binop_left; 1314a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko } else if (use->IsAdd()) { 1324a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko DCHECK_EQ(binop_left, mul); 1334a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko accumulator = binop_right; 1344a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko } 1354a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko 1364a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko if (accumulator != nullptr) { 1374a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko HMultiplyAccumulate* mulacc = 1384a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko new (arena) HMultiplyAccumulate(type, 1394a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko binop->GetKind(), 1404a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko accumulator, 1414a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko mul->GetLeft(), 1424a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko mul->GetRight()); 1434a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko 1444a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko binop->GetBlock()->ReplaceAndRemoveInstructionWith(binop, mulacc); 1454a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko DCHECK(!mul->HasUses()); 1464a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko mul->GetBlock()->RemoveInstruction(mul); 1474a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko return true; 1484a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko } 1494a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko } else if (use->IsNeg() && isa != kArm) { 1504a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko HMultiplyAccumulate* mulacc = 1514a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko new (arena) HMultiplyAccumulate(type, 1524a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko HInstruction::kSub, 1534a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko mul->GetBlock()->GetGraph()->GetConstant(type, 0), 1544a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko mul->GetLeft(), 1554a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko mul->GetRight()); 1564a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko 1574a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko use->GetBlock()->ReplaceAndRemoveInstructionWith(use, mulacc); 1584a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko DCHECK(!mul->HasUses()); 1594a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko mul->GetBlock()->RemoveInstruction(mul); 1604a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko return true; 1614a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko } 1624a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko } 1634a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko 1644a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko // Use multiply accumulate instruction for a few simple patterns. 1654a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko // We prefer not applying the following transformations if the left and 1664a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko // right inputs perform the same operation. 1674a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko // We rely on GVN having squashed the inputs if appropriate. However the 1684a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko // results are still correct even if that did not happen. 1694a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko if (mul->GetLeft() == mul->GetRight()) { 1704a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko return false; 1714a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko } 1724a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko 1734a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko HInstruction* left = mul->GetLeft(); 1744a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko HInstruction* right = mul->GetRight(); 1754a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko if ((right->IsAdd() || right->IsSub()) && 1764a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko TrySimpleMultiplyAccumulatePatterns(mul, right->AsBinaryOperation(), left)) { 1774a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko return true; 1784a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko } 1794a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko if ((left->IsAdd() || left->IsSub()) && 1804a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko TrySimpleMultiplyAccumulatePatterns(mul, left->AsBinaryOperation(), right)) { 1814a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko return true; 1824a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko } 1834a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko return false; 1844a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko} 1854a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko 1867fc6350f6f1ab04b52b9cd7542e0790528296cbeArtem Serov 1877fc6350f6f1ab04b52b9cd7542e0790528296cbeArtem Serovbool TryMergeNegatedInput(HBinaryOperation* op) { 1887fc6350f6f1ab04b52b9cd7542e0790528296cbeArtem Serov DCHECK(op->IsAnd() || op->IsOr() || op->IsXor()) << op->DebugName(); 1897fc6350f6f1ab04b52b9cd7542e0790528296cbeArtem Serov HInstruction* left = op->GetLeft(); 1907fc6350f6f1ab04b52b9cd7542e0790528296cbeArtem Serov HInstruction* right = op->GetRight(); 1917fc6350f6f1ab04b52b9cd7542e0790528296cbeArtem Serov 1927fc6350f6f1ab04b52b9cd7542e0790528296cbeArtem Serov // Only consider the case where there is exactly one Not, with 2 Not's De 1937fc6350f6f1ab04b52b9cd7542e0790528296cbeArtem Serov // Morgan's laws should be applied instead. 1947fc6350f6f1ab04b52b9cd7542e0790528296cbeArtem Serov if (left->IsNot() ^ right->IsNot()) { 1957fc6350f6f1ab04b52b9cd7542e0790528296cbeArtem Serov HInstruction* hnot = (left->IsNot() ? left : right); 1967fc6350f6f1ab04b52b9cd7542e0790528296cbeArtem Serov HInstruction* hother = (left->IsNot() ? right : left); 1977fc6350f6f1ab04b52b9cd7542e0790528296cbeArtem Serov 1987fc6350f6f1ab04b52b9cd7542e0790528296cbeArtem Serov // Only do the simplification if the Not has only one use and can thus be 1997fc6350f6f1ab04b52b9cd7542e0790528296cbeArtem Serov // safely removed. Even though ARM64 negated bitwise operations do not have 2007fc6350f6f1ab04b52b9cd7542e0790528296cbeArtem Serov // an immediate variant (only register), we still do the simplification when 2017fc6350f6f1ab04b52b9cd7542e0790528296cbeArtem Serov // `hother` is a constant, because it removes an instruction if the constant 2027fc6350f6f1ab04b52b9cd7542e0790528296cbeArtem Serov // cannot be encoded as an immediate: 2037fc6350f6f1ab04b52b9cd7542e0790528296cbeArtem Serov // mov r0, #large_constant 2047fc6350f6f1ab04b52b9cd7542e0790528296cbeArtem Serov // neg r2, r1 2057fc6350f6f1ab04b52b9cd7542e0790528296cbeArtem Serov // and r0, r0, r2 2067fc6350f6f1ab04b52b9cd7542e0790528296cbeArtem Serov // becomes: 2077fc6350f6f1ab04b52b9cd7542e0790528296cbeArtem Serov // mov r0, #large_constant 2087fc6350f6f1ab04b52b9cd7542e0790528296cbeArtem Serov // bic r0, r0, r1 2097fc6350f6f1ab04b52b9cd7542e0790528296cbeArtem Serov if (hnot->HasOnlyOneNonEnvironmentUse()) { 2107fc6350f6f1ab04b52b9cd7542e0790528296cbeArtem Serov // Replace code looking like 2117fc6350f6f1ab04b52b9cd7542e0790528296cbeArtem Serov // NOT tmp, mask 2127fc6350f6f1ab04b52b9cd7542e0790528296cbeArtem Serov // AND dst, src, tmp (respectively ORR, EOR) 2137fc6350f6f1ab04b52b9cd7542e0790528296cbeArtem Serov // with 2147fc6350f6f1ab04b52b9cd7542e0790528296cbeArtem Serov // BIC dst, src, mask (respectively ORN, EON) 2157fc6350f6f1ab04b52b9cd7542e0790528296cbeArtem Serov HInstruction* src = hnot->AsNot()->GetInput(); 2167fc6350f6f1ab04b52b9cd7542e0790528296cbeArtem Serov 2177fc6350f6f1ab04b52b9cd7542e0790528296cbeArtem Serov HBitwiseNegatedRight* neg_op = new (hnot->GetBlock()->GetGraph()->GetArena()) 2187fc6350f6f1ab04b52b9cd7542e0790528296cbeArtem Serov HBitwiseNegatedRight(op->GetType(), op->GetKind(), hother, src, op->GetDexPc()); 2197fc6350f6f1ab04b52b9cd7542e0790528296cbeArtem Serov 2207fc6350f6f1ab04b52b9cd7542e0790528296cbeArtem Serov op->GetBlock()->ReplaceAndRemoveInstructionWith(op, neg_op); 2217fc6350f6f1ab04b52b9cd7542e0790528296cbeArtem Serov hnot->GetBlock()->RemoveInstruction(hnot); 2227fc6350f6f1ab04b52b9cd7542e0790528296cbeArtem Serov return true; 2237fc6350f6f1ab04b52b9cd7542e0790528296cbeArtem Serov } 2247fc6350f6f1ab04b52b9cd7542e0790528296cbeArtem Serov } 2257fc6350f6f1ab04b52b9cd7542e0790528296cbeArtem Serov 2267fc6350f6f1ab04b52b9cd7542e0790528296cbeArtem Serov return false; 2277fc6350f6f1ab04b52b9cd7542e0790528296cbeArtem Serov} 2287fc6350f6f1ab04b52b9cd7542e0790528296cbeArtem Serov 2294a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko} // namespace art 230