13c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray/* 23c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray * Copyright (C) 2014 The Android Open Source Project 33c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray * 43c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray * Licensed under the Apache License, Version 2.0 (the "License"); 53c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray * you may not use this file except in compliance with the License. 63c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray * You may obtain a copy of the License at 73c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray * 83c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray * http://www.apache.org/licenses/LICENSE-2.0 93c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray * 103c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray * Unless required by applicable law or agreed to in writing, software 113c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray * distributed under the License is distributed on an "AS IS" BASIS, 123c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 133c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray * See the License for the specific language governing permissions and 143c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray * limitations under the License. 153c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray */ 163c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray 173c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray#include "instruction_simplifier.h" 183c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray 19a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray#include "intrinsics.h" 20acf735c13998ad2a175f5a17e7bfce220073279dCalin Juravle#include "mirror/class-inl.h" 21acf735c13998ad2a175f5a17e7bfce220073279dCalin Juravle#include "scoped_thread_state_change.h" 22acf735c13998ad2a175f5a17e7bfce220073279dCalin Juravle 233c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffraynamespace art { 243c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray 25a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffrayclass InstructionSimplifierVisitor : public HGraphDelegateVisitor { 265e6916cea259897baaca019c5c7a5d05746306edNicolas Geoffray public: 27acf735c13998ad2a175f5a17e7bfce220073279dCalin Juravle InstructionSimplifierVisitor(HGraph* graph, OptimizingCompilerStats* stats) 28a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray : HGraphDelegateVisitor(graph), 29188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames stats_(stats) {} 30188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames 31188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames void Run(); 325e6916cea259897baaca019c5c7a5d05746306edNicolas Geoffray 335e6916cea259897baaca019c5c7a5d05746306edNicolas Geoffray private: 34188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames void RecordSimplification() { 35188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames simplification_occurred_ = true; 36188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames simplifications_at_current_position_++; 376915898b28cea6c9836ca1be6814d87e89cc6d76Calin Juravle MaybeRecordStat(kInstructionSimplifications); 386915898b28cea6c9836ca1be6814d87e89cc6d76Calin Juravle } 396915898b28cea6c9836ca1be6814d87e89cc6d76Calin Juravle 406915898b28cea6c9836ca1be6814d87e89cc6d76Calin Juravle void MaybeRecordStat(MethodCompilationStat stat) { 416915898b28cea6c9836ca1be6814d87e89cc6d76Calin Juravle if (stats_ != nullptr) { 426915898b28cea6c9836ca1be6814d87e89cc6d76Calin Juravle stats_->RecordStat(stat); 43188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames } 44188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames } 45188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames 4640a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling bool ReplaceRotateWithRor(HBinaryOperation* op, HUShr* ushr, HShl* shl); 4740a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling bool TryReplaceWithRotate(HBinaryOperation* instruction); 4840a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling bool TryReplaceWithRotateConstantPattern(HBinaryOperation* op, HUShr* ushr, HShl* shl); 4940a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling bool TryReplaceWithRotateRegisterNegPattern(HBinaryOperation* op, HUShr* ushr, HShl* shl); 5040a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling bool TryReplaceWithRotateRegisterSubPattern(HBinaryOperation* op, HUShr* ushr, HShl* shl); 5140a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling 52188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames bool TryMoveNegOnInputsAfterBinop(HBinaryOperation* binop); 53ca0e3a0c9f1fd5902dc40043b061d2f9b79ec098Alexandre Rames // `op` should be either HOr or HAnd. 54ca0e3a0c9f1fd5902dc40043b061d2f9b79ec098Alexandre Rames // De Morgan's laws: 55ca0e3a0c9f1fd5902dc40043b061d2f9b79ec098Alexandre Rames // ~a & ~b = ~(a | b) and ~a | ~b = ~(a & b) 56ca0e3a0c9f1fd5902dc40043b061d2f9b79ec098Alexandre Rames bool TryDeMorganNegationFactoring(HBinaryOperation* op); 57b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames void VisitShift(HBinaryOperation* shift); 58b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames 595e6916cea259897baaca019c5c7a5d05746306edNicolas Geoffray void VisitEqual(HEqual* equal) OVERRIDE; 600d13fee6f4330cc9cb100c43135490a34c11d7a5David Brazdil void VisitNotEqual(HNotEqual* equal) OVERRIDE; 610d13fee6f4330cc9cb100c43135490a34c11d7a5David Brazdil void VisitBooleanNot(HBooleanNot* bool_not) OVERRIDE; 6207276db28d654594e0e86e9e467cad393f752e6eNicolas Geoffray void VisitInstanceFieldSet(HInstanceFieldSet* equal) OVERRIDE; 6307276db28d654594e0e86e9e467cad393f752e6eNicolas Geoffray void VisitStaticFieldSet(HStaticFieldSet* equal) OVERRIDE; 645e6916cea259897baaca019c5c7a5d05746306edNicolas Geoffray void VisitArraySet(HArraySet* equal) OVERRIDE; 6501fcc9ee556f98d0163cc9b524e989760826926fNicolas Geoffray void VisitTypeConversion(HTypeConversion* instruction) OVERRIDE; 6610e244f9e7f6d96a95c910a2bedef5bd3810c637Calin Juravle void VisitNullCheck(HNullCheck* instruction) OVERRIDE; 670304e182adee81be32c744fd3c0d28add29974ffMingyao Yang void VisitArrayLength(HArrayLength* instruction) OVERRIDE; 68acf735c13998ad2a175f5a17e7bfce220073279dCalin Juravle void VisitCheckCast(HCheckCast* instruction) OVERRIDE; 69b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames void VisitAdd(HAdd* instruction) OVERRIDE; 70b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames void VisitAnd(HAnd* instruction) OVERRIDE; 71c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendell void VisitCondition(HCondition* instruction) OVERRIDE; 72c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendell void VisitGreaterThan(HGreaterThan* condition) OVERRIDE; 73c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendell void VisitGreaterThanOrEqual(HGreaterThanOrEqual* condition) OVERRIDE; 74c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendell void VisitLessThan(HLessThan* condition) OVERRIDE; 75c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendell void VisitLessThanOrEqual(HLessThanOrEqual* condition) OVERRIDE; 76bdd7935c2adc3ad190ee87958e714a36f33cedaeAnton Shamin void VisitBelow(HBelow* condition) OVERRIDE; 77bdd7935c2adc3ad190ee87958e714a36f33cedaeAnton Shamin void VisitBelowOrEqual(HBelowOrEqual* condition) OVERRIDE; 78bdd7935c2adc3ad190ee87958e714a36f33cedaeAnton Shamin void VisitAbove(HAbove* condition) OVERRIDE; 79bdd7935c2adc3ad190ee87958e714a36f33cedaeAnton Shamin void VisitAboveOrEqual(HAboveOrEqual* condition) OVERRIDE; 80b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames void VisitDiv(HDiv* instruction) OVERRIDE; 81b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames void VisitMul(HMul* instruction) OVERRIDE; 82188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames void VisitNeg(HNeg* instruction) OVERRIDE; 83188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames void VisitNot(HNot* instruction) OVERRIDE; 84b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames void VisitOr(HOr* instruction) OVERRIDE; 85b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames void VisitShl(HShl* instruction) OVERRIDE; 86b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames void VisitShr(HShr* instruction) OVERRIDE; 87b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames void VisitSub(HSub* instruction) OVERRIDE; 88b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames void VisitUShr(HUShr* instruction) OVERRIDE; 89b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames void VisitXor(HXor* instruction) OVERRIDE; 9074eb1b264691c4eb399d0858015a7fc13c476ac6David Brazdil void VisitSelect(HSelect* select) OVERRIDE; 9174eb1b264691c4eb399d0858015a7fc13c476ac6David Brazdil void VisitIf(HIf* instruction) OVERRIDE; 92af88835231c2508509eb19aa2d21b92879351962Guillaume "Vermeille" Sanchez void VisitInstanceOf(HInstanceOf* instruction) OVERRIDE; 93a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray void VisitInvoke(HInvoke* invoke) OVERRIDE; 94bb245d199a5240b4c520263fd2c8c10dba79eadcAart Bik void VisitDeoptimize(HDeoptimize* deoptimize) OVERRIDE; 956e7455e90411c77088af5fcbf828219842bd2182Nicolas Geoffray 966e7455e90411c77088af5fcbf828219842bd2182Nicolas Geoffray bool CanEnsureNotNullAt(HInstruction* instr, HInstruction* at) const; 97acf735c13998ad2a175f5a17e7bfce220073279dCalin Juravle 9822c4922c6b31e154a6814c4abe9015d9ba156911Roland Levillain void SimplifyRotate(HInvoke* invoke, bool is_left, Primitive::Type type); 99ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray void SimplifySystemArrayCopy(HInvoke* invoke); 100ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray void SimplifyStringEquals(HInvoke* invoke); 101a5c4a4060edd03eda017abebc85f24cffb083ba7Roland Levillain void SimplifyCompare(HInvoke* invoke, bool is_signum, Primitive::Type type); 10275a38b24801bd4d27c95acef969930f626dd11daAart Bik void SimplifyIsNaN(HInvoke* invoke); 1032a6aad9d388bd29bff04aeec3eb9429d436d1873Aart Bik void SimplifyFP2Int(HInvoke* invoke); 1041193259cb37c9763a111825aa04718a409d07145Aart Bik void SimplifyMemBarrier(HInvoke* invoke, MemBarrierKind barrier_kind); 105ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray 106acf735c13998ad2a175f5a17e7bfce220073279dCalin Juravle OptimizingCompilerStats* stats_; 107188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames bool simplification_occurred_ = false; 108188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames int simplifications_at_current_position_ = 0; 109188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames // We ensure we do not loop infinitely. The value is a finger in the air guess 110188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames // that should allow enough simplification. 111188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames static constexpr int kMaxSamePositionSimplifications = 10; 1125e6916cea259897baaca019c5c7a5d05746306edNicolas Geoffray}; 1135e6916cea259897baaca019c5c7a5d05746306edNicolas Geoffray 1143c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffrayvoid InstructionSimplifier::Run() { 115acf735c13998ad2a175f5a17e7bfce220073279dCalin Juravle InstructionSimplifierVisitor visitor(graph_, stats_); 116188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames visitor.Run(); 117188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames} 118188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames 119188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Ramesvoid InstructionSimplifierVisitor::Run() { 12007276db28d654594e0e86e9e467cad393f752e6eNicolas Geoffray // Iterate in reverse post order to open up more simplifications to users 12107276db28d654594e0e86e9e467cad393f752e6eNicolas Geoffray // of instructions that got simplified. 122188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames for (HReversePostOrderIterator it(*GetGraph()); !it.Done();) { 123188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames // The simplification of an instruction to another instruction may yield 124188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames // possibilities for other simplifications. So although we perform a reverse 125188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames // post order visit, we sometimes need to revisit an instruction index. 126188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames simplification_occurred_ = false; 127188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames VisitBasicBlock(it.Current()); 128188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames if (simplification_occurred_ && 129188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames (simplifications_at_current_position_ < kMaxSamePositionSimplifications)) { 130188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames // New simplifications may be applicable to the instruction at the 131188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames // current index, so don't advance the iterator. 132188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames continue; 133188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames } 134188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames simplifications_at_current_position_ = 0; 135188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames it.Advance(); 136188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames } 1373c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray} 1383c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray 139b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Ramesnamespace { 140b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames 141b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Ramesbool AreAllBitsSet(HConstant* constant) { 142b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames return Int64FromConstant(constant) == -1; 143b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames} 144b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames 145b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames} // namespace 146b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames 147188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames// Returns true if the code was simplified to use only one negation operation 148188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames// after the binary operation instead of one on each of the inputs. 149188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Ramesbool InstructionSimplifierVisitor::TryMoveNegOnInputsAfterBinop(HBinaryOperation* binop) { 150188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames DCHECK(binop->IsAdd() || binop->IsSub()); 151188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames DCHECK(binop->GetLeft()->IsNeg() && binop->GetRight()->IsNeg()); 152188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames HNeg* left_neg = binop->GetLeft()->AsNeg(); 153188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames HNeg* right_neg = binop->GetRight()->AsNeg(); 154188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames if (!left_neg->HasOnlyOneNonEnvironmentUse() || 155188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames !right_neg->HasOnlyOneNonEnvironmentUse()) { 156188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames return false; 157188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames } 158188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames // Replace code looking like 159188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames // NEG tmp1, a 160188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames // NEG tmp2, b 161188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames // ADD dst, tmp1, tmp2 162188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames // with 163188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames // ADD tmp, a, b 164188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames // NEG dst, tmp 165aae9e66a727756bc965121a60ffcef89ed370e6cSerdjuk, Nikolay Y // Note that we cannot optimize `(-a) + (-b)` to `-(a + b)` for floating-point. 166aae9e66a727756bc965121a60ffcef89ed370e6cSerdjuk, Nikolay Y // When `a` is `-0.0` and `b` is `0.0`, the former expression yields `0.0`, 167aae9e66a727756bc965121a60ffcef89ed370e6cSerdjuk, Nikolay Y // while the later yields `-0.0`. 168aae9e66a727756bc965121a60ffcef89ed370e6cSerdjuk, Nikolay Y if (!Primitive::IsIntegralType(binop->GetType())) { 169aae9e66a727756bc965121a60ffcef89ed370e6cSerdjuk, Nikolay Y return false; 170aae9e66a727756bc965121a60ffcef89ed370e6cSerdjuk, Nikolay Y } 171188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames binop->ReplaceInput(left_neg->GetInput(), 0); 172188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames binop->ReplaceInput(right_neg->GetInput(), 1); 173188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames left_neg->GetBlock()->RemoveInstruction(left_neg); 174188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames right_neg->GetBlock()->RemoveInstruction(right_neg); 175188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames HNeg* neg = new (GetGraph()->GetArena()) HNeg(binop->GetType(), binop); 176188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames binop->GetBlock()->InsertInstructionBefore(neg, binop->GetNext()); 177188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames binop->ReplaceWithExceptInReplacementAtIndex(neg, 0); 178188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames RecordSimplification(); 179188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames return true; 180188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames} 181188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames 182ca0e3a0c9f1fd5902dc40043b061d2f9b79ec098Alexandre Ramesbool InstructionSimplifierVisitor::TryDeMorganNegationFactoring(HBinaryOperation* op) { 183ca0e3a0c9f1fd5902dc40043b061d2f9b79ec098Alexandre Rames DCHECK(op->IsAnd() || op->IsOr()) << op->DebugName(); 184ca0e3a0c9f1fd5902dc40043b061d2f9b79ec098Alexandre Rames Primitive::Type type = op->GetType(); 185ca0e3a0c9f1fd5902dc40043b061d2f9b79ec098Alexandre Rames HInstruction* left = op->GetLeft(); 186ca0e3a0c9f1fd5902dc40043b061d2f9b79ec098Alexandre Rames HInstruction* right = op->GetRight(); 187ca0e3a0c9f1fd5902dc40043b061d2f9b79ec098Alexandre Rames 188ca0e3a0c9f1fd5902dc40043b061d2f9b79ec098Alexandre Rames // We can apply De Morgan's laws if both inputs are Not's and are only used 189ca0e3a0c9f1fd5902dc40043b061d2f9b79ec098Alexandre Rames // by `op`. 1909f98025ba5541641cfa9abb7b9cf30332d91fad1Alexandre Rames if (((left->IsNot() && right->IsNot()) || 1919f98025ba5541641cfa9abb7b9cf30332d91fad1Alexandre Rames (left->IsBooleanNot() && right->IsBooleanNot())) && 192ca0e3a0c9f1fd5902dc40043b061d2f9b79ec098Alexandre Rames left->HasOnlyOneNonEnvironmentUse() && 193ca0e3a0c9f1fd5902dc40043b061d2f9b79ec098Alexandre Rames right->HasOnlyOneNonEnvironmentUse()) { 194ca0e3a0c9f1fd5902dc40043b061d2f9b79ec098Alexandre Rames // Replace code looking like 195ca0e3a0c9f1fd5902dc40043b061d2f9b79ec098Alexandre Rames // NOT nota, a 196ca0e3a0c9f1fd5902dc40043b061d2f9b79ec098Alexandre Rames // NOT notb, b 197ca0e3a0c9f1fd5902dc40043b061d2f9b79ec098Alexandre Rames // AND dst, nota, notb (respectively OR) 198ca0e3a0c9f1fd5902dc40043b061d2f9b79ec098Alexandre Rames // with 199ca0e3a0c9f1fd5902dc40043b061d2f9b79ec098Alexandre Rames // OR or, a, b (respectively AND) 200ca0e3a0c9f1fd5902dc40043b061d2f9b79ec098Alexandre Rames // NOT dest, or 2019f98025ba5541641cfa9abb7b9cf30332d91fad1Alexandre Rames HInstruction* src_left = left->InputAt(0); 2029f98025ba5541641cfa9abb7b9cf30332d91fad1Alexandre Rames HInstruction* src_right = right->InputAt(0); 203ca0e3a0c9f1fd5902dc40043b061d2f9b79ec098Alexandre Rames uint32_t dex_pc = op->GetDexPc(); 204ca0e3a0c9f1fd5902dc40043b061d2f9b79ec098Alexandre Rames 205ca0e3a0c9f1fd5902dc40043b061d2f9b79ec098Alexandre Rames // Remove the negations on the inputs. 206ca0e3a0c9f1fd5902dc40043b061d2f9b79ec098Alexandre Rames left->ReplaceWith(src_left); 207ca0e3a0c9f1fd5902dc40043b061d2f9b79ec098Alexandre Rames right->ReplaceWith(src_right); 208ca0e3a0c9f1fd5902dc40043b061d2f9b79ec098Alexandre Rames left->GetBlock()->RemoveInstruction(left); 209ca0e3a0c9f1fd5902dc40043b061d2f9b79ec098Alexandre Rames right->GetBlock()->RemoveInstruction(right); 210ca0e3a0c9f1fd5902dc40043b061d2f9b79ec098Alexandre Rames 211ca0e3a0c9f1fd5902dc40043b061d2f9b79ec098Alexandre Rames // Replace the `HAnd` or `HOr`. 212ca0e3a0c9f1fd5902dc40043b061d2f9b79ec098Alexandre Rames HBinaryOperation* hbin; 213ca0e3a0c9f1fd5902dc40043b061d2f9b79ec098Alexandre Rames if (op->IsAnd()) { 214ca0e3a0c9f1fd5902dc40043b061d2f9b79ec098Alexandre Rames hbin = new (GetGraph()->GetArena()) HOr(type, src_left, src_right, dex_pc); 215ca0e3a0c9f1fd5902dc40043b061d2f9b79ec098Alexandre Rames } else { 216ca0e3a0c9f1fd5902dc40043b061d2f9b79ec098Alexandre Rames hbin = new (GetGraph()->GetArena()) HAnd(type, src_left, src_right, dex_pc); 217ca0e3a0c9f1fd5902dc40043b061d2f9b79ec098Alexandre Rames } 2189f98025ba5541641cfa9abb7b9cf30332d91fad1Alexandre Rames HInstruction* hnot; 2199f98025ba5541641cfa9abb7b9cf30332d91fad1Alexandre Rames if (left->IsBooleanNot()) { 2209f98025ba5541641cfa9abb7b9cf30332d91fad1Alexandre Rames hnot = new (GetGraph()->GetArena()) HBooleanNot(hbin, dex_pc); 2219f98025ba5541641cfa9abb7b9cf30332d91fad1Alexandre Rames } else { 2229f98025ba5541641cfa9abb7b9cf30332d91fad1Alexandre Rames hnot = new (GetGraph()->GetArena()) HNot(type, hbin, dex_pc); 2239f98025ba5541641cfa9abb7b9cf30332d91fad1Alexandre Rames } 224ca0e3a0c9f1fd5902dc40043b061d2f9b79ec098Alexandre Rames 225ca0e3a0c9f1fd5902dc40043b061d2f9b79ec098Alexandre Rames op->GetBlock()->InsertInstructionBefore(hbin, op); 226ca0e3a0c9f1fd5902dc40043b061d2f9b79ec098Alexandre Rames op->GetBlock()->ReplaceAndRemoveInstructionWith(op, hnot); 227ca0e3a0c9f1fd5902dc40043b061d2f9b79ec098Alexandre Rames 228ca0e3a0c9f1fd5902dc40043b061d2f9b79ec098Alexandre Rames RecordSimplification(); 229ca0e3a0c9f1fd5902dc40043b061d2f9b79ec098Alexandre Rames return true; 230ca0e3a0c9f1fd5902dc40043b061d2f9b79ec098Alexandre Rames } 231ca0e3a0c9f1fd5902dc40043b061d2f9b79ec098Alexandre Rames 232ca0e3a0c9f1fd5902dc40043b061d2f9b79ec098Alexandre Rames return false; 233ca0e3a0c9f1fd5902dc40043b061d2f9b79ec098Alexandre Rames} 234ca0e3a0c9f1fd5902dc40043b061d2f9b79ec098Alexandre Rames 235b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Ramesvoid InstructionSimplifierVisitor::VisitShift(HBinaryOperation* instruction) { 236b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames DCHECK(instruction->IsShl() || instruction->IsShr() || instruction->IsUShr()); 237b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames HConstant* input_cst = instruction->GetConstantRight(); 238b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames HInstruction* input_other = instruction->GetLeastConstantLeft(); 239b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames 240ba56d060116d6e145be348fa575314654c6b0572Mark Mendell if (input_cst != nullptr) { 241164306e779de522efba7df637618a8eeed9e37acVladimir Marko int64_t cst = Int64FromConstant(input_cst); 2425b5b9319ff970979ed47d41a41283e4faeffb602Roland Levillain int64_t mask = (input_other->GetType() == Primitive::kPrimLong) 2435b5b9319ff970979ed47d41a41283e4faeffb602Roland Levillain ? kMaxLongShiftDistance 2445b5b9319ff970979ed47d41a41283e4faeffb602Roland Levillain : kMaxIntShiftDistance; 245164306e779de522efba7df637618a8eeed9e37acVladimir Marko if ((cst & mask) == 0) { 246ba56d060116d6e145be348fa575314654c6b0572Mark Mendell // Replace code looking like 247ba56d060116d6e145be348fa575314654c6b0572Mark Mendell // SHL dst, src, 0 248ba56d060116d6e145be348fa575314654c6b0572Mark Mendell // with 249ba56d060116d6e145be348fa575314654c6b0572Mark Mendell // src 250ba56d060116d6e145be348fa575314654c6b0572Mark Mendell instruction->ReplaceWith(input_other); 251ba56d060116d6e145be348fa575314654c6b0572Mark Mendell instruction->GetBlock()->RemoveInstruction(instruction); 252ba56d060116d6e145be348fa575314654c6b0572Mark Mendell } 253b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames } 254b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames} 255b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames 25640a04bf64e5837fa48aceaffe970c9984c94084aScott Wakelingstatic bool IsSubRegBitsMinusOther(HSub* sub, size_t reg_bits, HInstruction* other) { 25740a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling return (sub->GetRight() == other && 25840a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling sub->GetLeft()->IsConstant() && 25940a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling (Int64FromConstant(sub->GetLeft()->AsConstant()) & (reg_bits - 1)) == 0); 26040a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling} 26140a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling 26240a04bf64e5837fa48aceaffe970c9984c94084aScott Wakelingbool InstructionSimplifierVisitor::ReplaceRotateWithRor(HBinaryOperation* op, 26340a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling HUShr* ushr, 26440a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling HShl* shl) { 26522c4922c6b31e154a6814c4abe9015d9ba156911Roland Levillain DCHECK(op->IsAdd() || op->IsXor() || op->IsOr()) << op->DebugName(); 26622c4922c6b31e154a6814c4abe9015d9ba156911Roland Levillain HRor* ror = new (GetGraph()->GetArena()) HRor(ushr->GetType(), ushr->GetLeft(), ushr->GetRight()); 26740a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling op->GetBlock()->ReplaceAndRemoveInstructionWith(op, ror); 26840a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling if (!ushr->HasUses()) { 26940a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling ushr->GetBlock()->RemoveInstruction(ushr); 27040a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling } 27140a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling if (!ushr->GetRight()->HasUses()) { 27240a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling ushr->GetRight()->GetBlock()->RemoveInstruction(ushr->GetRight()); 27340a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling } 27440a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling if (!shl->HasUses()) { 27540a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling shl->GetBlock()->RemoveInstruction(shl); 27640a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling } 27740a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling if (!shl->GetRight()->HasUses()) { 27840a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling shl->GetRight()->GetBlock()->RemoveInstruction(shl->GetRight()); 27940a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling } 28040a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling return true; 28140a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling} 28240a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling 28340a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling// Try to replace a binary operation flanked by one UShr and one Shl with a bitfield rotation. 28440a04bf64e5837fa48aceaffe970c9984c94084aScott Wakelingbool InstructionSimplifierVisitor::TryReplaceWithRotate(HBinaryOperation* op) { 28540a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling DCHECK(op->IsAdd() || op->IsXor() || op->IsOr()); 28640a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling HInstruction* left = op->GetLeft(); 28740a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling HInstruction* right = op->GetRight(); 28840a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling // If we have an UShr and a Shl (in either order). 28940a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling if ((left->IsUShr() && right->IsShl()) || (left->IsShl() && right->IsUShr())) { 29040a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling HUShr* ushr = left->IsUShr() ? left->AsUShr() : right->AsUShr(); 29140a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling HShl* shl = left->IsShl() ? left->AsShl() : right->AsShl(); 29240a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling DCHECK(Primitive::IsIntOrLongType(ushr->GetType())); 29340a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling if (ushr->GetType() == shl->GetType() && 29440a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling ushr->GetLeft() == shl->GetLeft()) { 29540a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling if (ushr->GetRight()->IsConstant() && shl->GetRight()->IsConstant()) { 29640a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling // Shift distances are both constant, try replacing with Ror if they 29740a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling // add up to the register size. 29840a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling return TryReplaceWithRotateConstantPattern(op, ushr, shl); 29940a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling } else if (ushr->GetRight()->IsSub() || shl->GetRight()->IsSub()) { 30040a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling // Shift distances are potentially of the form x and (reg_size - x). 30140a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling return TryReplaceWithRotateRegisterSubPattern(op, ushr, shl); 30240a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling } else if (ushr->GetRight()->IsNeg() || shl->GetRight()->IsNeg()) { 30340a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling // Shift distances are potentially of the form d and -d. 30440a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling return TryReplaceWithRotateRegisterNegPattern(op, ushr, shl); 30540a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling } 30640a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling } 30740a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling } 30840a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling return false; 30940a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling} 31040a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling 31140a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling// Try replacing code looking like (x >>> #rdist OP x << #ldist): 31240a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling// UShr dst, x, #rdist 31340a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling// Shl tmp, x, #ldist 31440a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling// OP dst, dst, tmp 31540a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling// or like (x >>> #rdist OP x << #-ldist): 31640a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling// UShr dst, x, #rdist 31740a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling// Shl tmp, x, #-ldist 31840a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling// OP dst, dst, tmp 31940a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling// with 32040a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling// Ror dst, x, #rdist 32140a04bf64e5837fa48aceaffe970c9984c94084aScott Wakelingbool InstructionSimplifierVisitor::TryReplaceWithRotateConstantPattern(HBinaryOperation* op, 32240a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling HUShr* ushr, 32340a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling HShl* shl) { 32440a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling DCHECK(op->IsAdd() || op->IsXor() || op->IsOr()); 32540a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling size_t reg_bits = Primitive::ComponentSize(ushr->GetType()) * kBitsPerByte; 32640a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling size_t rdist = Int64FromConstant(ushr->GetRight()->AsConstant()); 32740a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling size_t ldist = Int64FromConstant(shl->GetRight()->AsConstant()); 32840a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling if (((ldist + rdist) & (reg_bits - 1)) == 0) { 32940a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling ReplaceRotateWithRor(op, ushr, shl); 33040a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling return true; 33140a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling } 33240a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling return false; 33340a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling} 33440a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling 33540a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling// Replace code looking like (x >>> -d OP x << d): 33640a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling// Neg neg, d 33740a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling// UShr dst, x, neg 33840a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling// Shl tmp, x, d 33940a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling// OP dst, dst, tmp 34040a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling// with 34140a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling// Neg neg, d 34240a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling// Ror dst, x, neg 34340a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling// *** OR *** 34440a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling// Replace code looking like (x >>> d OP x << -d): 34540a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling// UShr dst, x, d 34640a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling// Neg neg, d 34740a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling// Shl tmp, x, neg 34840a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling// OP dst, dst, tmp 34940a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling// with 35040a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling// Ror dst, x, d 35140a04bf64e5837fa48aceaffe970c9984c94084aScott Wakelingbool InstructionSimplifierVisitor::TryReplaceWithRotateRegisterNegPattern(HBinaryOperation* op, 35240a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling HUShr* ushr, 35340a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling HShl* shl) { 35440a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling DCHECK(op->IsAdd() || op->IsXor() || op->IsOr()); 35540a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling DCHECK(ushr->GetRight()->IsNeg() || shl->GetRight()->IsNeg()); 35640a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling bool neg_is_left = shl->GetRight()->IsNeg(); 35740a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling HNeg* neg = neg_is_left ? shl->GetRight()->AsNeg() : ushr->GetRight()->AsNeg(); 35840a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling // And the shift distance being negated is the distance being shifted the other way. 35940a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling if (neg->InputAt(0) == (neg_is_left ? ushr->GetRight() : shl->GetRight())) { 36040a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling ReplaceRotateWithRor(op, ushr, shl); 36140a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling } 36240a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling return false; 36340a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling} 36440a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling 36540a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling// Try replacing code looking like (x >>> d OP x << (#bits - d)): 36640a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling// UShr dst, x, d 36740a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling// Sub ld, #bits, d 36840a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling// Shl tmp, x, ld 36940a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling// OP dst, dst, tmp 37040a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling// with 37140a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling// Ror dst, x, d 37240a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling// *** OR *** 37340a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling// Replace code looking like (x >>> (#bits - d) OP x << d): 37440a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling// Sub rd, #bits, d 37540a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling// UShr dst, x, rd 37640a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling// Shl tmp, x, d 37740a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling// OP dst, dst, tmp 37840a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling// with 37940a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling// Neg neg, d 38040a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling// Ror dst, x, neg 38140a04bf64e5837fa48aceaffe970c9984c94084aScott Wakelingbool InstructionSimplifierVisitor::TryReplaceWithRotateRegisterSubPattern(HBinaryOperation* op, 38240a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling HUShr* ushr, 38340a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling HShl* shl) { 38440a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling DCHECK(op->IsAdd() || op->IsXor() || op->IsOr()); 38540a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling DCHECK(ushr->GetRight()->IsSub() || shl->GetRight()->IsSub()); 38640a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling size_t reg_bits = Primitive::ComponentSize(ushr->GetType()) * kBitsPerByte; 38740a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling HInstruction* shl_shift = shl->GetRight(); 38840a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling HInstruction* ushr_shift = ushr->GetRight(); 38940a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling if ((shl_shift->IsSub() && IsSubRegBitsMinusOther(shl_shift->AsSub(), reg_bits, ushr_shift)) || 39040a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling (ushr_shift->IsSub() && IsSubRegBitsMinusOther(ushr_shift->AsSub(), reg_bits, shl_shift))) { 39140a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling return ReplaceRotateWithRor(op, ushr, shl); 39240a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling } 39340a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling return false; 39440a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling} 39540a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling 39610e244f9e7f6d96a95c910a2bedef5bd3810c637Calin Juravlevoid InstructionSimplifierVisitor::VisitNullCheck(HNullCheck* null_check) { 39710e244f9e7f6d96a95c910a2bedef5bd3810c637Calin Juravle HInstruction* obj = null_check->InputAt(0); 39810e244f9e7f6d96a95c910a2bedef5bd3810c637Calin Juravle if (!obj->CanBeNull()) { 39910e244f9e7f6d96a95c910a2bedef5bd3810c637Calin Juravle null_check->ReplaceWith(obj); 40010e244f9e7f6d96a95c910a2bedef5bd3810c637Calin Juravle null_check->GetBlock()->RemoveInstruction(null_check); 401acf735c13998ad2a175f5a17e7bfce220073279dCalin Juravle if (stats_ != nullptr) { 402acf735c13998ad2a175f5a17e7bfce220073279dCalin Juravle stats_->RecordStat(MethodCompilationStat::kRemovedNullCheck); 403acf735c13998ad2a175f5a17e7bfce220073279dCalin Juravle } 404acf735c13998ad2a175f5a17e7bfce220073279dCalin Juravle } 405acf735c13998ad2a175f5a17e7bfce220073279dCalin Juravle} 406acf735c13998ad2a175f5a17e7bfce220073279dCalin Juravle 4076e7455e90411c77088af5fcbf828219842bd2182Nicolas Geoffraybool InstructionSimplifierVisitor::CanEnsureNotNullAt(HInstruction* input, HInstruction* at) const { 4086e7455e90411c77088af5fcbf828219842bd2182Nicolas Geoffray if (!input->CanBeNull()) { 4096e7455e90411c77088af5fcbf828219842bd2182Nicolas Geoffray return true; 4106e7455e90411c77088af5fcbf828219842bd2182Nicolas Geoffray } 4116e7455e90411c77088af5fcbf828219842bd2182Nicolas Geoffray 412d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko for (const HUseListNode<HInstruction*>& use : input->GetUses()) { 413d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko HInstruction* user = use.GetUser(); 414d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko if (user->IsNullCheck() && user->StrictlyDominates(at)) { 4158909bafa5d64e12eb53f3d37b984f53e7a632224Guillaume "Vermeille" Sanchez return true; 4168909bafa5d64e12eb53f3d37b984f53e7a632224Guillaume "Vermeille" Sanchez } 4178909bafa5d64e12eb53f3d37b984f53e7a632224Guillaume "Vermeille" Sanchez } 4186e7455e90411c77088af5fcbf828219842bd2182Nicolas Geoffray 4198909bafa5d64e12eb53f3d37b984f53e7a632224Guillaume "Vermeille" Sanchez return false; 4208909bafa5d64e12eb53f3d37b984f53e7a632224Guillaume "Vermeille" Sanchez} 4218909bafa5d64e12eb53f3d37b984f53e7a632224Guillaume "Vermeille" Sanchez 422222862ceaeed48528020412ef4f7b1cdaecf8789Guillaume Sanchez// Returns whether doing a type test between the class of `object` against `klass` has 423222862ceaeed48528020412ef4f7b1cdaecf8789Guillaume Sanchez// a statically known outcome. The result of the test is stored in `outcome`. 424222862ceaeed48528020412ef4f7b1cdaecf8789Guillaume Sanchezstatic bool TypeCheckHasKnownOutcome(HLoadClass* klass, HInstruction* object, bool* outcome) { 4252e76830f0b3f23825677436c0633714402715099Calin Juravle DCHECK(!object->IsNullConstant()) << "Null constants should be special cased"; 4262e76830f0b3f23825677436c0633714402715099Calin Juravle ReferenceTypeInfo obj_rti = object->GetReferenceTypeInfo(); 4272e76830f0b3f23825677436c0633714402715099Calin Juravle ScopedObjectAccess soa(Thread::Current()); 4282e76830f0b3f23825677436c0633714402715099Calin Juravle if (!obj_rti.IsValid()) { 4292e76830f0b3f23825677436c0633714402715099Calin Juravle // We run the simplifier before the reference type propagation so type info might not be 4302e76830f0b3f23825677436c0633714402715099Calin Juravle // available. 431222862ceaeed48528020412ef4f7b1cdaecf8789Guillaume Sanchez return false; 432acf735c13998ad2a175f5a17e7bfce220073279dCalin Juravle } 433222862ceaeed48528020412ef4f7b1cdaecf8789Guillaume Sanchez 434222862ceaeed48528020412ef4f7b1cdaecf8789Guillaume Sanchez ReferenceTypeInfo class_rti = klass->GetLoadedClassRTI(); 43598893e146b0ff0e1fd1d7c29252f1d1e75a163f2Calin Juravle if (!class_rti.IsValid()) { 43698893e146b0ff0e1fd1d7c29252f1d1e75a163f2Calin Juravle // Happens when the loaded class is unresolved. 43798893e146b0ff0e1fd1d7c29252f1d1e75a163f2Calin Juravle return false; 43898893e146b0ff0e1fd1d7c29252f1d1e75a163f2Calin Juravle } 43998893e146b0ff0e1fd1d7c29252f1d1e75a163f2Calin Juravle DCHECK(class_rti.IsExact()); 440acf735c13998ad2a175f5a17e7bfce220073279dCalin Juravle if (class_rti.IsSupertypeOf(obj_rti)) { 441222862ceaeed48528020412ef4f7b1cdaecf8789Guillaume Sanchez *outcome = true; 442222862ceaeed48528020412ef4f7b1cdaecf8789Guillaume Sanchez return true; 443222862ceaeed48528020412ef4f7b1cdaecf8789Guillaume Sanchez } else if (obj_rti.IsExact()) { 444222862ceaeed48528020412ef4f7b1cdaecf8789Guillaume Sanchez // The test failed at compile time so will also fail at runtime. 445222862ceaeed48528020412ef4f7b1cdaecf8789Guillaume Sanchez *outcome = false; 446222862ceaeed48528020412ef4f7b1cdaecf8789Guillaume Sanchez return true; 4477cb499b1af1575c854860b0d6a103c4a2a59a569Nicolas Geoffray } else if (!class_rti.IsInterface() 4487cb499b1af1575c854860b0d6a103c4a2a59a569Nicolas Geoffray && !obj_rti.IsInterface() 4497cb499b1af1575c854860b0d6a103c4a2a59a569Nicolas Geoffray && !obj_rti.IsSupertypeOf(class_rti)) { 450222862ceaeed48528020412ef4f7b1cdaecf8789Guillaume Sanchez // Different type hierarchy. The test will fail. 451222862ceaeed48528020412ef4f7b1cdaecf8789Guillaume Sanchez *outcome = false; 452222862ceaeed48528020412ef4f7b1cdaecf8789Guillaume Sanchez return true; 453222862ceaeed48528020412ef4f7b1cdaecf8789Guillaume Sanchez } 454222862ceaeed48528020412ef4f7b1cdaecf8789Guillaume Sanchez return false; 455222862ceaeed48528020412ef4f7b1cdaecf8789Guillaume Sanchez} 456222862ceaeed48528020412ef4f7b1cdaecf8789Guillaume Sanchez 457222862ceaeed48528020412ef4f7b1cdaecf8789Guillaume Sanchezvoid InstructionSimplifierVisitor::VisitCheckCast(HCheckCast* check_cast) { 458222862ceaeed48528020412ef4f7b1cdaecf8789Guillaume Sanchez HInstruction* object = check_cast->InputAt(0); 459e53fb5582f8f6ece5d0ce3b9c0d5b1cdb654b254Calin Juravle HLoadClass* load_class = check_cast->InputAt(1)->AsLoadClass(); 460e53fb5582f8f6ece5d0ce3b9c0d5b1cdb654b254Calin Juravle if (load_class->NeedsAccessCheck()) { 461e53fb5582f8f6ece5d0ce3b9c0d5b1cdb654b254Calin Juravle // If we need to perform an access check we cannot remove the instruction. 462e53fb5582f8f6ece5d0ce3b9c0d5b1cdb654b254Calin Juravle return; 463e53fb5582f8f6ece5d0ce3b9c0d5b1cdb654b254Calin Juravle } 464e53fb5582f8f6ece5d0ce3b9c0d5b1cdb654b254Calin Juravle 4656e7455e90411c77088af5fcbf828219842bd2182Nicolas Geoffray if (CanEnsureNotNullAt(object, check_cast)) { 466222862ceaeed48528020412ef4f7b1cdaecf8789Guillaume Sanchez check_cast->ClearMustDoNullCheck(); 467222862ceaeed48528020412ef4f7b1cdaecf8789Guillaume Sanchez } 468222862ceaeed48528020412ef4f7b1cdaecf8789Guillaume Sanchez 469222862ceaeed48528020412ef4f7b1cdaecf8789Guillaume Sanchez if (object->IsNullConstant()) { 470acf735c13998ad2a175f5a17e7bfce220073279dCalin Juravle check_cast->GetBlock()->RemoveInstruction(check_cast); 4716915898b28cea6c9836ca1be6814d87e89cc6d76Calin Juravle MaybeRecordStat(MethodCompilationStat::kRemovedCheckedCast); 472222862ceaeed48528020412ef4f7b1cdaecf8789Guillaume Sanchez return; 473222862ceaeed48528020412ef4f7b1cdaecf8789Guillaume Sanchez } 474222862ceaeed48528020412ef4f7b1cdaecf8789Guillaume Sanchez 475a65ed3045ec2df95a30994752b3fb0576f479354Vladimir Marko // Note: The `outcome` is initialized to please valgrind - the compiler can reorder 476a65ed3045ec2df95a30994752b3fb0576f479354Vladimir Marko // the return value check with the `outcome` check, b/27651442 . 477a65ed3045ec2df95a30994752b3fb0576f479354Vladimir Marko bool outcome = false; 478efa8468c78fdd808043dfb664b56541f3f2dd0e8Nicolas Geoffray if (TypeCheckHasKnownOutcome(load_class, object, &outcome)) { 479222862ceaeed48528020412ef4f7b1cdaecf8789Guillaume Sanchez if (outcome) { 480222862ceaeed48528020412ef4f7b1cdaecf8789Guillaume Sanchez check_cast->GetBlock()->RemoveInstruction(check_cast); 4816915898b28cea6c9836ca1be6814d87e89cc6d76Calin Juravle MaybeRecordStat(MethodCompilationStat::kRemovedCheckedCast); 482efa8468c78fdd808043dfb664b56541f3f2dd0e8Nicolas Geoffray if (!load_class->HasUses()) { 483efa8468c78fdd808043dfb664b56541f3f2dd0e8Nicolas Geoffray // We cannot rely on DCE to remove the class because the `HLoadClass` thinks it can throw. 484efa8468c78fdd808043dfb664b56541f3f2dd0e8Nicolas Geoffray // However, here we know that it cannot because the checkcast was successfull, hence 485efa8468c78fdd808043dfb664b56541f3f2dd0e8Nicolas Geoffray // the class was already loaded. 486efa8468c78fdd808043dfb664b56541f3f2dd0e8Nicolas Geoffray load_class->GetBlock()->RemoveInstruction(load_class); 487efa8468c78fdd808043dfb664b56541f3f2dd0e8Nicolas Geoffray } 488222862ceaeed48528020412ef4f7b1cdaecf8789Guillaume Sanchez } else { 489222862ceaeed48528020412ef4f7b1cdaecf8789Guillaume Sanchez // Don't do anything for exceptional cases for now. Ideally we should remove 490222862ceaeed48528020412ef4f7b1cdaecf8789Guillaume Sanchez // all instructions and blocks this instruction dominates. 491222862ceaeed48528020412ef4f7b1cdaecf8789Guillaume Sanchez } 49210e244f9e7f6d96a95c910a2bedef5bd3810c637Calin Juravle } 49310e244f9e7f6d96a95c910a2bedef5bd3810c637Calin Juravle} 49410e244f9e7f6d96a95c910a2bedef5bd3810c637Calin Juravle 495af88835231c2508509eb19aa2d21b92879351962Guillaume "Vermeille" Sanchezvoid InstructionSimplifierVisitor::VisitInstanceOf(HInstanceOf* instruction) { 496222862ceaeed48528020412ef4f7b1cdaecf8789Guillaume Sanchez HInstruction* object = instruction->InputAt(0); 497e53fb5582f8f6ece5d0ce3b9c0d5b1cdb654b254Calin Juravle HLoadClass* load_class = instruction->InputAt(1)->AsLoadClass(); 498e53fb5582f8f6ece5d0ce3b9c0d5b1cdb654b254Calin Juravle if (load_class->NeedsAccessCheck()) { 499e53fb5582f8f6ece5d0ce3b9c0d5b1cdb654b254Calin Juravle // If we need to perform an access check we cannot remove the instruction. 500e53fb5582f8f6ece5d0ce3b9c0d5b1cdb654b254Calin Juravle return; 501e53fb5582f8f6ece5d0ce3b9c0d5b1cdb654b254Calin Juravle } 502e53fb5582f8f6ece5d0ce3b9c0d5b1cdb654b254Calin Juravle 503222862ceaeed48528020412ef4f7b1cdaecf8789Guillaume Sanchez bool can_be_null = true; 5046e7455e90411c77088af5fcbf828219842bd2182Nicolas Geoffray if (CanEnsureNotNullAt(object, instruction)) { 505222862ceaeed48528020412ef4f7b1cdaecf8789Guillaume Sanchez can_be_null = false; 506af88835231c2508509eb19aa2d21b92879351962Guillaume "Vermeille" Sanchez instruction->ClearMustDoNullCheck(); 507af88835231c2508509eb19aa2d21b92879351962Guillaume "Vermeille" Sanchez } 508222862ceaeed48528020412ef4f7b1cdaecf8789Guillaume Sanchez 509222862ceaeed48528020412ef4f7b1cdaecf8789Guillaume Sanchez HGraph* graph = GetGraph(); 510222862ceaeed48528020412ef4f7b1cdaecf8789Guillaume Sanchez if (object->IsNullConstant()) { 5116915898b28cea6c9836ca1be6814d87e89cc6d76Calin Juravle MaybeRecordStat(kRemovedInstanceOf); 512222862ceaeed48528020412ef4f7b1cdaecf8789Guillaume Sanchez instruction->ReplaceWith(graph->GetIntConstant(0)); 513222862ceaeed48528020412ef4f7b1cdaecf8789Guillaume Sanchez instruction->GetBlock()->RemoveInstruction(instruction); 514222862ceaeed48528020412ef4f7b1cdaecf8789Guillaume Sanchez RecordSimplification(); 515222862ceaeed48528020412ef4f7b1cdaecf8789Guillaume Sanchez return; 516222862ceaeed48528020412ef4f7b1cdaecf8789Guillaume Sanchez } 517222862ceaeed48528020412ef4f7b1cdaecf8789Guillaume Sanchez 51824bd89559c177af9e342f0d5a64a0a2855dfb887Vladimir Marko // Note: The `outcome` is initialized to please valgrind - the compiler can reorder 51924bd89559c177af9e342f0d5a64a0a2855dfb887Vladimir Marko // the return value check with the `outcome` check, b/27651442 . 52024bd89559c177af9e342f0d5a64a0a2855dfb887Vladimir Marko bool outcome = false; 521efa8468c78fdd808043dfb664b56541f3f2dd0e8Nicolas Geoffray if (TypeCheckHasKnownOutcome(load_class, object, &outcome)) { 5226915898b28cea6c9836ca1be6814d87e89cc6d76Calin Juravle MaybeRecordStat(kRemovedInstanceOf); 523222862ceaeed48528020412ef4f7b1cdaecf8789Guillaume Sanchez if (outcome && can_be_null) { 524222862ceaeed48528020412ef4f7b1cdaecf8789Guillaume Sanchez // Type test will succeed, we just need a null test. 525222862ceaeed48528020412ef4f7b1cdaecf8789Guillaume Sanchez HNotEqual* test = new (graph->GetArena()) HNotEqual(graph->GetNullConstant(), object); 526222862ceaeed48528020412ef4f7b1cdaecf8789Guillaume Sanchez instruction->GetBlock()->InsertInstructionBefore(test, instruction); 527222862ceaeed48528020412ef4f7b1cdaecf8789Guillaume Sanchez instruction->ReplaceWith(test); 528222862ceaeed48528020412ef4f7b1cdaecf8789Guillaume Sanchez } else { 529222862ceaeed48528020412ef4f7b1cdaecf8789Guillaume Sanchez // We've statically determined the result of the instanceof. 530222862ceaeed48528020412ef4f7b1cdaecf8789Guillaume Sanchez instruction->ReplaceWith(graph->GetIntConstant(outcome)); 531222862ceaeed48528020412ef4f7b1cdaecf8789Guillaume Sanchez } 532222862ceaeed48528020412ef4f7b1cdaecf8789Guillaume Sanchez RecordSimplification(); 533222862ceaeed48528020412ef4f7b1cdaecf8789Guillaume Sanchez instruction->GetBlock()->RemoveInstruction(instruction); 534efa8468c78fdd808043dfb664b56541f3f2dd0e8Nicolas Geoffray if (outcome && !load_class->HasUses()) { 535efa8468c78fdd808043dfb664b56541f3f2dd0e8Nicolas Geoffray // We cannot rely on DCE to remove the class because the `HLoadClass` thinks it can throw. 536efa8468c78fdd808043dfb664b56541f3f2dd0e8Nicolas Geoffray // However, here we know that it cannot because the instanceof check was successfull, hence 537efa8468c78fdd808043dfb664b56541f3f2dd0e8Nicolas Geoffray // the class was already loaded. 538efa8468c78fdd808043dfb664b56541f3f2dd0e8Nicolas Geoffray load_class->GetBlock()->RemoveInstruction(load_class); 539efa8468c78fdd808043dfb664b56541f3f2dd0e8Nicolas Geoffray } 540222862ceaeed48528020412ef4f7b1cdaecf8789Guillaume Sanchez } 541af88835231c2508509eb19aa2d21b92879351962Guillaume "Vermeille" Sanchez} 542af88835231c2508509eb19aa2d21b92879351962Guillaume "Vermeille" Sanchez 54307276db28d654594e0e86e9e467cad393f752e6eNicolas Geoffrayvoid InstructionSimplifierVisitor::VisitInstanceFieldSet(HInstanceFieldSet* instruction) { 54407276db28d654594e0e86e9e467cad393f752e6eNicolas Geoffray if ((instruction->GetValue()->GetType() == Primitive::kPrimNot) 5456e7455e90411c77088af5fcbf828219842bd2182Nicolas Geoffray && CanEnsureNotNullAt(instruction->GetValue(), instruction)) { 54607276db28d654594e0e86e9e467cad393f752e6eNicolas Geoffray instruction->ClearValueCanBeNull(); 54707276db28d654594e0e86e9e467cad393f752e6eNicolas Geoffray } 54807276db28d654594e0e86e9e467cad393f752e6eNicolas Geoffray} 54907276db28d654594e0e86e9e467cad393f752e6eNicolas Geoffray 55007276db28d654594e0e86e9e467cad393f752e6eNicolas Geoffrayvoid InstructionSimplifierVisitor::VisitStaticFieldSet(HStaticFieldSet* instruction) { 55107276db28d654594e0e86e9e467cad393f752e6eNicolas Geoffray if ((instruction->GetValue()->GetType() == Primitive::kPrimNot) 5526e7455e90411c77088af5fcbf828219842bd2182Nicolas Geoffray && CanEnsureNotNullAt(instruction->GetValue(), instruction)) { 55307276db28d654594e0e86e9e467cad393f752e6eNicolas Geoffray instruction->ClearValueCanBeNull(); 55407276db28d654594e0e86e9e467cad393f752e6eNicolas Geoffray } 55507276db28d654594e0e86e9e467cad393f752e6eNicolas Geoffray} 55607276db28d654594e0e86e9e467cad393f752e6eNicolas Geoffray 557bdd7935c2adc3ad190ee87958e714a36f33cedaeAnton Shaminstatic HCondition* GetOppositeConditionSwapOps(ArenaAllocator* arena, HInstruction* cond) { 558bdd7935c2adc3ad190ee87958e714a36f33cedaeAnton Shamin HInstruction *lhs = cond->InputAt(0); 559bdd7935c2adc3ad190ee87958e714a36f33cedaeAnton Shamin HInstruction *rhs = cond->InputAt(1); 560bdd7935c2adc3ad190ee87958e714a36f33cedaeAnton Shamin switch (cond->GetKind()) { 561bdd7935c2adc3ad190ee87958e714a36f33cedaeAnton Shamin case HInstruction::kEqual: 562bdd7935c2adc3ad190ee87958e714a36f33cedaeAnton Shamin return new (arena) HEqual(rhs, lhs); 563bdd7935c2adc3ad190ee87958e714a36f33cedaeAnton Shamin case HInstruction::kNotEqual: 564bdd7935c2adc3ad190ee87958e714a36f33cedaeAnton Shamin return new (arena) HNotEqual(rhs, lhs); 565bdd7935c2adc3ad190ee87958e714a36f33cedaeAnton Shamin case HInstruction::kLessThan: 566bdd7935c2adc3ad190ee87958e714a36f33cedaeAnton Shamin return new (arena) HGreaterThan(rhs, lhs); 567bdd7935c2adc3ad190ee87958e714a36f33cedaeAnton Shamin case HInstruction::kLessThanOrEqual: 568bdd7935c2adc3ad190ee87958e714a36f33cedaeAnton Shamin return new (arena) HGreaterThanOrEqual(rhs, lhs); 569bdd7935c2adc3ad190ee87958e714a36f33cedaeAnton Shamin case HInstruction::kGreaterThan: 570bdd7935c2adc3ad190ee87958e714a36f33cedaeAnton Shamin return new (arena) HLessThan(rhs, lhs); 571bdd7935c2adc3ad190ee87958e714a36f33cedaeAnton Shamin case HInstruction::kGreaterThanOrEqual: 572bdd7935c2adc3ad190ee87958e714a36f33cedaeAnton Shamin return new (arena) HLessThanOrEqual(rhs, lhs); 573bdd7935c2adc3ad190ee87958e714a36f33cedaeAnton Shamin case HInstruction::kBelow: 574bdd7935c2adc3ad190ee87958e714a36f33cedaeAnton Shamin return new (arena) HAbove(rhs, lhs); 575bdd7935c2adc3ad190ee87958e714a36f33cedaeAnton Shamin case HInstruction::kBelowOrEqual: 576bdd7935c2adc3ad190ee87958e714a36f33cedaeAnton Shamin return new (arena) HAboveOrEqual(rhs, lhs); 577bdd7935c2adc3ad190ee87958e714a36f33cedaeAnton Shamin case HInstruction::kAbove: 578bdd7935c2adc3ad190ee87958e714a36f33cedaeAnton Shamin return new (arena) HBelow(rhs, lhs); 579bdd7935c2adc3ad190ee87958e714a36f33cedaeAnton Shamin case HInstruction::kAboveOrEqual: 580bdd7935c2adc3ad190ee87958e714a36f33cedaeAnton Shamin return new (arena) HBelowOrEqual(rhs, lhs); 581bdd7935c2adc3ad190ee87958e714a36f33cedaeAnton Shamin default: 582bdd7935c2adc3ad190ee87958e714a36f33cedaeAnton Shamin LOG(FATAL) << "Unknown ConditionType " << cond->GetKind(); 583bdd7935c2adc3ad190ee87958e714a36f33cedaeAnton Shamin } 584bdd7935c2adc3ad190ee87958e714a36f33cedaeAnton Shamin return nullptr; 585bdd7935c2adc3ad190ee87958e714a36f33cedaeAnton Shamin} 586bdd7935c2adc3ad190ee87958e714a36f33cedaeAnton Shamin 5875e6916cea259897baaca019c5c7a5d05746306edNicolas Geoffrayvoid InstructionSimplifierVisitor::VisitEqual(HEqual* equal) { 5880d13fee6f4330cc9cb100c43135490a34c11d7a5David Brazdil HInstruction* input_const = equal->GetConstantRight(); 5890d13fee6f4330cc9cb100c43135490a34c11d7a5David Brazdil if (input_const != nullptr) { 5900d13fee6f4330cc9cb100c43135490a34c11d7a5David Brazdil HInstruction* input_value = equal->GetLeastConstantLeft(); 5910d13fee6f4330cc9cb100c43135490a34c11d7a5David Brazdil if (input_value->GetType() == Primitive::kPrimBoolean && input_const->IsIntConstant()) { 5920d13fee6f4330cc9cb100c43135490a34c11d7a5David Brazdil HBasicBlock* block = equal->GetBlock(); 5933c4ab80c102ff1bfc0e74d4abddbf5454bf4008dNicolas Geoffray // We are comparing the boolean to a constant which is of type int and can 5943c4ab80c102ff1bfc0e74d4abddbf5454bf4008dNicolas Geoffray // be any constant. 5951a65388f1d86bb232c2e44fecb44cebe13105d2eRoland Levillain if (input_const->AsIntConstant()->IsTrue()) { 5960d13fee6f4330cc9cb100c43135490a34c11d7a5David Brazdil // Replace (bool_value == true) with bool_value 5970d13fee6f4330cc9cb100c43135490a34c11d7a5David Brazdil equal->ReplaceWith(input_value); 5980d13fee6f4330cc9cb100c43135490a34c11d7a5David Brazdil block->RemoveInstruction(equal); 5990d13fee6f4330cc9cb100c43135490a34c11d7a5David Brazdil RecordSimplification(); 6001a65388f1d86bb232c2e44fecb44cebe13105d2eRoland Levillain } else if (input_const->AsIntConstant()->IsFalse()) { 601f652917de5634b30c974c81d35a72871915b352aMark Mendell equal->ReplaceWith(GetGraph()->InsertOppositeCondition(input_value, equal)); 602f652917de5634b30c974c81d35a72871915b352aMark Mendell block->RemoveInstruction(equal); 6030d13fee6f4330cc9cb100c43135490a34c11d7a5David Brazdil RecordSimplification(); 6041e9ec053008fca7eb713815716c69375c37b399cDavid Brazdil } else { 6051e9ec053008fca7eb713815716c69375c37b399cDavid Brazdil // Replace (bool_value == integer_not_zero_nor_one_constant) with false 6061e9ec053008fca7eb713815716c69375c37b399cDavid Brazdil equal->ReplaceWith(GetGraph()->GetIntConstant(0)); 6071e9ec053008fca7eb713815716c69375c37b399cDavid Brazdil block->RemoveInstruction(equal); 6081e9ec053008fca7eb713815716c69375c37b399cDavid Brazdil RecordSimplification(); 6090d13fee6f4330cc9cb100c43135490a34c11d7a5David Brazdil } 610c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendell } else { 611c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendell VisitCondition(equal); 61201ef345767ea609417fc511e42007705c9667546Nicolas Geoffray } 613c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendell } else { 614c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendell VisitCondition(equal); 61501ef345767ea609417fc511e42007705c9667546Nicolas Geoffray } 61601ef345767ea609417fc511e42007705c9667546Nicolas Geoffray} 61701ef345767ea609417fc511e42007705c9667546Nicolas Geoffray 6180d13fee6f4330cc9cb100c43135490a34c11d7a5David Brazdilvoid InstructionSimplifierVisitor::VisitNotEqual(HNotEqual* not_equal) { 6190d13fee6f4330cc9cb100c43135490a34c11d7a5David Brazdil HInstruction* input_const = not_equal->GetConstantRight(); 6200d13fee6f4330cc9cb100c43135490a34c11d7a5David Brazdil if (input_const != nullptr) { 6210d13fee6f4330cc9cb100c43135490a34c11d7a5David Brazdil HInstruction* input_value = not_equal->GetLeastConstantLeft(); 6220d13fee6f4330cc9cb100c43135490a34c11d7a5David Brazdil if (input_value->GetType() == Primitive::kPrimBoolean && input_const->IsIntConstant()) { 6230d13fee6f4330cc9cb100c43135490a34c11d7a5David Brazdil HBasicBlock* block = not_equal->GetBlock(); 6243c4ab80c102ff1bfc0e74d4abddbf5454bf4008dNicolas Geoffray // We are comparing the boolean to a constant which is of type int and can 6253c4ab80c102ff1bfc0e74d4abddbf5454bf4008dNicolas Geoffray // be any constant. 6261a65388f1d86bb232c2e44fecb44cebe13105d2eRoland Levillain if (input_const->AsIntConstant()->IsTrue()) { 627f652917de5634b30c974c81d35a72871915b352aMark Mendell not_equal->ReplaceWith(GetGraph()->InsertOppositeCondition(input_value, not_equal)); 628f652917de5634b30c974c81d35a72871915b352aMark Mendell block->RemoveInstruction(not_equal); 6290d13fee6f4330cc9cb100c43135490a34c11d7a5David Brazdil RecordSimplification(); 6301a65388f1d86bb232c2e44fecb44cebe13105d2eRoland Levillain } else if (input_const->AsIntConstant()->IsFalse()) { 6310d13fee6f4330cc9cb100c43135490a34c11d7a5David Brazdil // Replace (bool_value != false) with bool_value 6320d13fee6f4330cc9cb100c43135490a34c11d7a5David Brazdil not_equal->ReplaceWith(input_value); 6330d13fee6f4330cc9cb100c43135490a34c11d7a5David Brazdil block->RemoveInstruction(not_equal); 6340d13fee6f4330cc9cb100c43135490a34c11d7a5David Brazdil RecordSimplification(); 6351e9ec053008fca7eb713815716c69375c37b399cDavid Brazdil } else { 6361e9ec053008fca7eb713815716c69375c37b399cDavid Brazdil // Replace (bool_value != integer_not_zero_nor_one_constant) with true 6371e9ec053008fca7eb713815716c69375c37b399cDavid Brazdil not_equal->ReplaceWith(GetGraph()->GetIntConstant(1)); 6381e9ec053008fca7eb713815716c69375c37b399cDavid Brazdil block->RemoveInstruction(not_equal); 6391e9ec053008fca7eb713815716c69375c37b399cDavid Brazdil RecordSimplification(); 6400d13fee6f4330cc9cb100c43135490a34c11d7a5David Brazdil } 641c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendell } else { 642c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendell VisitCondition(not_equal); 6430d13fee6f4330cc9cb100c43135490a34c11d7a5David Brazdil } 644c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendell } else { 645c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendell VisitCondition(not_equal); 6460d13fee6f4330cc9cb100c43135490a34c11d7a5David Brazdil } 6470d13fee6f4330cc9cb100c43135490a34c11d7a5David Brazdil} 6480d13fee6f4330cc9cb100c43135490a34c11d7a5David Brazdil 6490d13fee6f4330cc9cb100c43135490a34c11d7a5David Brazdilvoid InstructionSimplifierVisitor::VisitBooleanNot(HBooleanNot* bool_not) { 65074eb1b264691c4eb399d0858015a7fc13c476ac6David Brazdil HInstruction* input = bool_not->InputAt(0); 65174eb1b264691c4eb399d0858015a7fc13c476ac6David Brazdil HInstruction* replace_with = nullptr; 65274eb1b264691c4eb399d0858015a7fc13c476ac6David Brazdil 65374eb1b264691c4eb399d0858015a7fc13c476ac6David Brazdil if (input->IsIntConstant()) { 65474eb1b264691c4eb399d0858015a7fc13c476ac6David Brazdil // Replace !(true/false) with false/true. 6551a65388f1d86bb232c2e44fecb44cebe13105d2eRoland Levillain if (input->AsIntConstant()->IsTrue()) { 65674eb1b264691c4eb399d0858015a7fc13c476ac6David Brazdil replace_with = GetGraph()->GetIntConstant(0); 65774eb1b264691c4eb399d0858015a7fc13c476ac6David Brazdil } else { 6581a65388f1d86bb232c2e44fecb44cebe13105d2eRoland Levillain DCHECK(input->AsIntConstant()->IsFalse()) << input->AsIntConstant()->GetValue(); 65974eb1b264691c4eb399d0858015a7fc13c476ac6David Brazdil replace_with = GetGraph()->GetIntConstant(1); 66074eb1b264691c4eb399d0858015a7fc13c476ac6David Brazdil } 66174eb1b264691c4eb399d0858015a7fc13c476ac6David Brazdil } else if (input->IsBooleanNot()) { 66274eb1b264691c4eb399d0858015a7fc13c476ac6David Brazdil // Replace (!(!bool_value)) with bool_value. 66374eb1b264691c4eb399d0858015a7fc13c476ac6David Brazdil replace_with = input->InputAt(0); 66474eb1b264691c4eb399d0858015a7fc13c476ac6David Brazdil } else if (input->IsCondition() && 66574eb1b264691c4eb399d0858015a7fc13c476ac6David Brazdil // Don't change FP compares. The definition of compares involving 66674eb1b264691c4eb399d0858015a7fc13c476ac6David Brazdil // NaNs forces the compares to be done as written by the user. 66774eb1b264691c4eb399d0858015a7fc13c476ac6David Brazdil !Primitive::IsFloatingPointType(input->InputAt(0)->GetType())) { 66874eb1b264691c4eb399d0858015a7fc13c476ac6David Brazdil // Replace condition with its opposite. 66974eb1b264691c4eb399d0858015a7fc13c476ac6David Brazdil replace_with = GetGraph()->InsertOppositeCondition(input->AsCondition(), bool_not); 67074eb1b264691c4eb399d0858015a7fc13c476ac6David Brazdil } 67174eb1b264691c4eb399d0858015a7fc13c476ac6David Brazdil 67274eb1b264691c4eb399d0858015a7fc13c476ac6David Brazdil if (replace_with != nullptr) { 67374eb1b264691c4eb399d0858015a7fc13c476ac6David Brazdil bool_not->ReplaceWith(replace_with); 6740d13fee6f4330cc9cb100c43135490a34c11d7a5David Brazdil bool_not->GetBlock()->RemoveInstruction(bool_not); 67574eb1b264691c4eb399d0858015a7fc13c476ac6David Brazdil RecordSimplification(); 67674eb1b264691c4eb399d0858015a7fc13c476ac6David Brazdil } 67774eb1b264691c4eb399d0858015a7fc13c476ac6David Brazdil} 67874eb1b264691c4eb399d0858015a7fc13c476ac6David Brazdil 67974eb1b264691c4eb399d0858015a7fc13c476ac6David Brazdilvoid InstructionSimplifierVisitor::VisitSelect(HSelect* select) { 68074eb1b264691c4eb399d0858015a7fc13c476ac6David Brazdil HInstruction* replace_with = nullptr; 68174eb1b264691c4eb399d0858015a7fc13c476ac6David Brazdil HInstruction* condition = select->GetCondition(); 68274eb1b264691c4eb399d0858015a7fc13c476ac6David Brazdil HInstruction* true_value = select->GetTrueValue(); 68374eb1b264691c4eb399d0858015a7fc13c476ac6David Brazdil HInstruction* false_value = select->GetFalseValue(); 68474eb1b264691c4eb399d0858015a7fc13c476ac6David Brazdil 68574eb1b264691c4eb399d0858015a7fc13c476ac6David Brazdil if (condition->IsBooleanNot()) { 68674eb1b264691c4eb399d0858015a7fc13c476ac6David Brazdil // Change ((!cond) ? x : y) to (cond ? y : x). 68774eb1b264691c4eb399d0858015a7fc13c476ac6David Brazdil condition = condition->InputAt(0); 68874eb1b264691c4eb399d0858015a7fc13c476ac6David Brazdil std::swap(true_value, false_value); 68974eb1b264691c4eb399d0858015a7fc13c476ac6David Brazdil select->ReplaceInput(false_value, 0); 69074eb1b264691c4eb399d0858015a7fc13c476ac6David Brazdil select->ReplaceInput(true_value, 1); 69174eb1b264691c4eb399d0858015a7fc13c476ac6David Brazdil select->ReplaceInput(condition, 2); 69274eb1b264691c4eb399d0858015a7fc13c476ac6David Brazdil RecordSimplification(); 69374eb1b264691c4eb399d0858015a7fc13c476ac6David Brazdil } 69474eb1b264691c4eb399d0858015a7fc13c476ac6David Brazdil 69574eb1b264691c4eb399d0858015a7fc13c476ac6David Brazdil if (true_value == false_value) { 69674eb1b264691c4eb399d0858015a7fc13c476ac6David Brazdil // Replace (cond ? x : x) with (x). 69774eb1b264691c4eb399d0858015a7fc13c476ac6David Brazdil replace_with = true_value; 69874eb1b264691c4eb399d0858015a7fc13c476ac6David Brazdil } else if (condition->IsIntConstant()) { 6991a65388f1d86bb232c2e44fecb44cebe13105d2eRoland Levillain if (condition->AsIntConstant()->IsTrue()) { 70074eb1b264691c4eb399d0858015a7fc13c476ac6David Brazdil // Replace (true ? x : y) with (x). 70174eb1b264691c4eb399d0858015a7fc13c476ac6David Brazdil replace_with = true_value; 70274eb1b264691c4eb399d0858015a7fc13c476ac6David Brazdil } else { 70374eb1b264691c4eb399d0858015a7fc13c476ac6David Brazdil // Replace (false ? x : y) with (y). 7041a65388f1d86bb232c2e44fecb44cebe13105d2eRoland Levillain DCHECK(condition->AsIntConstant()->IsFalse()) << condition->AsIntConstant()->GetValue(); 70574eb1b264691c4eb399d0858015a7fc13c476ac6David Brazdil replace_with = false_value; 70674eb1b264691c4eb399d0858015a7fc13c476ac6David Brazdil } 70774eb1b264691c4eb399d0858015a7fc13c476ac6David Brazdil } else if (true_value->IsIntConstant() && false_value->IsIntConstant()) { 7081a65388f1d86bb232c2e44fecb44cebe13105d2eRoland Levillain if (true_value->AsIntConstant()->IsTrue() && false_value->AsIntConstant()->IsFalse()) { 70974eb1b264691c4eb399d0858015a7fc13c476ac6David Brazdil // Replace (cond ? true : false) with (cond). 71074eb1b264691c4eb399d0858015a7fc13c476ac6David Brazdil replace_with = condition; 7111a65388f1d86bb232c2e44fecb44cebe13105d2eRoland Levillain } else if (true_value->AsIntConstant()->IsFalse() && false_value->AsIntConstant()->IsTrue()) { 71274eb1b264691c4eb399d0858015a7fc13c476ac6David Brazdil // Replace (cond ? false : true) with (!cond). 71374eb1b264691c4eb399d0858015a7fc13c476ac6David Brazdil replace_with = GetGraph()->InsertOppositeCondition(condition, select); 71474eb1b264691c4eb399d0858015a7fc13c476ac6David Brazdil } 71574eb1b264691c4eb399d0858015a7fc13c476ac6David Brazdil } 71674eb1b264691c4eb399d0858015a7fc13c476ac6David Brazdil 71774eb1b264691c4eb399d0858015a7fc13c476ac6David Brazdil if (replace_with != nullptr) { 71874eb1b264691c4eb399d0858015a7fc13c476ac6David Brazdil select->ReplaceWith(replace_with); 71974eb1b264691c4eb399d0858015a7fc13c476ac6David Brazdil select->GetBlock()->RemoveInstruction(select); 72074eb1b264691c4eb399d0858015a7fc13c476ac6David Brazdil RecordSimplification(); 72174eb1b264691c4eb399d0858015a7fc13c476ac6David Brazdil } 72274eb1b264691c4eb399d0858015a7fc13c476ac6David Brazdil} 72374eb1b264691c4eb399d0858015a7fc13c476ac6David Brazdil 72474eb1b264691c4eb399d0858015a7fc13c476ac6David Brazdilvoid InstructionSimplifierVisitor::VisitIf(HIf* instruction) { 72574eb1b264691c4eb399d0858015a7fc13c476ac6David Brazdil HInstruction* condition = instruction->InputAt(0); 72674eb1b264691c4eb399d0858015a7fc13c476ac6David Brazdil if (condition->IsBooleanNot()) { 72774eb1b264691c4eb399d0858015a7fc13c476ac6David Brazdil // Swap successors if input is negated. 72874eb1b264691c4eb399d0858015a7fc13c476ac6David Brazdil instruction->ReplaceInput(condition->InputAt(0), 0); 72974eb1b264691c4eb399d0858015a7fc13c476ac6David Brazdil instruction->GetBlock()->SwapSuccessors(); 7300d13fee6f4330cc9cb100c43135490a34c11d7a5David Brazdil RecordSimplification(); 7310d13fee6f4330cc9cb100c43135490a34c11d7a5David Brazdil } 7320d13fee6f4330cc9cb100c43135490a34c11d7a5David Brazdil} 7330d13fee6f4330cc9cb100c43135490a34c11d7a5David Brazdil 7340304e182adee81be32c744fd3c0d28add29974ffMingyao Yangvoid InstructionSimplifierVisitor::VisitArrayLength(HArrayLength* instruction) { 7350304e182adee81be32c744fd3c0d28add29974ffMingyao Yang HInstruction* input = instruction->InputAt(0); 7360304e182adee81be32c744fd3c0d28add29974ffMingyao Yang // If the array is a NewArray with constant size, replace the array length 7370304e182adee81be32c744fd3c0d28add29974ffMingyao Yang // with the constant instruction. This helps the bounds check elimination phase. 7380304e182adee81be32c744fd3c0d28add29974ffMingyao Yang if (input->IsNewArray()) { 7390304e182adee81be32c744fd3c0d28add29974ffMingyao Yang input = input->InputAt(0); 7400304e182adee81be32c744fd3c0d28add29974ffMingyao Yang if (input->IsIntConstant()) { 7410304e182adee81be32c744fd3c0d28add29974ffMingyao Yang instruction->ReplaceWith(input); 7420304e182adee81be32c744fd3c0d28add29974ffMingyao Yang } 7430304e182adee81be32c744fd3c0d28add29974ffMingyao Yang } 7440304e182adee81be32c744fd3c0d28add29974ffMingyao Yang} 7450304e182adee81be32c744fd3c0d28add29974ffMingyao Yang 7465e6916cea259897baaca019c5c7a5d05746306edNicolas Geoffrayvoid InstructionSimplifierVisitor::VisitArraySet(HArraySet* instruction) { 747af07bc121121d7bd7e8329c55dfe24782207b561Nicolas Geoffray HInstruction* value = instruction->GetValue(); 748af07bc121121d7bd7e8329c55dfe24782207b561Nicolas Geoffray if (value->GetType() != Primitive::kPrimNot) return; 749af07bc121121d7bd7e8329c55dfe24782207b561Nicolas Geoffray 750e0395dd58454e27fc47c0ca273913929fb658e6cNicolas Geoffray if (CanEnsureNotNullAt(value, instruction)) { 751e0395dd58454e27fc47c0ca273913929fb658e6cNicolas Geoffray instruction->ClearValueCanBeNull(); 752e0395dd58454e27fc47c0ca273913929fb658e6cNicolas Geoffray } 753e0395dd58454e27fc47c0ca273913929fb658e6cNicolas Geoffray 754af07bc121121d7bd7e8329c55dfe24782207b561Nicolas Geoffray if (value->IsArrayGet()) { 755af07bc121121d7bd7e8329c55dfe24782207b561Nicolas Geoffray if (value->AsArrayGet()->GetArray() == instruction->GetArray()) { 756af07bc121121d7bd7e8329c55dfe24782207b561Nicolas Geoffray // If the code is just swapping elements in the array, no need for a type check. 757af07bc121121d7bd7e8329c55dfe24782207b561Nicolas Geoffray instruction->ClearNeedsTypeCheck(); 758e0395dd58454e27fc47c0ca273913929fb658e6cNicolas Geoffray return; 759af07bc121121d7bd7e8329c55dfe24782207b561Nicolas Geoffray } 760af07bc121121d7bd7e8329c55dfe24782207b561Nicolas Geoffray } 76107276db28d654594e0e86e9e467cad393f752e6eNicolas Geoffray 7629fdb31e12023d94c710a766a54d8a57c91a196f9Nicolas Geoffray if (value->IsNullConstant()) { 7639fdb31e12023d94c710a766a54d8a57c91a196f9Nicolas Geoffray instruction->ClearNeedsTypeCheck(); 764e0395dd58454e27fc47c0ca273913929fb658e6cNicolas Geoffray return; 7659fdb31e12023d94c710a766a54d8a57c91a196f9Nicolas Geoffray } 7669fdb31e12023d94c710a766a54d8a57c91a196f9Nicolas Geoffray 767e0395dd58454e27fc47c0ca273913929fb658e6cNicolas Geoffray ScopedObjectAccess soa(Thread::Current()); 768e0395dd58454e27fc47c0ca273913929fb658e6cNicolas Geoffray ReferenceTypeInfo array_rti = instruction->GetArray()->GetReferenceTypeInfo(); 769e0395dd58454e27fc47c0ca273913929fb658e6cNicolas Geoffray ReferenceTypeInfo value_rti = value->GetReferenceTypeInfo(); 770e0395dd58454e27fc47c0ca273913929fb658e6cNicolas Geoffray if (!array_rti.IsValid()) { 771e0395dd58454e27fc47c0ca273913929fb658e6cNicolas Geoffray return; 772e0395dd58454e27fc47c0ca273913929fb658e6cNicolas Geoffray } 773e0395dd58454e27fc47c0ca273913929fb658e6cNicolas Geoffray 774e0395dd58454e27fc47c0ca273913929fb658e6cNicolas Geoffray if (value_rti.IsValid() && array_rti.CanArrayHold(value_rti)) { 775e0395dd58454e27fc47c0ca273913929fb658e6cNicolas Geoffray instruction->ClearNeedsTypeCheck(); 776e0395dd58454e27fc47c0ca273913929fb658e6cNicolas Geoffray return; 777e0395dd58454e27fc47c0ca273913929fb658e6cNicolas Geoffray } 778e0395dd58454e27fc47c0ca273913929fb658e6cNicolas Geoffray 779e0395dd58454e27fc47c0ca273913929fb658e6cNicolas Geoffray if (array_rti.IsObjectArray()) { 780e0395dd58454e27fc47c0ca273913929fb658e6cNicolas Geoffray if (array_rti.IsExact()) { 781e0395dd58454e27fc47c0ca273913929fb658e6cNicolas Geoffray instruction->ClearNeedsTypeCheck(); 782e0395dd58454e27fc47c0ca273913929fb658e6cNicolas Geoffray return; 783e0395dd58454e27fc47c0ca273913929fb658e6cNicolas Geoffray } 784e0395dd58454e27fc47c0ca273913929fb658e6cNicolas Geoffray instruction->SetStaticTypeOfArrayIsObjectArray(); 78507276db28d654594e0e86e9e467cad393f752e6eNicolas Geoffray } 786af07bc121121d7bd7e8329c55dfe24782207b561Nicolas Geoffray} 787af07bc121121d7bd7e8329c55dfe24782207b561Nicolas Geoffray 788b52bbde2870e5ab5d126612961dcb3da8e5236eeVladimir Markostatic bool IsTypeConversionImplicit(Primitive::Type input_type, Primitive::Type result_type) { 789f355c3ff08710ac2eba3aac2aacc5e65caa06b4cRoland Levillain // Invariant: We should never generate a conversion to a Boolean value. 790f355c3ff08710ac2eba3aac2aacc5e65caa06b4cRoland Levillain DCHECK_NE(Primitive::kPrimBoolean, result_type); 791f355c3ff08710ac2eba3aac2aacc5e65caa06b4cRoland Levillain 792b52bbde2870e5ab5d126612961dcb3da8e5236eeVladimir Marko // Besides conversion to the same type, widening integral conversions are implicit, 793b52bbde2870e5ab5d126612961dcb3da8e5236eeVladimir Marko // excluding conversions to long and the byte->char conversion where we need to 794b52bbde2870e5ab5d126612961dcb3da8e5236eeVladimir Marko // clear the high 16 bits of the 32-bit sign-extended representation of byte. 795b52bbde2870e5ab5d126612961dcb3da8e5236eeVladimir Marko return result_type == input_type || 796f355c3ff08710ac2eba3aac2aacc5e65caa06b4cRoland Levillain (result_type == Primitive::kPrimInt && (input_type == Primitive::kPrimBoolean || 797f355c3ff08710ac2eba3aac2aacc5e65caa06b4cRoland Levillain input_type == Primitive::kPrimByte || 798f355c3ff08710ac2eba3aac2aacc5e65caa06b4cRoland Levillain input_type == Primitive::kPrimShort || 799f355c3ff08710ac2eba3aac2aacc5e65caa06b4cRoland Levillain input_type == Primitive::kPrimChar)) || 800f355c3ff08710ac2eba3aac2aacc5e65caa06b4cRoland Levillain (result_type == Primitive::kPrimChar && input_type == Primitive::kPrimBoolean) || 801f355c3ff08710ac2eba3aac2aacc5e65caa06b4cRoland Levillain (result_type == Primitive::kPrimShort && (input_type == Primitive::kPrimBoolean || 802f355c3ff08710ac2eba3aac2aacc5e65caa06b4cRoland Levillain input_type == Primitive::kPrimByte)) || 803f355c3ff08710ac2eba3aac2aacc5e65caa06b4cRoland Levillain (result_type == Primitive::kPrimByte && input_type == Primitive::kPrimBoolean); 804b52bbde2870e5ab5d126612961dcb3da8e5236eeVladimir Marko} 805b52bbde2870e5ab5d126612961dcb3da8e5236eeVladimir Marko 806b52bbde2870e5ab5d126612961dcb3da8e5236eeVladimir Markostatic bool IsTypeConversionLossless(Primitive::Type input_type, Primitive::Type result_type) { 807b52bbde2870e5ab5d126612961dcb3da8e5236eeVladimir Marko // The conversion to a larger type is loss-less with the exception of two cases, 808b52bbde2870e5ab5d126612961dcb3da8e5236eeVladimir Marko // - conversion to char, the only unsigned type, where we may lose some bits, and 809b52bbde2870e5ab5d126612961dcb3da8e5236eeVladimir Marko // - conversion from float to long, the only FP to integral conversion with smaller FP type. 810b52bbde2870e5ab5d126612961dcb3da8e5236eeVladimir Marko // For integral to FP conversions this holds because the FP mantissa is large enough. 811b52bbde2870e5ab5d126612961dcb3da8e5236eeVladimir Marko DCHECK_NE(input_type, result_type); 812b52bbde2870e5ab5d126612961dcb3da8e5236eeVladimir Marko return Primitive::ComponentSize(result_type) > Primitive::ComponentSize(input_type) && 813b52bbde2870e5ab5d126612961dcb3da8e5236eeVladimir Marko result_type != Primitive::kPrimChar && 814b52bbde2870e5ab5d126612961dcb3da8e5236eeVladimir Marko !(result_type == Primitive::kPrimLong && input_type == Primitive::kPrimFloat); 815b52bbde2870e5ab5d126612961dcb3da8e5236eeVladimir Marko} 816b52bbde2870e5ab5d126612961dcb3da8e5236eeVladimir Marko 81701fcc9ee556f98d0163cc9b524e989760826926fNicolas Geoffrayvoid InstructionSimplifierVisitor::VisitTypeConversion(HTypeConversion* instruction) { 818b52bbde2870e5ab5d126612961dcb3da8e5236eeVladimir Marko HInstruction* input = instruction->GetInput(); 819b52bbde2870e5ab5d126612961dcb3da8e5236eeVladimir Marko Primitive::Type input_type = input->GetType(); 820b52bbde2870e5ab5d126612961dcb3da8e5236eeVladimir Marko Primitive::Type result_type = instruction->GetResultType(); 821b52bbde2870e5ab5d126612961dcb3da8e5236eeVladimir Marko if (IsTypeConversionImplicit(input_type, result_type)) { 822b52bbde2870e5ab5d126612961dcb3da8e5236eeVladimir Marko // Remove the implicit conversion; this includes conversion to the same type. 823b52bbde2870e5ab5d126612961dcb3da8e5236eeVladimir Marko instruction->ReplaceWith(input); 82401fcc9ee556f98d0163cc9b524e989760826926fNicolas Geoffray instruction->GetBlock()->RemoveInstruction(instruction); 825b52bbde2870e5ab5d126612961dcb3da8e5236eeVladimir Marko RecordSimplification(); 826b52bbde2870e5ab5d126612961dcb3da8e5236eeVladimir Marko return; 827b52bbde2870e5ab5d126612961dcb3da8e5236eeVladimir Marko } 828b52bbde2870e5ab5d126612961dcb3da8e5236eeVladimir Marko 829b52bbde2870e5ab5d126612961dcb3da8e5236eeVladimir Marko if (input->IsTypeConversion()) { 830b52bbde2870e5ab5d126612961dcb3da8e5236eeVladimir Marko HTypeConversion* input_conversion = input->AsTypeConversion(); 831b52bbde2870e5ab5d126612961dcb3da8e5236eeVladimir Marko HInstruction* original_input = input_conversion->GetInput(); 832b52bbde2870e5ab5d126612961dcb3da8e5236eeVladimir Marko Primitive::Type original_type = original_input->GetType(); 833b52bbde2870e5ab5d126612961dcb3da8e5236eeVladimir Marko 834b52bbde2870e5ab5d126612961dcb3da8e5236eeVladimir Marko // When the first conversion is lossless, a direct conversion from the original type 835b52bbde2870e5ab5d126612961dcb3da8e5236eeVladimir Marko // to the final type yields the same result, even for a lossy second conversion, for 836b52bbde2870e5ab5d126612961dcb3da8e5236eeVladimir Marko // example float->double->int or int->double->float. 837b52bbde2870e5ab5d126612961dcb3da8e5236eeVladimir Marko bool is_first_conversion_lossless = IsTypeConversionLossless(original_type, input_type); 838b52bbde2870e5ab5d126612961dcb3da8e5236eeVladimir Marko 839b52bbde2870e5ab5d126612961dcb3da8e5236eeVladimir Marko // For integral conversions, see if the first conversion loses only bits that the second 840b52bbde2870e5ab5d126612961dcb3da8e5236eeVladimir Marko // doesn't need, i.e. the final type is no wider than the intermediate. If so, direct 841b52bbde2870e5ab5d126612961dcb3da8e5236eeVladimir Marko // conversion yields the same result, for example long->int->short or int->char->short. 842b52bbde2870e5ab5d126612961dcb3da8e5236eeVladimir Marko bool integral_conversions_with_non_widening_second = 843b52bbde2870e5ab5d126612961dcb3da8e5236eeVladimir Marko Primitive::IsIntegralType(input_type) && 844b52bbde2870e5ab5d126612961dcb3da8e5236eeVladimir Marko Primitive::IsIntegralType(original_type) && 845b52bbde2870e5ab5d126612961dcb3da8e5236eeVladimir Marko Primitive::IsIntegralType(result_type) && 846b52bbde2870e5ab5d126612961dcb3da8e5236eeVladimir Marko Primitive::ComponentSize(result_type) <= Primitive::ComponentSize(input_type); 847b52bbde2870e5ab5d126612961dcb3da8e5236eeVladimir Marko 848b52bbde2870e5ab5d126612961dcb3da8e5236eeVladimir Marko if (is_first_conversion_lossless || integral_conversions_with_non_widening_second) { 849b52bbde2870e5ab5d126612961dcb3da8e5236eeVladimir Marko // If the merged conversion is implicit, do the simplification unconditionally. 850b52bbde2870e5ab5d126612961dcb3da8e5236eeVladimir Marko if (IsTypeConversionImplicit(original_type, result_type)) { 851b52bbde2870e5ab5d126612961dcb3da8e5236eeVladimir Marko instruction->ReplaceWith(original_input); 852b52bbde2870e5ab5d126612961dcb3da8e5236eeVladimir Marko instruction->GetBlock()->RemoveInstruction(instruction); 853b52bbde2870e5ab5d126612961dcb3da8e5236eeVladimir Marko if (!input_conversion->HasUses()) { 854b52bbde2870e5ab5d126612961dcb3da8e5236eeVladimir Marko // Don't wait for DCE. 855b52bbde2870e5ab5d126612961dcb3da8e5236eeVladimir Marko input_conversion->GetBlock()->RemoveInstruction(input_conversion); 856b52bbde2870e5ab5d126612961dcb3da8e5236eeVladimir Marko } 857b52bbde2870e5ab5d126612961dcb3da8e5236eeVladimir Marko RecordSimplification(); 858b52bbde2870e5ab5d126612961dcb3da8e5236eeVladimir Marko return; 859b52bbde2870e5ab5d126612961dcb3da8e5236eeVladimir Marko } 860b52bbde2870e5ab5d126612961dcb3da8e5236eeVladimir Marko // Otherwise simplify only if the first conversion has no other use. 861b52bbde2870e5ab5d126612961dcb3da8e5236eeVladimir Marko if (input_conversion->HasOnlyOneNonEnvironmentUse()) { 862b52bbde2870e5ab5d126612961dcb3da8e5236eeVladimir Marko input_conversion->ReplaceWith(original_input); 863b52bbde2870e5ab5d126612961dcb3da8e5236eeVladimir Marko input_conversion->GetBlock()->RemoveInstruction(input_conversion); 864b52bbde2870e5ab5d126612961dcb3da8e5236eeVladimir Marko RecordSimplification(); 865b52bbde2870e5ab5d126612961dcb3da8e5236eeVladimir Marko return; 866b52bbde2870e5ab5d126612961dcb3da8e5236eeVladimir Marko } 867b52bbde2870e5ab5d126612961dcb3da8e5236eeVladimir Marko } 868625090fe9bf47d8d735c9a66cbf491de3a3e3765Vladimir Marko } else if (input->IsAnd() && Primitive::IsIntegralType(result_type)) { 8698428bd376e660df2ffceee72f797d1cfc6c66433Vladimir Marko DCHECK(Primitive::IsIntegralType(input_type)); 8708428bd376e660df2ffceee72f797d1cfc6c66433Vladimir Marko HAnd* input_and = input->AsAnd(); 8718428bd376e660df2ffceee72f797d1cfc6c66433Vladimir Marko HConstant* constant = input_and->GetConstantRight(); 8728428bd376e660df2ffceee72f797d1cfc6c66433Vladimir Marko if (constant != nullptr) { 8738428bd376e660df2ffceee72f797d1cfc6c66433Vladimir Marko int64_t value = Int64FromConstant(constant); 8748428bd376e660df2ffceee72f797d1cfc6c66433Vladimir Marko DCHECK_NE(value, -1); // "& -1" would have been optimized away in VisitAnd(). 8758428bd376e660df2ffceee72f797d1cfc6c66433Vladimir Marko size_t trailing_ones = CTZ(~static_cast<uint64_t>(value)); 8768428bd376e660df2ffceee72f797d1cfc6c66433Vladimir Marko if (trailing_ones >= kBitsPerByte * Primitive::ComponentSize(result_type)) { 8778428bd376e660df2ffceee72f797d1cfc6c66433Vladimir Marko // The `HAnd` is useless, for example in `(byte) (x & 0xff)`, get rid of it. 878625090fe9bf47d8d735c9a66cbf491de3a3e3765Vladimir Marko HInstruction* original_input = input_and->GetLeastConstantLeft(); 879625090fe9bf47d8d735c9a66cbf491de3a3e3765Vladimir Marko if (IsTypeConversionImplicit(original_input->GetType(), result_type)) { 880625090fe9bf47d8d735c9a66cbf491de3a3e3765Vladimir Marko instruction->ReplaceWith(original_input); 881625090fe9bf47d8d735c9a66cbf491de3a3e3765Vladimir Marko instruction->GetBlock()->RemoveInstruction(instruction); 882625090fe9bf47d8d735c9a66cbf491de3a3e3765Vladimir Marko RecordSimplification(); 883625090fe9bf47d8d735c9a66cbf491de3a3e3765Vladimir Marko return; 884625090fe9bf47d8d735c9a66cbf491de3a3e3765Vladimir Marko } else if (input->HasOnlyOneNonEnvironmentUse()) { 885625090fe9bf47d8d735c9a66cbf491de3a3e3765Vladimir Marko input_and->ReplaceWith(original_input); 886625090fe9bf47d8d735c9a66cbf491de3a3e3765Vladimir Marko input_and->GetBlock()->RemoveInstruction(input_and); 887625090fe9bf47d8d735c9a66cbf491de3a3e3765Vladimir Marko RecordSimplification(); 888625090fe9bf47d8d735c9a66cbf491de3a3e3765Vladimir Marko return; 889625090fe9bf47d8d735c9a66cbf491de3a3e3765Vladimir Marko } 8908428bd376e660df2ffceee72f797d1cfc6c66433Vladimir Marko } 8918428bd376e660df2ffceee72f797d1cfc6c66433Vladimir Marko } 89201fcc9ee556f98d0163cc9b524e989760826926fNicolas Geoffray } 89301fcc9ee556f98d0163cc9b524e989760826926fNicolas Geoffray} 89401fcc9ee556f98d0163cc9b524e989760826926fNicolas Geoffray 895b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Ramesvoid InstructionSimplifierVisitor::VisitAdd(HAdd* instruction) { 896b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames HConstant* input_cst = instruction->GetConstantRight(); 897b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames HInstruction* input_other = instruction->GetLeastConstantLeft(); 8981a65388f1d86bb232c2e44fecb44cebe13105d2eRoland Levillain if ((input_cst != nullptr) && input_cst->IsArithmeticZero()) { 899b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames // Replace code looking like 900b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames // ADD dst, src, 0 901b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames // with 902b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames // src 903115b53f609e74672fa93eea1845bb17340d5112aSerguei Katkov // Note that we cannot optimize `x + 0.0` to `x` for floating-point. When 904115b53f609e74672fa93eea1845bb17340d5112aSerguei Katkov // `x` is `-0.0`, the former expression yields `0.0`, while the later 905115b53f609e74672fa93eea1845bb17340d5112aSerguei Katkov // yields `-0.0`. 906115b53f609e74672fa93eea1845bb17340d5112aSerguei Katkov if (Primitive::IsIntegralType(instruction->GetType())) { 907115b53f609e74672fa93eea1845bb17340d5112aSerguei Katkov instruction->ReplaceWith(input_other); 908115b53f609e74672fa93eea1845bb17340d5112aSerguei Katkov instruction->GetBlock()->RemoveInstruction(instruction); 909115b53f609e74672fa93eea1845bb17340d5112aSerguei Katkov return; 910115b53f609e74672fa93eea1845bb17340d5112aSerguei Katkov } 911188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames } 912188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames 913188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames HInstruction* left = instruction->GetLeft(); 914188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames HInstruction* right = instruction->GetRight(); 915188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames bool left_is_neg = left->IsNeg(); 916188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames bool right_is_neg = right->IsNeg(); 917188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames 918188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames if (left_is_neg && right_is_neg) { 919188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames if (TryMoveNegOnInputsAfterBinop(instruction)) { 920188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames return; 921188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames } 922188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames } 923188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames 924188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames HNeg* neg = left_is_neg ? left->AsNeg() : right->AsNeg(); 925188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames if ((left_is_neg ^ right_is_neg) && neg->HasOnlyOneNonEnvironmentUse()) { 926188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames // Replace code looking like 927188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames // NEG tmp, b 928188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames // ADD dst, a, tmp 929188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames // with 930188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames // SUB dst, a, b 931188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames // We do not perform the optimization if the input negation has environment 932188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames // uses or multiple non-environment uses as it could lead to worse code. In 933188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames // particular, we do not want the live range of `b` to be extended if we are 934188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames // not sure the initial 'NEG' instruction can be removed. 935188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames HInstruction* other = left_is_neg ? right : left; 936188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames HSub* sub = new(GetGraph()->GetArena()) HSub(instruction->GetType(), other, neg->GetInput()); 937188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames instruction->GetBlock()->ReplaceAndRemoveInstructionWith(instruction, sub); 938188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames RecordSimplification(); 939188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames neg->GetBlock()->RemoveInstruction(neg); 94040a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling return; 941b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames } 94240a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling 94340a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling TryReplaceWithRotate(instruction); 944b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames} 945b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames 946b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Ramesvoid InstructionSimplifierVisitor::VisitAnd(HAnd* instruction) { 947b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames HConstant* input_cst = instruction->GetConstantRight(); 948b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames HInstruction* input_other = instruction->GetLeastConstantLeft(); 949b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames 950452c1b60120aee0883c3339b363f820b8d69c299Vladimir Marko if (input_cst != nullptr) { 951452c1b60120aee0883c3339b363f820b8d69c299Vladimir Marko int64_t value = Int64FromConstant(input_cst); 952452c1b60120aee0883c3339b363f820b8d69c299Vladimir Marko if (value == -1) { 953452c1b60120aee0883c3339b363f820b8d69c299Vladimir Marko // Replace code looking like 954452c1b60120aee0883c3339b363f820b8d69c299Vladimir Marko // AND dst, src, 0xFFF...FF 955452c1b60120aee0883c3339b363f820b8d69c299Vladimir Marko // with 956452c1b60120aee0883c3339b363f820b8d69c299Vladimir Marko // src 957452c1b60120aee0883c3339b363f820b8d69c299Vladimir Marko instruction->ReplaceWith(input_other); 958452c1b60120aee0883c3339b363f820b8d69c299Vladimir Marko instruction->GetBlock()->RemoveInstruction(instruction); 959452c1b60120aee0883c3339b363f820b8d69c299Vladimir Marko RecordSimplification(); 960452c1b60120aee0883c3339b363f820b8d69c299Vladimir Marko return; 961452c1b60120aee0883c3339b363f820b8d69c299Vladimir Marko } 962452c1b60120aee0883c3339b363f820b8d69c299Vladimir Marko // Eliminate And from UShr+And if the And-mask contains all the bits that 963452c1b60120aee0883c3339b363f820b8d69c299Vladimir Marko // can be non-zero after UShr. Transform Shr+And to UShr if the And-mask 964452c1b60120aee0883c3339b363f820b8d69c299Vladimir Marko // precisely clears the shifted-in sign bits. 965452c1b60120aee0883c3339b363f820b8d69c299Vladimir Marko if ((input_other->IsUShr() || input_other->IsShr()) && input_other->InputAt(1)->IsConstant()) { 966452c1b60120aee0883c3339b363f820b8d69c299Vladimir Marko size_t reg_bits = (instruction->GetResultType() == Primitive::kPrimLong) ? 64 : 32; 967452c1b60120aee0883c3339b363f820b8d69c299Vladimir Marko size_t shift = Int64FromConstant(input_other->InputAt(1)->AsConstant()) & (reg_bits - 1); 968452c1b60120aee0883c3339b363f820b8d69c299Vladimir Marko size_t num_tail_bits_set = CTZ(value + 1); 969452c1b60120aee0883c3339b363f820b8d69c299Vladimir Marko if ((num_tail_bits_set >= reg_bits - shift) && input_other->IsUShr()) { 970452c1b60120aee0883c3339b363f820b8d69c299Vladimir Marko // This AND clears only bits known to be clear, for example "(x >>> 24) & 0xff". 971452c1b60120aee0883c3339b363f820b8d69c299Vladimir Marko instruction->ReplaceWith(input_other); 972452c1b60120aee0883c3339b363f820b8d69c299Vladimir Marko instruction->GetBlock()->RemoveInstruction(instruction); 973452c1b60120aee0883c3339b363f820b8d69c299Vladimir Marko RecordSimplification(); 974452c1b60120aee0883c3339b363f820b8d69c299Vladimir Marko return; 975452c1b60120aee0883c3339b363f820b8d69c299Vladimir Marko } else if ((num_tail_bits_set == reg_bits - shift) && IsPowerOfTwo(value + 1) && 976452c1b60120aee0883c3339b363f820b8d69c299Vladimir Marko input_other->HasOnlyOneNonEnvironmentUse()) { 977452c1b60120aee0883c3339b363f820b8d69c299Vladimir Marko DCHECK(input_other->IsShr()); // For UShr, we would have taken the branch above. 978452c1b60120aee0883c3339b363f820b8d69c299Vladimir Marko // Replace SHR+AND with USHR, for example "(x >> 24) & 0xff" -> "x >>> 24". 979452c1b60120aee0883c3339b363f820b8d69c299Vladimir Marko HUShr* ushr = new (GetGraph()->GetArena()) HUShr(instruction->GetType(), 980452c1b60120aee0883c3339b363f820b8d69c299Vladimir Marko input_other->InputAt(0), 981452c1b60120aee0883c3339b363f820b8d69c299Vladimir Marko input_other->InputAt(1), 982452c1b60120aee0883c3339b363f820b8d69c299Vladimir Marko input_other->GetDexPc()); 983452c1b60120aee0883c3339b363f820b8d69c299Vladimir Marko instruction->GetBlock()->ReplaceAndRemoveInstructionWith(instruction, ushr); 984452c1b60120aee0883c3339b363f820b8d69c299Vladimir Marko input_other->GetBlock()->RemoveInstruction(input_other); 985452c1b60120aee0883c3339b363f820b8d69c299Vladimir Marko RecordSimplification(); 986452c1b60120aee0883c3339b363f820b8d69c299Vladimir Marko return; 987452c1b60120aee0883c3339b363f820b8d69c299Vladimir Marko } 988452c1b60120aee0883c3339b363f820b8d69c299Vladimir Marko } 989b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames } 990b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames 991b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames // We assume that GVN has run before, so we only perform a pointer comparison. 992b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames // If for some reason the values are equal but the pointers are different, we 993188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames // are still correct and only miss an optimization opportunity. 994b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames if (instruction->GetLeft() == instruction->GetRight()) { 995b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames // Replace code looking like 996b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames // AND dst, src, src 997b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames // with 998b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames // src 999b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames instruction->ReplaceWith(instruction->GetLeft()); 1000b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames instruction->GetBlock()->RemoveInstruction(instruction); 1001ca0e3a0c9f1fd5902dc40043b061d2f9b79ec098Alexandre Rames return; 1002b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames } 1003ca0e3a0c9f1fd5902dc40043b061d2f9b79ec098Alexandre Rames 1004ca0e3a0c9f1fd5902dc40043b061d2f9b79ec098Alexandre Rames TryDeMorganNegationFactoring(instruction); 1005b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames} 1006b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames 1007c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendellvoid InstructionSimplifierVisitor::VisitGreaterThan(HGreaterThan* condition) { 1008c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendell VisitCondition(condition); 1009c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendell} 1010c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendell 1011c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendellvoid InstructionSimplifierVisitor::VisitGreaterThanOrEqual(HGreaterThanOrEqual* condition) { 1012c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendell VisitCondition(condition); 1013c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendell} 1014c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendell 1015c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendellvoid InstructionSimplifierVisitor::VisitLessThan(HLessThan* condition) { 1016c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendell VisitCondition(condition); 1017c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendell} 1018c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendell 1019c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendellvoid InstructionSimplifierVisitor::VisitLessThanOrEqual(HLessThanOrEqual* condition) { 1020c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendell VisitCondition(condition); 1021c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendell} 1022c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendell 1023bdd7935c2adc3ad190ee87958e714a36f33cedaeAnton Shaminvoid InstructionSimplifierVisitor::VisitBelow(HBelow* condition) { 1024bdd7935c2adc3ad190ee87958e714a36f33cedaeAnton Shamin VisitCondition(condition); 1025bdd7935c2adc3ad190ee87958e714a36f33cedaeAnton Shamin} 1026bdd7935c2adc3ad190ee87958e714a36f33cedaeAnton Shamin 1027bdd7935c2adc3ad190ee87958e714a36f33cedaeAnton Shaminvoid InstructionSimplifierVisitor::VisitBelowOrEqual(HBelowOrEqual* condition) { 1028bdd7935c2adc3ad190ee87958e714a36f33cedaeAnton Shamin VisitCondition(condition); 1029bdd7935c2adc3ad190ee87958e714a36f33cedaeAnton Shamin} 1030bdd7935c2adc3ad190ee87958e714a36f33cedaeAnton Shamin 1031bdd7935c2adc3ad190ee87958e714a36f33cedaeAnton Shaminvoid InstructionSimplifierVisitor::VisitAbove(HAbove* condition) { 1032bdd7935c2adc3ad190ee87958e714a36f33cedaeAnton Shamin VisitCondition(condition); 1033bdd7935c2adc3ad190ee87958e714a36f33cedaeAnton Shamin} 1034bdd7935c2adc3ad190ee87958e714a36f33cedaeAnton Shamin 1035bdd7935c2adc3ad190ee87958e714a36f33cedaeAnton Shaminvoid InstructionSimplifierVisitor::VisitAboveOrEqual(HAboveOrEqual* condition) { 1036bdd7935c2adc3ad190ee87958e714a36f33cedaeAnton Shamin VisitCondition(condition); 1037bdd7935c2adc3ad190ee87958e714a36f33cedaeAnton Shamin} 1038e9f37600e98ba21308ad4f70d9d68cf6c057bdbeAart Bik 1039c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendellvoid InstructionSimplifierVisitor::VisitCondition(HCondition* condition) { 1040bdd7935c2adc3ad190ee87958e714a36f33cedaeAnton Shamin // Reverse condition if left is constant. Our code generators prefer constant 1041bdd7935c2adc3ad190ee87958e714a36f33cedaeAnton Shamin // on the right hand side. 1042bdd7935c2adc3ad190ee87958e714a36f33cedaeAnton Shamin if (condition->GetLeft()->IsConstant() && !condition->GetRight()->IsConstant()) { 1043bdd7935c2adc3ad190ee87958e714a36f33cedaeAnton Shamin HBasicBlock* block = condition->GetBlock(); 1044bdd7935c2adc3ad190ee87958e714a36f33cedaeAnton Shamin HCondition* replacement = GetOppositeConditionSwapOps(block->GetGraph()->GetArena(), condition); 1045bdd7935c2adc3ad190ee87958e714a36f33cedaeAnton Shamin // If it is a fp we must set the opposite bias. 1046bdd7935c2adc3ad190ee87958e714a36f33cedaeAnton Shamin if (replacement != nullptr) { 1047bdd7935c2adc3ad190ee87958e714a36f33cedaeAnton Shamin if (condition->IsLtBias()) { 1048bdd7935c2adc3ad190ee87958e714a36f33cedaeAnton Shamin replacement->SetBias(ComparisonBias::kGtBias); 1049bdd7935c2adc3ad190ee87958e714a36f33cedaeAnton Shamin } else if (condition->IsGtBias()) { 1050bdd7935c2adc3ad190ee87958e714a36f33cedaeAnton Shamin replacement->SetBias(ComparisonBias::kLtBias); 1051bdd7935c2adc3ad190ee87958e714a36f33cedaeAnton Shamin } 1052bdd7935c2adc3ad190ee87958e714a36f33cedaeAnton Shamin block->ReplaceAndRemoveInstructionWith(condition, replacement); 1053bdd7935c2adc3ad190ee87958e714a36f33cedaeAnton Shamin RecordSimplification(); 1054bdd7935c2adc3ad190ee87958e714a36f33cedaeAnton Shamin 1055bdd7935c2adc3ad190ee87958e714a36f33cedaeAnton Shamin condition = replacement; 1056bdd7935c2adc3ad190ee87958e714a36f33cedaeAnton Shamin } 1057bdd7935c2adc3ad190ee87958e714a36f33cedaeAnton Shamin } 1058c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendell 1059c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendell HInstruction* left = condition->GetLeft(); 1060c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendell HInstruction* right = condition->GetRight(); 1061bdd7935c2adc3ad190ee87958e714a36f33cedaeAnton Shamin 1062bdd7935c2adc3ad190ee87958e714a36f33cedaeAnton Shamin // Try to fold an HCompare into this HCondition. 1063bdd7935c2adc3ad190ee87958e714a36f33cedaeAnton Shamin 1064c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendell // We can only replace an HCondition which compares a Compare to 0. 1065c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendell // Both 'dx' and 'jack' generate a compare to 0 when compiling a 1066c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendell // condition with a long, float or double comparison as input. 1067c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendell if (!left->IsCompare() || !right->IsConstant() || right->AsIntConstant()->GetValue() != 0) { 1068c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendell // Conversion is not possible. 1069c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendell return; 1070c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendell } 1071c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendell 1072c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendell // Is the Compare only used for this purpose? 1073d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko if (!left->GetUses().HasExactlyOneElement()) { 1074c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendell // Someone else also wants the result of the compare. 1075c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendell return; 1076c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendell } 1077c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendell 1078d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko if (!left->GetEnvUses().empty()) { 1079c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendell // There is a reference to the compare result in an environment. Do we really need it? 1080c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendell if (GetGraph()->IsDebuggable()) { 1081c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendell return; 1082c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendell } 1083c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendell 1084c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendell // We have to ensure that there are no deopt points in the sequence. 1085c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendell if (left->HasAnyEnvironmentUseBefore(condition)) { 1086c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendell return; 1087c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendell } 1088c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendell } 1089c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendell 1090c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendell // Clean up any environment uses from the HCompare, if any. 1091c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendell left->RemoveEnvironmentUsers(); 1092c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendell 1093c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendell // We have decided to fold the HCompare into the HCondition. Transfer the information. 1094c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendell condition->SetBias(left->AsCompare()->GetBias()); 1095c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendell 1096c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendell // Replace the operands of the HCondition. 1097c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendell condition->ReplaceInput(left->InputAt(0), 0); 1098c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendell condition->ReplaceInput(left->InputAt(1), 1); 1099c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendell 1100c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendell // Remove the HCompare. 1101c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendell left->GetBlock()->RemoveInstruction(left); 1102c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendell 1103c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendell RecordSimplification(); 1104c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendell} 1105c470193cfc522fc818eb2eaab896aef9caf0c75aMark Mendell 1106b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Ramesvoid InstructionSimplifierVisitor::VisitDiv(HDiv* instruction) { 1107b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames HConstant* input_cst = instruction->GetConstantRight(); 1108b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames HInstruction* input_other = instruction->GetLeastConstantLeft(); 1109b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames Primitive::Type type = instruction->GetType(); 1110b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames 1111b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames if ((input_cst != nullptr) && input_cst->IsOne()) { 1112b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames // Replace code looking like 1113b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames // DIV dst, src, 1 1114b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames // with 1115b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames // src 1116b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames instruction->ReplaceWith(input_other); 1117b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames instruction->GetBlock()->RemoveInstruction(instruction); 1118b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames return; 1119b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames } 1120b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames 11210d22184ec9e5b1e958c031ac92c7f053de3a13a2Nicolas Geoffray if ((input_cst != nullptr) && input_cst->IsMinusOne()) { 1122b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames // Replace code looking like 1123b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames // DIV dst, src, -1 1124b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames // with 1125b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames // NEG dst, src 1126b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames instruction->GetBlock()->ReplaceAndRemoveInstructionWith( 11270d22184ec9e5b1e958c031ac92c7f053de3a13a2Nicolas Geoffray instruction, new (GetGraph()->GetArena()) HNeg(type, input_other)); 1128188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames RecordSimplification(); 11290d22184ec9e5b1e958c031ac92c7f053de3a13a2Nicolas Geoffray return; 11300d22184ec9e5b1e958c031ac92c7f053de3a13a2Nicolas Geoffray } 11310d22184ec9e5b1e958c031ac92c7f053de3a13a2Nicolas Geoffray 11320d22184ec9e5b1e958c031ac92c7f053de3a13a2Nicolas Geoffray if ((input_cst != nullptr) && Primitive::IsFloatingPointType(type)) { 11330d22184ec9e5b1e958c031ac92c7f053de3a13a2Nicolas Geoffray // Try replacing code looking like 11340d22184ec9e5b1e958c031ac92c7f053de3a13a2Nicolas Geoffray // DIV dst, src, constant 11350d22184ec9e5b1e958c031ac92c7f053de3a13a2Nicolas Geoffray // with 11360d22184ec9e5b1e958c031ac92c7f053de3a13a2Nicolas Geoffray // MUL dst, src, 1 / constant 11370d22184ec9e5b1e958c031ac92c7f053de3a13a2Nicolas Geoffray HConstant* reciprocal = nullptr; 11380d22184ec9e5b1e958c031ac92c7f053de3a13a2Nicolas Geoffray if (type == Primitive::Primitive::kPrimDouble) { 11390d22184ec9e5b1e958c031ac92c7f053de3a13a2Nicolas Geoffray double value = input_cst->AsDoubleConstant()->GetValue(); 11400d22184ec9e5b1e958c031ac92c7f053de3a13a2Nicolas Geoffray if (CanDivideByReciprocalMultiplyDouble(bit_cast<int64_t, double>(value))) { 11410d22184ec9e5b1e958c031ac92c7f053de3a13a2Nicolas Geoffray reciprocal = GetGraph()->GetDoubleConstant(1.0 / value); 11420d22184ec9e5b1e958c031ac92c7f053de3a13a2Nicolas Geoffray } 11430d22184ec9e5b1e958c031ac92c7f053de3a13a2Nicolas Geoffray } else { 11440d22184ec9e5b1e958c031ac92c7f053de3a13a2Nicolas Geoffray DCHECK_EQ(type, Primitive::kPrimFloat); 11450d22184ec9e5b1e958c031ac92c7f053de3a13a2Nicolas Geoffray float value = input_cst->AsFloatConstant()->GetValue(); 11460d22184ec9e5b1e958c031ac92c7f053de3a13a2Nicolas Geoffray if (CanDivideByReciprocalMultiplyFloat(bit_cast<int32_t, float>(value))) { 11470d22184ec9e5b1e958c031ac92c7f053de3a13a2Nicolas Geoffray reciprocal = GetGraph()->GetFloatConstant(1.0f / value); 11480d22184ec9e5b1e958c031ac92c7f053de3a13a2Nicolas Geoffray } 11490d22184ec9e5b1e958c031ac92c7f053de3a13a2Nicolas Geoffray } 11500d22184ec9e5b1e958c031ac92c7f053de3a13a2Nicolas Geoffray 11510d22184ec9e5b1e958c031ac92c7f053de3a13a2Nicolas Geoffray if (reciprocal != nullptr) { 11520d22184ec9e5b1e958c031ac92c7f053de3a13a2Nicolas Geoffray instruction->GetBlock()->ReplaceAndRemoveInstructionWith( 11530d22184ec9e5b1e958c031ac92c7f053de3a13a2Nicolas Geoffray instruction, new (GetGraph()->GetArena()) HMul(type, input_other, reciprocal)); 11540d22184ec9e5b1e958c031ac92c7f053de3a13a2Nicolas Geoffray RecordSimplification(); 11550d22184ec9e5b1e958c031ac92c7f053de3a13a2Nicolas Geoffray return; 11560d22184ec9e5b1e958c031ac92c7f053de3a13a2Nicolas Geoffray } 1157b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames } 1158b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames} 1159b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames 1160b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Ramesvoid InstructionSimplifierVisitor::VisitMul(HMul* instruction) { 1161b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames HConstant* input_cst = instruction->GetConstantRight(); 1162b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames HInstruction* input_other = instruction->GetLeastConstantLeft(); 1163b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames Primitive::Type type = instruction->GetType(); 1164b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames HBasicBlock* block = instruction->GetBlock(); 1165b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames ArenaAllocator* allocator = GetGraph()->GetArena(); 1166b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames 1167b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames if (input_cst == nullptr) { 1168b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames return; 1169b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames } 1170b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames 1171b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames if (input_cst->IsOne()) { 1172b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames // Replace code looking like 1173b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames // MUL dst, src, 1 1174b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames // with 1175b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames // src 1176b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames instruction->ReplaceWith(input_other); 1177b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames instruction->GetBlock()->RemoveInstruction(instruction); 1178b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames return; 1179b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames } 1180b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames 1181b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames if (input_cst->IsMinusOne() && 1182b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames (Primitive::IsFloatingPointType(type) || Primitive::IsIntOrLongType(type))) { 1183b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames // Replace code looking like 1184b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames // MUL dst, src, -1 1185b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames // with 1186b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames // NEG dst, src 1187b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames HNeg* neg = new (allocator) HNeg(type, input_other); 1188b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames block->ReplaceAndRemoveInstructionWith(instruction, neg); 1189188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames RecordSimplification(); 1190b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames return; 1191b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames } 1192b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames 1193b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames if (Primitive::IsFloatingPointType(type) && 1194b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames ((input_cst->IsFloatConstant() && input_cst->AsFloatConstant()->GetValue() == 2.0f) || 1195b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames (input_cst->IsDoubleConstant() && input_cst->AsDoubleConstant()->GetValue() == 2.0))) { 1196b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames // Replace code looking like 1197b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames // FP_MUL dst, src, 2.0 1198b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames // with 1199b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames // FP_ADD dst, src, src 1200b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames // The 'int' and 'long' cases are handled below. 1201b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames block->ReplaceAndRemoveInstructionWith(instruction, 1202b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames new (allocator) HAdd(type, input_other, input_other)); 1203188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames RecordSimplification(); 1204b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames return; 1205b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames } 1206b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames 1207b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames if (Primitive::IsIntOrLongType(type)) { 1208b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames int64_t factor = Int64FromConstant(input_cst); 1209538491967d1514a263e99d78379d743fcc896eefSerguei Katkov // Even though constant propagation also takes care of the zero case, other 1210538491967d1514a263e99d78379d743fcc896eefSerguei Katkov // optimizations can lead to having a zero multiplication. 1211538491967d1514a263e99d78379d743fcc896eefSerguei Katkov if (factor == 0) { 1212538491967d1514a263e99d78379d743fcc896eefSerguei Katkov // Replace code looking like 1213538491967d1514a263e99d78379d743fcc896eefSerguei Katkov // MUL dst, src, 0 1214538491967d1514a263e99d78379d743fcc896eefSerguei Katkov // with 1215538491967d1514a263e99d78379d743fcc896eefSerguei Katkov // 0 1216538491967d1514a263e99d78379d743fcc896eefSerguei Katkov instruction->ReplaceWith(input_cst); 1217538491967d1514a263e99d78379d743fcc896eefSerguei Katkov instruction->GetBlock()->RemoveInstruction(instruction); 1218538491967d1514a263e99d78379d743fcc896eefSerguei Katkov } else if (IsPowerOfTwo(factor)) { 1219b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames // Replace code looking like 1220b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames // MUL dst, src, pow_of_2 1221b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames // with 1222b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames // SHL dst, src, log2(pow_of_2) 12238d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil HIntConstant* shift = GetGraph()->GetIntConstant(WhichPowerOf2(factor)); 122422c4922c6b31e154a6814c4abe9015d9ba156911Roland Levillain HShl* shl = new (allocator) HShl(type, input_other, shift); 1225b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames block->ReplaceAndRemoveInstructionWith(instruction, shl); 1226188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames RecordSimplification(); 122738db785600757a832423e076b3cf0af3bee942d8Alexandre Rames } else if (IsPowerOfTwo(factor - 1)) { 122838db785600757a832423e076b3cf0af3bee942d8Alexandre Rames // Transform code looking like 122938db785600757a832423e076b3cf0af3bee942d8Alexandre Rames // MUL dst, src, (2^n + 1) 123038db785600757a832423e076b3cf0af3bee942d8Alexandre Rames // into 123138db785600757a832423e076b3cf0af3bee942d8Alexandre Rames // SHL tmp, src, n 123238db785600757a832423e076b3cf0af3bee942d8Alexandre Rames // ADD dst, src, tmp 123338db785600757a832423e076b3cf0af3bee942d8Alexandre Rames HShl* shl = new (allocator) HShl(type, 123438db785600757a832423e076b3cf0af3bee942d8Alexandre Rames input_other, 123538db785600757a832423e076b3cf0af3bee942d8Alexandre Rames GetGraph()->GetIntConstant(WhichPowerOf2(factor - 1))); 123638db785600757a832423e076b3cf0af3bee942d8Alexandre Rames HAdd* add = new (allocator) HAdd(type, input_other, shl); 123738db785600757a832423e076b3cf0af3bee942d8Alexandre Rames 123838db785600757a832423e076b3cf0af3bee942d8Alexandre Rames block->InsertInstructionBefore(shl, instruction); 123938db785600757a832423e076b3cf0af3bee942d8Alexandre Rames block->ReplaceAndRemoveInstructionWith(instruction, add); 124038db785600757a832423e076b3cf0af3bee942d8Alexandre Rames RecordSimplification(); 124138db785600757a832423e076b3cf0af3bee942d8Alexandre Rames } else if (IsPowerOfTwo(factor + 1)) { 124238db785600757a832423e076b3cf0af3bee942d8Alexandre Rames // Transform code looking like 124338db785600757a832423e076b3cf0af3bee942d8Alexandre Rames // MUL dst, src, (2^n - 1) 124438db785600757a832423e076b3cf0af3bee942d8Alexandre Rames // into 124538db785600757a832423e076b3cf0af3bee942d8Alexandre Rames // SHL tmp, src, n 124638db785600757a832423e076b3cf0af3bee942d8Alexandre Rames // SUB dst, tmp, src 124738db785600757a832423e076b3cf0af3bee942d8Alexandre Rames HShl* shl = new (allocator) HShl(type, 124838db785600757a832423e076b3cf0af3bee942d8Alexandre Rames input_other, 124938db785600757a832423e076b3cf0af3bee942d8Alexandre Rames GetGraph()->GetIntConstant(WhichPowerOf2(factor + 1))); 125038db785600757a832423e076b3cf0af3bee942d8Alexandre Rames HSub* sub = new (allocator) HSub(type, shl, input_other); 125138db785600757a832423e076b3cf0af3bee942d8Alexandre Rames 125238db785600757a832423e076b3cf0af3bee942d8Alexandre Rames block->InsertInstructionBefore(shl, instruction); 125338db785600757a832423e076b3cf0af3bee942d8Alexandre Rames block->ReplaceAndRemoveInstructionWith(instruction, sub); 125438db785600757a832423e076b3cf0af3bee942d8Alexandre Rames RecordSimplification(); 1255188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames } 1256188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames } 1257188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames} 1258188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames 1259188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Ramesvoid InstructionSimplifierVisitor::VisitNeg(HNeg* instruction) { 1260188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames HInstruction* input = instruction->GetInput(); 1261188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames if (input->IsNeg()) { 1262188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames // Replace code looking like 1263188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames // NEG tmp, src 1264188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames // NEG dst, tmp 1265188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames // with 1266188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames // src 1267188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames HNeg* previous_neg = input->AsNeg(); 1268188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames instruction->ReplaceWith(previous_neg->GetInput()); 1269188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames instruction->GetBlock()->RemoveInstruction(instruction); 1270188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames // We perform the optimization even if the input negation has environment 1271188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames // uses since it allows removing the current instruction. But we only delete 1272188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames // the input negation only if it is does not have any uses left. 1273188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames if (!previous_neg->HasUses()) { 1274188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames previous_neg->GetBlock()->RemoveInstruction(previous_neg); 1275188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames } 1276188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames RecordSimplification(); 1277188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames return; 1278188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames } 1279188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames 1280339dfc209ad93482269eea1386e79973abc313cfSerguei Katkov if (input->IsSub() && input->HasOnlyOneNonEnvironmentUse() && 1281339dfc209ad93482269eea1386e79973abc313cfSerguei Katkov !Primitive::IsFloatingPointType(input->GetType())) { 1282188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames // Replace code looking like 1283188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames // SUB tmp, a, b 1284188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames // NEG dst, tmp 1285188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames // with 1286188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames // SUB dst, b, a 1287188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames // We do not perform the optimization if the input subtraction has 1288188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames // environment uses or multiple non-environment uses as it could lead to 1289188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames // worse code. In particular, we do not want the live ranges of `a` and `b` 1290188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames // to be extended if we are not sure the initial 'SUB' instruction can be 1291188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames // removed. 1292339dfc209ad93482269eea1386e79973abc313cfSerguei Katkov // We do not perform optimization for fp because we could lose the sign of zero. 1293188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames HSub* sub = input->AsSub(); 1294188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames HSub* new_sub = 1295188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames new (GetGraph()->GetArena()) HSub(instruction->GetType(), sub->GetRight(), sub->GetLeft()); 1296188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames instruction->GetBlock()->ReplaceAndRemoveInstructionWith(instruction, new_sub); 1297188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames if (!sub->HasUses()) { 1298188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames sub->GetBlock()->RemoveInstruction(sub); 1299188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames } 1300188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames RecordSimplification(); 1301188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames } 1302188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames} 1303188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames 1304188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Ramesvoid InstructionSimplifierVisitor::VisitNot(HNot* instruction) { 1305188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames HInstruction* input = instruction->GetInput(); 1306188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames if (input->IsNot()) { 1307188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames // Replace code looking like 1308188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames // NOT tmp, src 1309188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames // NOT dst, tmp 1310188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames // with 1311188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames // src 1312188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames // We perform the optimization even if the input negation has environment 1313188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames // uses since it allows removing the current instruction. But we only delete 1314188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames // the input negation only if it is does not have any uses left. 1315188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames HNot* previous_not = input->AsNot(); 1316188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames instruction->ReplaceWith(previous_not->GetInput()); 1317188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames instruction->GetBlock()->RemoveInstruction(instruction); 1318188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames if (!previous_not->HasUses()) { 1319188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames previous_not->GetBlock()->RemoveInstruction(previous_not); 1320b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames } 1321188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames RecordSimplification(); 1322b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames } 1323b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames} 1324b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames 1325b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Ramesvoid InstructionSimplifierVisitor::VisitOr(HOr* instruction) { 1326b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames HConstant* input_cst = instruction->GetConstantRight(); 1327b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames HInstruction* input_other = instruction->GetLeastConstantLeft(); 1328b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames 13291a65388f1d86bb232c2e44fecb44cebe13105d2eRoland Levillain if ((input_cst != nullptr) && input_cst->IsZeroBitPattern()) { 1330b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames // Replace code looking like 1331b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames // OR dst, src, 0 1332b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames // with 1333b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames // src 1334b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames instruction->ReplaceWith(input_other); 1335b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames instruction->GetBlock()->RemoveInstruction(instruction); 1336b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames return; 1337b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames } 1338b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames 1339b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames // We assume that GVN has run before, so we only perform a pointer comparison. 1340b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames // If for some reason the values are equal but the pointers are different, we 1341188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames // are still correct and only miss an optimization opportunity. 1342b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames if (instruction->GetLeft() == instruction->GetRight()) { 1343b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames // Replace code looking like 1344b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames // OR dst, src, src 1345b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames // with 1346b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames // src 1347b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames instruction->ReplaceWith(instruction->GetLeft()); 1348b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames instruction->GetBlock()->RemoveInstruction(instruction); 134940a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling return; 1350b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames } 135140a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling 1352ca0e3a0c9f1fd5902dc40043b061d2f9b79ec098Alexandre Rames if (TryDeMorganNegationFactoring(instruction)) return; 1353ca0e3a0c9f1fd5902dc40043b061d2f9b79ec098Alexandre Rames 135440a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling TryReplaceWithRotate(instruction); 1355b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames} 1356b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames 1357b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Ramesvoid InstructionSimplifierVisitor::VisitShl(HShl* instruction) { 1358b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames VisitShift(instruction); 1359b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames} 1360b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames 1361b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Ramesvoid InstructionSimplifierVisitor::VisitShr(HShr* instruction) { 1362b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames VisitShift(instruction); 1363b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames} 1364b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames 1365b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Ramesvoid InstructionSimplifierVisitor::VisitSub(HSub* instruction) { 1366b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames HConstant* input_cst = instruction->GetConstantRight(); 1367b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames HInstruction* input_other = instruction->GetLeastConstantLeft(); 1368b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames 1369115b53f609e74672fa93eea1845bb17340d5112aSerguei Katkov Primitive::Type type = instruction->GetType(); 1370115b53f609e74672fa93eea1845bb17340d5112aSerguei Katkov if (Primitive::IsFloatingPointType(type)) { 1371115b53f609e74672fa93eea1845bb17340d5112aSerguei Katkov return; 1372115b53f609e74672fa93eea1845bb17340d5112aSerguei Katkov } 1373115b53f609e74672fa93eea1845bb17340d5112aSerguei Katkov 13741a65388f1d86bb232c2e44fecb44cebe13105d2eRoland Levillain if ((input_cst != nullptr) && input_cst->IsArithmeticZero()) { 1375b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames // Replace code looking like 1376b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames // SUB dst, src, 0 1377b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames // with 1378b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames // src 1379115b53f609e74672fa93eea1845bb17340d5112aSerguei Katkov // Note that we cannot optimize `x - 0.0` to `x` for floating-point. When 1380115b53f609e74672fa93eea1845bb17340d5112aSerguei Katkov // `x` is `-0.0`, the former expression yields `0.0`, while the later 1381115b53f609e74672fa93eea1845bb17340d5112aSerguei Katkov // yields `-0.0`. 1382b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames instruction->ReplaceWith(input_other); 1383b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames instruction->GetBlock()->RemoveInstruction(instruction); 1384b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames return; 1385b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames } 1386b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames 1387b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames HBasicBlock* block = instruction->GetBlock(); 1388b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames ArenaAllocator* allocator = GetGraph()->GetArena(); 1389b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames 1390188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames HInstruction* left = instruction->GetLeft(); 1391188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames HInstruction* right = instruction->GetRight(); 1392188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames if (left->IsConstant()) { 1393188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames if (Int64FromConstant(left->AsConstant()) == 0) { 1394b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames // Replace code looking like 1395b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames // SUB dst, 0, src 1396b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames // with 1397b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames // NEG dst, src 1398188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames // Note that we cannot optimize `0.0 - x` to `-x` for floating-point. When 1399b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames // `x` is `0.0`, the former expression yields `0.0`, while the later 1400b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames // yields `-0.0`. 1401188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames HNeg* neg = new (allocator) HNeg(type, right); 1402b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames block->ReplaceAndRemoveInstructionWith(instruction, neg); 1403188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames RecordSimplification(); 1404188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames return; 1405188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames } 1406188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames } 1407188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames 1408188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames if (left->IsNeg() && right->IsNeg()) { 1409188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames if (TryMoveNegOnInputsAfterBinop(instruction)) { 1410188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames return; 1411b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames } 1412b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames } 1413188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames 1414188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames if (right->IsNeg() && right->HasOnlyOneNonEnvironmentUse()) { 1415188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames // Replace code looking like 1416188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames // NEG tmp, b 1417188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames // SUB dst, a, tmp 1418188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames // with 1419188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames // ADD dst, a, b 1420188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames HAdd* add = new(GetGraph()->GetArena()) HAdd(type, left, right->AsNeg()->GetInput()); 1421188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames instruction->GetBlock()->ReplaceAndRemoveInstructionWith(instruction, add); 1422188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames RecordSimplification(); 1423188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames right->GetBlock()->RemoveInstruction(right); 1424188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames return; 1425188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames } 1426188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames 1427188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames if (left->IsNeg() && left->HasOnlyOneNonEnvironmentUse()) { 1428188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames // Replace code looking like 1429188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames // NEG tmp, a 1430188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames // SUB dst, tmp, b 1431188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames // with 1432188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames // ADD tmp, a, b 1433188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames // NEG dst, tmp 1434188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames // The second version is not intrinsically better, but enables more 1435188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames // transformations. 1436188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames HAdd* add = new(GetGraph()->GetArena()) HAdd(type, left->AsNeg()->GetInput(), right); 1437188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames instruction->GetBlock()->InsertInstructionBefore(add, instruction); 1438188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames HNeg* neg = new (GetGraph()->GetArena()) HNeg(instruction->GetType(), add); 1439188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames instruction->GetBlock()->InsertInstructionBefore(neg, instruction); 1440188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames instruction->ReplaceWith(neg); 1441188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames instruction->GetBlock()->RemoveInstruction(instruction); 1442188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames RecordSimplification(); 1443188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames left->GetBlock()->RemoveInstruction(left); 1444188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames } 1445b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames} 1446b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames 1447b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Ramesvoid InstructionSimplifierVisitor::VisitUShr(HUShr* instruction) { 1448b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames VisitShift(instruction); 1449b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames} 1450b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames 1451b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Ramesvoid InstructionSimplifierVisitor::VisitXor(HXor* instruction) { 1452b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames HConstant* input_cst = instruction->GetConstantRight(); 1453b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames HInstruction* input_other = instruction->GetLeastConstantLeft(); 1454b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames 14551a65388f1d86bb232c2e44fecb44cebe13105d2eRoland Levillain if ((input_cst != nullptr) && input_cst->IsZeroBitPattern()) { 1456b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames // Replace code looking like 1457b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames // XOR dst, src, 0 1458b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames // with 1459b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames // src 1460b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames instruction->ReplaceWith(input_other); 1461b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames instruction->GetBlock()->RemoveInstruction(instruction); 1462b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames return; 1463b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames } 1464b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames 1465b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames if ((input_cst != nullptr) && AreAllBitsSet(input_cst)) { 1466b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames // Replace code looking like 1467b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames // XOR dst, src, 0xFFF...FF 1468b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames // with 1469b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames // NOT dst, src 1470b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames HNot* bitwise_not = new (GetGraph()->GetArena()) HNot(instruction->GetType(), input_other); 1471b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames instruction->GetBlock()->ReplaceAndRemoveInstructionWith(instruction, bitwise_not); 1472188d4316a880ae24aed315aa52dc503c4fcb1ec7Alexandre Rames RecordSimplification(); 1473b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames return; 1474b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames } 147540a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling 1476ca0e3a0c9f1fd5902dc40043b061d2f9b79ec098Alexandre Rames HInstruction* left = instruction->GetLeft(); 1477ca0e3a0c9f1fd5902dc40043b061d2f9b79ec098Alexandre Rames HInstruction* right = instruction->GetRight(); 14789f98025ba5541641cfa9abb7b9cf30332d91fad1Alexandre Rames if (((left->IsNot() && right->IsNot()) || 14799f98025ba5541641cfa9abb7b9cf30332d91fad1Alexandre Rames (left->IsBooleanNot() && right->IsBooleanNot())) && 1480ca0e3a0c9f1fd5902dc40043b061d2f9b79ec098Alexandre Rames left->HasOnlyOneNonEnvironmentUse() && 1481ca0e3a0c9f1fd5902dc40043b061d2f9b79ec098Alexandre Rames right->HasOnlyOneNonEnvironmentUse()) { 1482ca0e3a0c9f1fd5902dc40043b061d2f9b79ec098Alexandre Rames // Replace code looking like 1483ca0e3a0c9f1fd5902dc40043b061d2f9b79ec098Alexandre Rames // NOT nota, a 1484ca0e3a0c9f1fd5902dc40043b061d2f9b79ec098Alexandre Rames // NOT notb, b 1485ca0e3a0c9f1fd5902dc40043b061d2f9b79ec098Alexandre Rames // XOR dst, nota, notb 1486ca0e3a0c9f1fd5902dc40043b061d2f9b79ec098Alexandre Rames // with 1487ca0e3a0c9f1fd5902dc40043b061d2f9b79ec098Alexandre Rames // XOR dst, a, b 14889f98025ba5541641cfa9abb7b9cf30332d91fad1Alexandre Rames instruction->ReplaceInput(left->InputAt(0), 0); 14899f98025ba5541641cfa9abb7b9cf30332d91fad1Alexandre Rames instruction->ReplaceInput(right->InputAt(0), 1); 1490ca0e3a0c9f1fd5902dc40043b061d2f9b79ec098Alexandre Rames left->GetBlock()->RemoveInstruction(left); 1491ca0e3a0c9f1fd5902dc40043b061d2f9b79ec098Alexandre Rames right->GetBlock()->RemoveInstruction(right); 1492ca0e3a0c9f1fd5902dc40043b061d2f9b79ec098Alexandre Rames RecordSimplification(); 1493ca0e3a0c9f1fd5902dc40043b061d2f9b79ec098Alexandre Rames return; 1494ca0e3a0c9f1fd5902dc40043b061d2f9b79ec098Alexandre Rames } 1495ca0e3a0c9f1fd5902dc40043b061d2f9b79ec098Alexandre Rames 149640a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling TryReplaceWithRotate(instruction); 1497b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames} 1498b2fd7bca70b580921eebf7c45769c39d2dfd8a5aAlexandre Rames 1499ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffrayvoid InstructionSimplifierVisitor::SimplifyStringEquals(HInvoke* instruction) { 1500ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray HInstruction* argument = instruction->InputAt(1); 1501ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray HInstruction* receiver = instruction->InputAt(0); 1502ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray if (receiver == argument) { 1503ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray // Because String.equals is an instance call, the receiver is 1504ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray // a null check if we don't know it's null. The argument however, will 1505ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray // be the actual object. So we cannot end up in a situation where both 1506ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray // are equal but could be null. 1507ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray DCHECK(CanEnsureNotNullAt(argument, instruction)); 1508ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray instruction->ReplaceWith(GetGraph()->GetIntConstant(1)); 1509ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray instruction->GetBlock()->RemoveInstruction(instruction); 1510ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray } else { 1511ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray StringEqualsOptimizations optimizations(instruction); 1512ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray if (CanEnsureNotNullAt(argument, instruction)) { 1513ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray optimizations.SetArgumentNotNull(); 1514ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray } 1515ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray ScopedObjectAccess soa(Thread::Current()); 1516ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray ReferenceTypeInfo argument_rti = argument->GetReferenceTypeInfo(); 1517ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray if (argument_rti.IsValid() && argument_rti.IsStringClass()) { 1518ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray optimizations.SetArgumentIsString(); 1519ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray } 1520ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray } 1521ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray} 1522ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray 152322c4922c6b31e154a6814c4abe9015d9ba156911Roland Levillainvoid InstructionSimplifierVisitor::SimplifyRotate(HInvoke* invoke, 152422c4922c6b31e154a6814c4abe9015d9ba156911Roland Levillain bool is_left, 152522c4922c6b31e154a6814c4abe9015d9ba156911Roland Levillain Primitive::Type type) { 152640a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling DCHECK(invoke->IsInvokeStaticOrDirect()); 152740a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling DCHECK_EQ(invoke->GetOriginalInvokeType(), InvokeType::kStatic); 152840a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling HInstruction* value = invoke->InputAt(0); 152940a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling HInstruction* distance = invoke->InputAt(1); 153040a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling // Replace the invoke with an HRor. 153140a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling if (is_left) { 1532937e6cd515bbe7ff2f255c8fcd40bf1a575a9a16Roland Levillain // Unconditionally set the type of the negated distance to `int`, 1533937e6cd515bbe7ff2f255c8fcd40bf1a575a9a16Roland Levillain // as shift and rotate operations expect a 32-bit (or narrower) 1534937e6cd515bbe7ff2f255c8fcd40bf1a575a9a16Roland Levillain // value for their distance input. 1535937e6cd515bbe7ff2f255c8fcd40bf1a575a9a16Roland Levillain distance = new (GetGraph()->GetArena()) HNeg(Primitive::kPrimInt, distance); 153640a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling invoke->GetBlock()->InsertInstructionBefore(distance, invoke); 153740a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling } 153822c4922c6b31e154a6814c4abe9015d9ba156911Roland Levillain HRor* ror = new (GetGraph()->GetArena()) HRor(type, value, distance); 153940a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling invoke->GetBlock()->ReplaceAndRemoveInstructionWith(invoke, ror); 154040a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling // Remove ClinitCheck and LoadClass, if possible. 154140a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling HInstruction* clinit = invoke->InputAt(invoke->InputCount() - 1); 154240a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling if (clinit->IsClinitCheck() && !clinit->HasUses()) { 154340a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling clinit->GetBlock()->RemoveInstruction(clinit); 154440a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling HInstruction* ldclass = clinit->InputAt(0); 154540a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling if (ldclass->IsLoadClass() && !ldclass->HasUses()) { 154640a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling ldclass->GetBlock()->RemoveInstruction(ldclass); 154740a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling } 154840a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling } 154940a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling} 155040a04bf64e5837fa48aceaffe970c9984c94084aScott Wakeling 1551ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffraystatic bool IsArrayLengthOf(HInstruction* potential_length, HInstruction* potential_array) { 1552ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray if (potential_length->IsArrayLength()) { 1553ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray return potential_length->InputAt(0) == potential_array; 1554ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray } 1555ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray 1556ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray if (potential_array->IsNewArray()) { 1557ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray return potential_array->InputAt(0) == potential_length; 1558ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray } 1559ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray 1560ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray return false; 1561ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray} 1562ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray 1563ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffrayvoid InstructionSimplifierVisitor::SimplifySystemArrayCopy(HInvoke* instruction) { 1564ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray HInstruction* source = instruction->InputAt(0); 1565ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray HInstruction* destination = instruction->InputAt(2); 1566ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray HInstruction* count = instruction->InputAt(4); 1567ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray SystemArrayCopyOptimizations optimizations(instruction); 1568ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray if (CanEnsureNotNullAt(source, instruction)) { 1569ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray optimizations.SetSourceIsNotNull(); 1570ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray } 1571ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray if (CanEnsureNotNullAt(destination, instruction)) { 1572ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray optimizations.SetDestinationIsNotNull(); 1573ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray } 1574ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray if (destination == source) { 1575ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray optimizations.SetDestinationIsSource(); 1576ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray } 1577ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray 1578ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray if (IsArrayLengthOf(count, source)) { 1579ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray optimizations.SetCountIsSourceLength(); 1580ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray } 1581ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray 1582ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray if (IsArrayLengthOf(count, destination)) { 1583ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray optimizations.SetCountIsDestinationLength(); 1584ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray } 1585ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray 1586ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray { 1587ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray ScopedObjectAccess soa(Thread::Current()); 1588ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray ReferenceTypeInfo destination_rti = destination->GetReferenceTypeInfo(); 1589ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray if (destination_rti.IsValid()) { 1590ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray if (destination_rti.IsObjectArray()) { 1591ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray if (destination_rti.IsExact()) { 1592ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray optimizations.SetDoesNotNeedTypeCheck(); 1593ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray } 1594ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray optimizations.SetDestinationIsTypedObjectArray(); 1595a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray } 1596ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray if (destination_rti.IsPrimitiveArrayClass()) { 1597ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray optimizations.SetDestinationIsPrimitiveArray(); 1598ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray } else if (destination_rti.IsNonPrimitiveArrayClass()) { 1599ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray optimizations.SetDestinationIsNonPrimitiveArray(); 1600a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray } 1601a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray } 1602ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray ReferenceTypeInfo source_rti = source->GetReferenceTypeInfo(); 1603ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray if (source_rti.IsValid()) { 1604ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray if (destination_rti.IsValid() && destination_rti.CanArrayHoldValuesOf(source_rti)) { 1605ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray optimizations.SetDoesNotNeedTypeCheck(); 1606ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray } 1607ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray if (source_rti.IsPrimitiveArrayClass()) { 1608ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray optimizations.SetSourceIsPrimitiveArray(); 1609ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray } else if (source_rti.IsNonPrimitiveArrayClass()) { 1610ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray optimizations.SetSourceIsNonPrimitiveArray(); 1611ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray } 1612ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray } 1613ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray } 1614ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray} 1615ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray 1616a5c4a4060edd03eda017abebc85f24cffb083ba7Roland Levillainvoid InstructionSimplifierVisitor::SimplifyCompare(HInvoke* invoke, 1617a5c4a4060edd03eda017abebc85f24cffb083ba7Roland Levillain bool is_signum, 1618a5c4a4060edd03eda017abebc85f24cffb083ba7Roland Levillain Primitive::Type type) { 1619a19616e3363276e7f2c471eb2839fb16f1d43f27Aart Bik DCHECK(invoke->IsInvokeStaticOrDirect()); 1620a19616e3363276e7f2c471eb2839fb16f1d43f27Aart Bik uint32_t dex_pc = invoke->GetDexPc(); 1621a19616e3363276e7f2c471eb2839fb16f1d43f27Aart Bik HInstruction* left = invoke->InputAt(0); 1622a19616e3363276e7f2c471eb2839fb16f1d43f27Aart Bik HInstruction* right; 1623a19616e3363276e7f2c471eb2839fb16f1d43f27Aart Bik if (!is_signum) { 1624a19616e3363276e7f2c471eb2839fb16f1d43f27Aart Bik right = invoke->InputAt(1); 1625a19616e3363276e7f2c471eb2839fb16f1d43f27Aart Bik } else if (type == Primitive::kPrimLong) { 1626a19616e3363276e7f2c471eb2839fb16f1d43f27Aart Bik right = GetGraph()->GetLongConstant(0); 1627a19616e3363276e7f2c471eb2839fb16f1d43f27Aart Bik } else { 1628a19616e3363276e7f2c471eb2839fb16f1d43f27Aart Bik right = GetGraph()->GetIntConstant(0); 1629a19616e3363276e7f2c471eb2839fb16f1d43f27Aart Bik } 1630a19616e3363276e7f2c471eb2839fb16f1d43f27Aart Bik HCompare* compare = new (GetGraph()->GetArena()) 1631a19616e3363276e7f2c471eb2839fb16f1d43f27Aart Bik HCompare(type, left, right, ComparisonBias::kNoBias, dex_pc); 1632a19616e3363276e7f2c471eb2839fb16f1d43f27Aart Bik invoke->GetBlock()->ReplaceAndRemoveInstructionWith(invoke, compare); 1633a19616e3363276e7f2c471eb2839fb16f1d43f27Aart Bik} 1634a19616e3363276e7f2c471eb2839fb16f1d43f27Aart Bik 163575a38b24801bd4d27c95acef969930f626dd11daAart Bikvoid InstructionSimplifierVisitor::SimplifyIsNaN(HInvoke* invoke) { 163675a38b24801bd4d27c95acef969930f626dd11daAart Bik DCHECK(invoke->IsInvokeStaticOrDirect()); 163775a38b24801bd4d27c95acef969930f626dd11daAart Bik uint32_t dex_pc = invoke->GetDexPc(); 163875a38b24801bd4d27c95acef969930f626dd11daAart Bik // IsNaN(x) is the same as x != x. 163975a38b24801bd4d27c95acef969930f626dd11daAart Bik HInstruction* x = invoke->InputAt(0); 164075a38b24801bd4d27c95acef969930f626dd11daAart Bik HCondition* condition = new (GetGraph()->GetArena()) HNotEqual(x, x, dex_pc); 16418ffc1fa556eb92f50a0bd3d5eab56435fff206f6Aart Bik condition->SetBias(ComparisonBias::kLtBias); 164275a38b24801bd4d27c95acef969930f626dd11daAart Bik invoke->GetBlock()->ReplaceAndRemoveInstructionWith(invoke, condition); 164375a38b24801bd4d27c95acef969930f626dd11daAart Bik} 164475a38b24801bd4d27c95acef969930f626dd11daAart Bik 16452a6aad9d388bd29bff04aeec3eb9429d436d1873Aart Bikvoid InstructionSimplifierVisitor::SimplifyFP2Int(HInvoke* invoke) { 16462a6aad9d388bd29bff04aeec3eb9429d436d1873Aart Bik DCHECK(invoke->IsInvokeStaticOrDirect()); 16472a6aad9d388bd29bff04aeec3eb9429d436d1873Aart Bik uint32_t dex_pc = invoke->GetDexPc(); 16482a6aad9d388bd29bff04aeec3eb9429d436d1873Aart Bik HInstruction* x = invoke->InputAt(0); 16492a6aad9d388bd29bff04aeec3eb9429d436d1873Aart Bik Primitive::Type type = x->GetType(); 16502a6aad9d388bd29bff04aeec3eb9429d436d1873Aart Bik // Set proper bit pattern for NaN and replace intrinsic with raw version. 16512a6aad9d388bd29bff04aeec3eb9429d436d1873Aart Bik HInstruction* nan; 16522a6aad9d388bd29bff04aeec3eb9429d436d1873Aart Bik if (type == Primitive::kPrimDouble) { 16532a6aad9d388bd29bff04aeec3eb9429d436d1873Aart Bik nan = GetGraph()->GetLongConstant(0x7ff8000000000000L); 16542a6aad9d388bd29bff04aeec3eb9429d436d1873Aart Bik invoke->SetIntrinsic(Intrinsics::kDoubleDoubleToRawLongBits, 16552a6aad9d388bd29bff04aeec3eb9429d436d1873Aart Bik kNeedsEnvironmentOrCache, 16562a6aad9d388bd29bff04aeec3eb9429d436d1873Aart Bik kNoSideEffects, 16572a6aad9d388bd29bff04aeec3eb9429d436d1873Aart Bik kNoThrow); 16582a6aad9d388bd29bff04aeec3eb9429d436d1873Aart Bik } else { 16592a6aad9d388bd29bff04aeec3eb9429d436d1873Aart Bik DCHECK_EQ(type, Primitive::kPrimFloat); 16602a6aad9d388bd29bff04aeec3eb9429d436d1873Aart Bik nan = GetGraph()->GetIntConstant(0x7fc00000); 16612a6aad9d388bd29bff04aeec3eb9429d436d1873Aart Bik invoke->SetIntrinsic(Intrinsics::kFloatFloatToRawIntBits, 16622a6aad9d388bd29bff04aeec3eb9429d436d1873Aart Bik kNeedsEnvironmentOrCache, 16632a6aad9d388bd29bff04aeec3eb9429d436d1873Aart Bik kNoSideEffects, 16642a6aad9d388bd29bff04aeec3eb9429d436d1873Aart Bik kNoThrow); 16652a6aad9d388bd29bff04aeec3eb9429d436d1873Aart Bik } 16662a6aad9d388bd29bff04aeec3eb9429d436d1873Aart Bik // Test IsNaN(x), which is the same as x != x. 16672a6aad9d388bd29bff04aeec3eb9429d436d1873Aart Bik HCondition* condition = new (GetGraph()->GetArena()) HNotEqual(x, x, dex_pc); 16682a6aad9d388bd29bff04aeec3eb9429d436d1873Aart Bik condition->SetBias(ComparisonBias::kLtBias); 16692a6aad9d388bd29bff04aeec3eb9429d436d1873Aart Bik invoke->GetBlock()->InsertInstructionBefore(condition, invoke->GetNext()); 16702a6aad9d388bd29bff04aeec3eb9429d436d1873Aart Bik // Select between the two. 16712a6aad9d388bd29bff04aeec3eb9429d436d1873Aart Bik HInstruction* select = new (GetGraph()->GetArena()) HSelect(condition, nan, invoke, dex_pc); 16722a6aad9d388bd29bff04aeec3eb9429d436d1873Aart Bik invoke->GetBlock()->InsertInstructionBefore(select, condition->GetNext()); 16732a6aad9d388bd29bff04aeec3eb9429d436d1873Aart Bik invoke->ReplaceWithExceptInReplacementAtIndex(select, 0); // false at index 0 16742a6aad9d388bd29bff04aeec3eb9429d436d1873Aart Bik} 16752a6aad9d388bd29bff04aeec3eb9429d436d1873Aart Bik 16761193259cb37c9763a111825aa04718a409d07145Aart Bikvoid InstructionSimplifierVisitor::SimplifyMemBarrier(HInvoke* invoke, MemBarrierKind barrier_kind) { 16771193259cb37c9763a111825aa04718a409d07145Aart Bik uint32_t dex_pc = invoke->GetDexPc(); 16781193259cb37c9763a111825aa04718a409d07145Aart Bik HMemoryBarrier* mem_barrier = new (GetGraph()->GetArena()) HMemoryBarrier(barrier_kind, dex_pc); 16791193259cb37c9763a111825aa04718a409d07145Aart Bik invoke->GetBlock()->ReplaceAndRemoveInstructionWith(invoke, mem_barrier); 16801193259cb37c9763a111825aa04718a409d07145Aart Bik} 16811193259cb37c9763a111825aa04718a409d07145Aart Bik 1682ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffrayvoid InstructionSimplifierVisitor::VisitInvoke(HInvoke* instruction) { 16832a6aad9d388bd29bff04aeec3eb9429d436d1873Aart Bik switch (instruction->GetIntrinsic()) { 16842a6aad9d388bd29bff04aeec3eb9429d436d1873Aart Bik case Intrinsics::kStringEquals: 16852a6aad9d388bd29bff04aeec3eb9429d436d1873Aart Bik SimplifyStringEquals(instruction); 16862a6aad9d388bd29bff04aeec3eb9429d436d1873Aart Bik break; 16872a6aad9d388bd29bff04aeec3eb9429d436d1873Aart Bik case Intrinsics::kSystemArrayCopy: 16882a6aad9d388bd29bff04aeec3eb9429d436d1873Aart Bik SimplifySystemArrayCopy(instruction); 16892a6aad9d388bd29bff04aeec3eb9429d436d1873Aart Bik break; 16902a6aad9d388bd29bff04aeec3eb9429d436d1873Aart Bik case Intrinsics::kIntegerRotateRight: 169122c4922c6b31e154a6814c4abe9015d9ba156911Roland Levillain SimplifyRotate(instruction, /* is_left */ false, Primitive::kPrimInt); 169222c4922c6b31e154a6814c4abe9015d9ba156911Roland Levillain break; 16932a6aad9d388bd29bff04aeec3eb9429d436d1873Aart Bik case Intrinsics::kLongRotateRight: 169422c4922c6b31e154a6814c4abe9015d9ba156911Roland Levillain SimplifyRotate(instruction, /* is_left */ false, Primitive::kPrimLong); 16952a6aad9d388bd29bff04aeec3eb9429d436d1873Aart Bik break; 16962a6aad9d388bd29bff04aeec3eb9429d436d1873Aart Bik case Intrinsics::kIntegerRotateLeft: 169722c4922c6b31e154a6814c4abe9015d9ba156911Roland Levillain SimplifyRotate(instruction, /* is_left */ true, Primitive::kPrimInt); 169822c4922c6b31e154a6814c4abe9015d9ba156911Roland Levillain break; 16992a6aad9d388bd29bff04aeec3eb9429d436d1873Aart Bik case Intrinsics::kLongRotateLeft: 170022c4922c6b31e154a6814c4abe9015d9ba156911Roland Levillain SimplifyRotate(instruction, /* is_left */ true, Primitive::kPrimLong); 17012a6aad9d388bd29bff04aeec3eb9429d436d1873Aart Bik break; 17022a6aad9d388bd29bff04aeec3eb9429d436d1873Aart Bik case Intrinsics::kIntegerCompare: 1703a5c4a4060edd03eda017abebc85f24cffb083ba7Roland Levillain SimplifyCompare(instruction, /* is_signum */ false, Primitive::kPrimInt); 1704a5c4a4060edd03eda017abebc85f24cffb083ba7Roland Levillain break; 17052a6aad9d388bd29bff04aeec3eb9429d436d1873Aart Bik case Intrinsics::kLongCompare: 1706a5c4a4060edd03eda017abebc85f24cffb083ba7Roland Levillain SimplifyCompare(instruction, /* is_signum */ false, Primitive::kPrimLong); 17072a6aad9d388bd29bff04aeec3eb9429d436d1873Aart Bik break; 17082a6aad9d388bd29bff04aeec3eb9429d436d1873Aart Bik case Intrinsics::kIntegerSignum: 1709a5c4a4060edd03eda017abebc85f24cffb083ba7Roland Levillain SimplifyCompare(instruction, /* is_signum */ true, Primitive::kPrimInt); 1710a5c4a4060edd03eda017abebc85f24cffb083ba7Roland Levillain break; 17112a6aad9d388bd29bff04aeec3eb9429d436d1873Aart Bik case Intrinsics::kLongSignum: 1712a5c4a4060edd03eda017abebc85f24cffb083ba7Roland Levillain SimplifyCompare(instruction, /* is_signum */ true, Primitive::kPrimLong); 17132a6aad9d388bd29bff04aeec3eb9429d436d1873Aart Bik break; 17142a6aad9d388bd29bff04aeec3eb9429d436d1873Aart Bik case Intrinsics::kFloatIsNaN: 17152a6aad9d388bd29bff04aeec3eb9429d436d1873Aart Bik case Intrinsics::kDoubleIsNaN: 17162a6aad9d388bd29bff04aeec3eb9429d436d1873Aart Bik SimplifyIsNaN(instruction); 17172a6aad9d388bd29bff04aeec3eb9429d436d1873Aart Bik break; 17182a6aad9d388bd29bff04aeec3eb9429d436d1873Aart Bik case Intrinsics::kFloatFloatToIntBits: 17192a6aad9d388bd29bff04aeec3eb9429d436d1873Aart Bik case Intrinsics::kDoubleDoubleToLongBits: 17202a6aad9d388bd29bff04aeec3eb9429d436d1873Aart Bik SimplifyFP2Int(instruction); 17212a6aad9d388bd29bff04aeec3eb9429d436d1873Aart Bik break; 17221193259cb37c9763a111825aa04718a409d07145Aart Bik case Intrinsics::kUnsafeLoadFence: 17231193259cb37c9763a111825aa04718a409d07145Aart Bik SimplifyMemBarrier(instruction, MemBarrierKind::kLoadAny); 17241193259cb37c9763a111825aa04718a409d07145Aart Bik break; 17251193259cb37c9763a111825aa04718a409d07145Aart Bik case Intrinsics::kUnsafeStoreFence: 17261193259cb37c9763a111825aa04718a409d07145Aart Bik SimplifyMemBarrier(instruction, MemBarrierKind::kAnyStore); 17271193259cb37c9763a111825aa04718a409d07145Aart Bik break; 17281193259cb37c9763a111825aa04718a409d07145Aart Bik case Intrinsics::kUnsafeFullFence: 17291193259cb37c9763a111825aa04718a409d07145Aart Bik SimplifyMemBarrier(instruction, MemBarrierKind::kAnyAny); 17301193259cb37c9763a111825aa04718a409d07145Aart Bik break; 17312a6aad9d388bd29bff04aeec3eb9429d436d1873Aart Bik default: 17322a6aad9d388bd29bff04aeec3eb9429d436d1873Aart Bik break; 1733a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray } 1734a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray} 1735a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray 1736bb245d199a5240b4c520263fd2c8c10dba79eadcAart Bikvoid InstructionSimplifierVisitor::VisitDeoptimize(HDeoptimize* deoptimize) { 1737bb245d199a5240b4c520263fd2c8c10dba79eadcAart Bik HInstruction* cond = deoptimize->InputAt(0); 1738bb245d199a5240b4c520263fd2c8c10dba79eadcAart Bik if (cond->IsConstant()) { 17391a65388f1d86bb232c2e44fecb44cebe13105d2eRoland Levillain if (cond->AsIntConstant()->IsFalse()) { 1740bb245d199a5240b4c520263fd2c8c10dba79eadcAart Bik // Never deopt: instruction can be removed. 1741bb245d199a5240b4c520263fd2c8c10dba79eadcAart Bik deoptimize->GetBlock()->RemoveInstruction(deoptimize); 1742bb245d199a5240b4c520263fd2c8c10dba79eadcAart Bik } else { 1743bb245d199a5240b4c520263fd2c8c10dba79eadcAart Bik // Always deopt. 1744bb245d199a5240b4c520263fd2c8c10dba79eadcAart Bik } 1745bb245d199a5240b4c520263fd2c8c10dba79eadcAart Bik } 1746bb245d199a5240b4c520263fd2c8c10dba79eadcAart Bik} 1747bb245d199a5240b4c520263fd2c8c10dba79eadcAart Bik 17483c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray} // namespace art 1749