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