instruction_simplifier.cc revision 9f98025ba5541641cfa9abb7b9cf30332d91fad1
1/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "instruction_simplifier.h"
18
19#include "intrinsics.h"
20#include "mirror/class-inl.h"
21#include "scoped_thread_state_change.h"
22
23namespace art {
24
25class InstructionSimplifierVisitor : public HGraphDelegateVisitor {
26 public:
27  InstructionSimplifierVisitor(HGraph* graph, OptimizingCompilerStats* stats)
28      : HGraphDelegateVisitor(graph),
29        stats_(stats) {}
30
31  void Run();
32
33 private:
34  void RecordSimplification() {
35    simplification_occurred_ = true;
36    simplifications_at_current_position_++;
37    if (stats_) {
38      stats_->RecordStat(kInstructionSimplifications);
39    }
40  }
41
42  bool ReplaceRotateWithRor(HBinaryOperation* op, HUShr* ushr, HShl* shl);
43  bool TryReplaceWithRotate(HBinaryOperation* instruction);
44  bool TryReplaceWithRotateConstantPattern(HBinaryOperation* op, HUShr* ushr, HShl* shl);
45  bool TryReplaceWithRotateRegisterNegPattern(HBinaryOperation* op, HUShr* ushr, HShl* shl);
46  bool TryReplaceWithRotateRegisterSubPattern(HBinaryOperation* op, HUShr* ushr, HShl* shl);
47
48  bool TryMoveNegOnInputsAfterBinop(HBinaryOperation* binop);
49  // `op` should be either HOr or HAnd.
50  // De Morgan's laws:
51  // ~a & ~b = ~(a | b)  and  ~a | ~b = ~(a & b)
52  bool TryDeMorganNegationFactoring(HBinaryOperation* op);
53  void VisitShift(HBinaryOperation* shift);
54
55  void VisitSuspendCheck(HSuspendCheck* check) OVERRIDE;
56  void VisitEqual(HEqual* equal) OVERRIDE;
57  void VisitNotEqual(HNotEqual* equal) OVERRIDE;
58  void VisitBooleanNot(HBooleanNot* bool_not) OVERRIDE;
59  void VisitInstanceFieldSet(HInstanceFieldSet* equal) OVERRIDE;
60  void VisitStaticFieldSet(HStaticFieldSet* equal) OVERRIDE;
61  void VisitArraySet(HArraySet* equal) OVERRIDE;
62  void VisitTypeConversion(HTypeConversion* instruction) OVERRIDE;
63  void VisitNullCheck(HNullCheck* instruction) OVERRIDE;
64  void VisitArrayLength(HArrayLength* instruction) OVERRIDE;
65  void VisitCheckCast(HCheckCast* instruction) OVERRIDE;
66  void VisitAdd(HAdd* instruction) OVERRIDE;
67  void VisitAnd(HAnd* instruction) OVERRIDE;
68  void VisitCondition(HCondition* instruction) OVERRIDE;
69  void VisitGreaterThan(HGreaterThan* condition) OVERRIDE;
70  void VisitGreaterThanOrEqual(HGreaterThanOrEqual* condition) OVERRIDE;
71  void VisitLessThan(HLessThan* condition) OVERRIDE;
72  void VisitLessThanOrEqual(HLessThanOrEqual* condition) OVERRIDE;
73  void VisitDiv(HDiv* instruction) OVERRIDE;
74  void VisitMul(HMul* instruction) OVERRIDE;
75  void VisitNeg(HNeg* instruction) OVERRIDE;
76  void VisitNot(HNot* instruction) OVERRIDE;
77  void VisitOr(HOr* instruction) OVERRIDE;
78  void VisitShl(HShl* instruction) OVERRIDE;
79  void VisitShr(HShr* instruction) OVERRIDE;
80  void VisitSub(HSub* instruction) OVERRIDE;
81  void VisitUShr(HUShr* instruction) OVERRIDE;
82  void VisitXor(HXor* instruction) OVERRIDE;
83  void VisitSelect(HSelect* select) OVERRIDE;
84  void VisitIf(HIf* instruction) OVERRIDE;
85  void VisitInstanceOf(HInstanceOf* instruction) OVERRIDE;
86  void VisitInvoke(HInvoke* invoke) OVERRIDE;
87  void VisitDeoptimize(HDeoptimize* deoptimize) OVERRIDE;
88
89  bool CanEnsureNotNullAt(HInstruction* instr, HInstruction* at) const;
90
91  void SimplifyRotate(HInvoke* invoke, bool is_left);
92  void SimplifySystemArrayCopy(HInvoke* invoke);
93  void SimplifyStringEquals(HInvoke* invoke);
94
95  OptimizingCompilerStats* stats_;
96  bool simplification_occurred_ = false;
97  int simplifications_at_current_position_ = 0;
98  // We ensure we do not loop infinitely. The value is a finger in the air guess
99  // that should allow enough simplification.
100  static constexpr int kMaxSamePositionSimplifications = 10;
101};
102
103void InstructionSimplifier::Run() {
104  InstructionSimplifierVisitor visitor(graph_, stats_);
105  visitor.Run();
106}
107
108void InstructionSimplifierVisitor::Run() {
109  // Iterate in reverse post order to open up more simplifications to users
110  // of instructions that got simplified.
111  for (HReversePostOrderIterator it(*GetGraph()); !it.Done();) {
112    // The simplification of an instruction to another instruction may yield
113    // possibilities for other simplifications. So although we perform a reverse
114    // post order visit, we sometimes need to revisit an instruction index.
115    simplification_occurred_ = false;
116    VisitBasicBlock(it.Current());
117    if (simplification_occurred_ &&
118        (simplifications_at_current_position_ < kMaxSamePositionSimplifications)) {
119      // New simplifications may be applicable to the instruction at the
120      // current index, so don't advance the iterator.
121      continue;
122    }
123    simplifications_at_current_position_ = 0;
124    it.Advance();
125  }
126}
127
128namespace {
129
130bool AreAllBitsSet(HConstant* constant) {
131  return Int64FromConstant(constant) == -1;
132}
133
134}  // namespace
135
136// Returns true if the code was simplified to use only one negation operation
137// after the binary operation instead of one on each of the inputs.
138bool InstructionSimplifierVisitor::TryMoveNegOnInputsAfterBinop(HBinaryOperation* binop) {
139  DCHECK(binop->IsAdd() || binop->IsSub());
140  DCHECK(binop->GetLeft()->IsNeg() && binop->GetRight()->IsNeg());
141  HNeg* left_neg = binop->GetLeft()->AsNeg();
142  HNeg* right_neg = binop->GetRight()->AsNeg();
143  if (!left_neg->HasOnlyOneNonEnvironmentUse() ||
144      !right_neg->HasOnlyOneNonEnvironmentUse()) {
145    return false;
146  }
147  // Replace code looking like
148  //    NEG tmp1, a
149  //    NEG tmp2, b
150  //    ADD dst, tmp1, tmp2
151  // with
152  //    ADD tmp, a, b
153  //    NEG dst, tmp
154  // Note that we cannot optimize `(-a) + (-b)` to `-(a + b)` for floating-point.
155  // When `a` is `-0.0` and `b` is `0.0`, the former expression yields `0.0`,
156  // while the later yields `-0.0`.
157  if (!Primitive::IsIntegralType(binop->GetType())) {
158    return false;
159  }
160  binop->ReplaceInput(left_neg->GetInput(), 0);
161  binop->ReplaceInput(right_neg->GetInput(), 1);
162  left_neg->GetBlock()->RemoveInstruction(left_neg);
163  right_neg->GetBlock()->RemoveInstruction(right_neg);
164  HNeg* neg = new (GetGraph()->GetArena()) HNeg(binop->GetType(), binop);
165  binop->GetBlock()->InsertInstructionBefore(neg, binop->GetNext());
166  binop->ReplaceWithExceptInReplacementAtIndex(neg, 0);
167  RecordSimplification();
168  return true;
169}
170
171bool InstructionSimplifierVisitor::TryDeMorganNegationFactoring(HBinaryOperation* op) {
172  DCHECK(op->IsAnd() || op->IsOr()) << op->DebugName();
173  Primitive::Type type = op->GetType();
174  HInstruction* left = op->GetLeft();
175  HInstruction* right = op->GetRight();
176
177  // We can apply De Morgan's laws if both inputs are Not's and are only used
178  // by `op`.
179  if (((left->IsNot() && right->IsNot()) ||
180       (left->IsBooleanNot() && right->IsBooleanNot())) &&
181      left->HasOnlyOneNonEnvironmentUse() &&
182      right->HasOnlyOneNonEnvironmentUse()) {
183    // Replace code looking like
184    //    NOT nota, a
185    //    NOT notb, b
186    //    AND dst, nota, notb (respectively OR)
187    // with
188    //    OR or, a, b         (respectively AND)
189    //    NOT dest, or
190    HInstruction* src_left = left->InputAt(0);
191    HInstruction* src_right = right->InputAt(0);
192    uint32_t dex_pc = op->GetDexPc();
193
194    // Remove the negations on the inputs.
195    left->ReplaceWith(src_left);
196    right->ReplaceWith(src_right);
197    left->GetBlock()->RemoveInstruction(left);
198    right->GetBlock()->RemoveInstruction(right);
199
200    // Replace the `HAnd` or `HOr`.
201    HBinaryOperation* hbin;
202    if (op->IsAnd()) {
203      hbin = new (GetGraph()->GetArena()) HOr(type, src_left, src_right, dex_pc);
204    } else {
205      hbin = new (GetGraph()->GetArena()) HAnd(type, src_left, src_right, dex_pc);
206    }
207    HInstruction* hnot;
208    if (left->IsBooleanNot()) {
209      hnot = new (GetGraph()->GetArena()) HBooleanNot(hbin, dex_pc);
210    } else {
211      hnot = new (GetGraph()->GetArena()) HNot(type, hbin, dex_pc);
212    }
213
214    op->GetBlock()->InsertInstructionBefore(hbin, op);
215    op->GetBlock()->ReplaceAndRemoveInstructionWith(op, hnot);
216
217    RecordSimplification();
218    return true;
219  }
220
221  return false;
222}
223
224void InstructionSimplifierVisitor::VisitShift(HBinaryOperation* instruction) {
225  DCHECK(instruction->IsShl() || instruction->IsShr() || instruction->IsUShr());
226  HConstant* input_cst = instruction->GetConstantRight();
227  HInstruction* input_other = instruction->GetLeastConstantLeft();
228
229  if (input_cst != nullptr) {
230    if (input_cst->IsZero()) {
231      // Replace code looking like
232      //    SHL dst, src, 0
233      // with
234      //    src
235      instruction->ReplaceWith(input_other);
236      instruction->GetBlock()->RemoveInstruction(instruction);
237    }
238  }
239}
240
241static bool IsSubRegBitsMinusOther(HSub* sub, size_t reg_bits, HInstruction* other) {
242  return (sub->GetRight() == other &&
243          sub->GetLeft()->IsConstant() &&
244          (Int64FromConstant(sub->GetLeft()->AsConstant()) & (reg_bits - 1)) == 0);
245}
246
247bool InstructionSimplifierVisitor::ReplaceRotateWithRor(HBinaryOperation* op,
248                                                        HUShr* ushr,
249                                                        HShl* shl) {
250  DCHECK(op->IsAdd() || op->IsXor() || op->IsOr());
251  HRor* ror = new (GetGraph()->GetArena()) HRor(ushr->GetType(),
252                                                ushr->GetLeft(),
253                                                ushr->GetRight());
254  op->GetBlock()->ReplaceAndRemoveInstructionWith(op, ror);
255  if (!ushr->HasUses()) {
256    ushr->GetBlock()->RemoveInstruction(ushr);
257  }
258  if (!ushr->GetRight()->HasUses()) {
259    ushr->GetRight()->GetBlock()->RemoveInstruction(ushr->GetRight());
260  }
261  if (!shl->HasUses()) {
262    shl->GetBlock()->RemoveInstruction(shl);
263  }
264  if (!shl->GetRight()->HasUses()) {
265    shl->GetRight()->GetBlock()->RemoveInstruction(shl->GetRight());
266  }
267  return true;
268}
269
270// Try to replace a binary operation flanked by one UShr and one Shl with a bitfield rotation.
271bool InstructionSimplifierVisitor::TryReplaceWithRotate(HBinaryOperation* op) {
272  DCHECK(op->IsAdd() || op->IsXor() || op->IsOr());
273  HInstruction* left = op->GetLeft();
274  HInstruction* right = op->GetRight();
275  // If we have an UShr and a Shl (in either order).
276  if ((left->IsUShr() && right->IsShl()) || (left->IsShl() && right->IsUShr())) {
277    HUShr* ushr = left->IsUShr() ? left->AsUShr() : right->AsUShr();
278    HShl* shl = left->IsShl() ? left->AsShl() : right->AsShl();
279    DCHECK(Primitive::IsIntOrLongType(ushr->GetType()));
280    if (ushr->GetType() == shl->GetType() &&
281        ushr->GetLeft() == shl->GetLeft()) {
282      if (ushr->GetRight()->IsConstant() && shl->GetRight()->IsConstant()) {
283        // Shift distances are both constant, try replacing with Ror if they
284        // add up to the register size.
285        return TryReplaceWithRotateConstantPattern(op, ushr, shl);
286      } else if (ushr->GetRight()->IsSub() || shl->GetRight()->IsSub()) {
287        // Shift distances are potentially of the form x and (reg_size - x).
288        return TryReplaceWithRotateRegisterSubPattern(op, ushr, shl);
289      } else if (ushr->GetRight()->IsNeg() || shl->GetRight()->IsNeg()) {
290        // Shift distances are potentially of the form d and -d.
291        return TryReplaceWithRotateRegisterNegPattern(op, ushr, shl);
292      }
293    }
294  }
295  return false;
296}
297
298// Try replacing code looking like (x >>> #rdist OP x << #ldist):
299//    UShr dst, x,   #rdist
300//    Shl  tmp, x,   #ldist
301//    OP   dst, dst, tmp
302// or like (x >>> #rdist OP x << #-ldist):
303//    UShr dst, x,   #rdist
304//    Shl  tmp, x,   #-ldist
305//    OP   dst, dst, tmp
306// with
307//    Ror  dst, x,   #rdist
308bool InstructionSimplifierVisitor::TryReplaceWithRotateConstantPattern(HBinaryOperation* op,
309                                                                       HUShr* ushr,
310                                                                       HShl* shl) {
311  DCHECK(op->IsAdd() || op->IsXor() || op->IsOr());
312  size_t reg_bits = Primitive::ComponentSize(ushr->GetType()) * kBitsPerByte;
313  size_t rdist = Int64FromConstant(ushr->GetRight()->AsConstant());
314  size_t ldist = Int64FromConstant(shl->GetRight()->AsConstant());
315  if (((ldist + rdist) & (reg_bits - 1)) == 0) {
316    ReplaceRotateWithRor(op, ushr, shl);
317    return true;
318  }
319  return false;
320}
321
322// Replace code looking like (x >>> -d OP x << d):
323//    Neg  neg, d
324//    UShr dst, x,   neg
325//    Shl  tmp, x,   d
326//    OP   dst, dst, tmp
327// with
328//    Neg  neg, d
329//    Ror  dst, x,   neg
330// *** OR ***
331// Replace code looking like (x >>> d OP x << -d):
332//    UShr dst, x,   d
333//    Neg  neg, d
334//    Shl  tmp, x,   neg
335//    OP   dst, dst, tmp
336// with
337//    Ror  dst, x,   d
338bool InstructionSimplifierVisitor::TryReplaceWithRotateRegisterNegPattern(HBinaryOperation* op,
339                                                                          HUShr* ushr,
340                                                                          HShl* shl) {
341  DCHECK(op->IsAdd() || op->IsXor() || op->IsOr());
342  DCHECK(ushr->GetRight()->IsNeg() || shl->GetRight()->IsNeg());
343  bool neg_is_left = shl->GetRight()->IsNeg();
344  HNeg* neg = neg_is_left ? shl->GetRight()->AsNeg() : ushr->GetRight()->AsNeg();
345  // And the shift distance being negated is the distance being shifted the other way.
346  if (neg->InputAt(0) == (neg_is_left ? ushr->GetRight() : shl->GetRight())) {
347    ReplaceRotateWithRor(op, ushr, shl);
348  }
349  return false;
350}
351
352// Try replacing code looking like (x >>> d OP x << (#bits - d)):
353//    UShr dst, x,     d
354//    Sub  ld,  #bits, d
355//    Shl  tmp, x,     ld
356//    OP   dst, dst,   tmp
357// with
358//    Ror  dst, x,     d
359// *** OR ***
360// Replace code looking like (x >>> (#bits - d) OP x << d):
361//    Sub  rd,  #bits, d
362//    UShr dst, x,     rd
363//    Shl  tmp, x,     d
364//    OP   dst, dst,   tmp
365// with
366//    Neg  neg, d
367//    Ror  dst, x,     neg
368bool InstructionSimplifierVisitor::TryReplaceWithRotateRegisterSubPattern(HBinaryOperation* op,
369                                                                          HUShr* ushr,
370                                                                          HShl* shl) {
371  DCHECK(op->IsAdd() || op->IsXor() || op->IsOr());
372  DCHECK(ushr->GetRight()->IsSub() || shl->GetRight()->IsSub());
373  size_t reg_bits = Primitive::ComponentSize(ushr->GetType()) * kBitsPerByte;
374  HInstruction* shl_shift = shl->GetRight();
375  HInstruction* ushr_shift = ushr->GetRight();
376  if ((shl_shift->IsSub() && IsSubRegBitsMinusOther(shl_shift->AsSub(), reg_bits, ushr_shift)) ||
377      (ushr_shift->IsSub() && IsSubRegBitsMinusOther(ushr_shift->AsSub(), reg_bits, shl_shift))) {
378    return ReplaceRotateWithRor(op, ushr, shl);
379  }
380  return false;
381}
382
383void InstructionSimplifierVisitor::VisitNullCheck(HNullCheck* null_check) {
384  HInstruction* obj = null_check->InputAt(0);
385  if (!obj->CanBeNull()) {
386    null_check->ReplaceWith(obj);
387    null_check->GetBlock()->RemoveInstruction(null_check);
388    if (stats_ != nullptr) {
389      stats_->RecordStat(MethodCompilationStat::kRemovedNullCheck);
390    }
391  }
392}
393
394bool InstructionSimplifierVisitor::CanEnsureNotNullAt(HInstruction* input, HInstruction* at) const {
395  if (!input->CanBeNull()) {
396    return true;
397  }
398
399  for (HUseIterator<HInstruction*> it(input->GetUses()); !it.Done(); it.Advance()) {
400    HInstruction* use = it.Current()->GetUser();
401    if (use->IsNullCheck() && use->StrictlyDominates(at)) {
402      return true;
403    }
404  }
405
406  return false;
407}
408
409// Returns whether doing a type test between the class of `object` against `klass` has
410// a statically known outcome. The result of the test is stored in `outcome`.
411static bool TypeCheckHasKnownOutcome(HLoadClass* klass, HInstruction* object, bool* outcome) {
412  DCHECK(!object->IsNullConstant()) << "Null constants should be special cased";
413  ReferenceTypeInfo obj_rti = object->GetReferenceTypeInfo();
414  ScopedObjectAccess soa(Thread::Current());
415  if (!obj_rti.IsValid()) {
416    // We run the simplifier before the reference type propagation so type info might not be
417    // available.
418    return false;
419  }
420
421  ReferenceTypeInfo class_rti = klass->GetLoadedClassRTI();
422  if (!class_rti.IsValid()) {
423    // Happens when the loaded class is unresolved.
424    return false;
425  }
426  DCHECK(class_rti.IsExact());
427  if (class_rti.IsSupertypeOf(obj_rti)) {
428    *outcome = true;
429    return true;
430  } else if (obj_rti.IsExact()) {
431    // The test failed at compile time so will also fail at runtime.
432    *outcome = false;
433    return true;
434  } else if (!class_rti.IsInterface()
435             && !obj_rti.IsInterface()
436             && !obj_rti.IsSupertypeOf(class_rti)) {
437    // Different type hierarchy. The test will fail.
438    *outcome = false;
439    return true;
440  }
441  return false;
442}
443
444void InstructionSimplifierVisitor::VisitCheckCast(HCheckCast* check_cast) {
445  HInstruction* object = check_cast->InputAt(0);
446  HLoadClass* load_class = check_cast->InputAt(1)->AsLoadClass();
447  if (load_class->NeedsAccessCheck()) {
448    // If we need to perform an access check we cannot remove the instruction.
449    return;
450  }
451
452  if (CanEnsureNotNullAt(object, check_cast)) {
453    check_cast->ClearMustDoNullCheck();
454  }
455
456  if (object->IsNullConstant()) {
457    check_cast->GetBlock()->RemoveInstruction(check_cast);
458    if (stats_ != nullptr) {
459      stats_->RecordStat(MethodCompilationStat::kRemovedCheckedCast);
460    }
461    return;
462  }
463
464  bool outcome;
465  if (TypeCheckHasKnownOutcome(load_class, object, &outcome)) {
466    if (outcome) {
467      check_cast->GetBlock()->RemoveInstruction(check_cast);
468      if (stats_ != nullptr) {
469        stats_->RecordStat(MethodCompilationStat::kRemovedCheckedCast);
470      }
471      if (!load_class->HasUses()) {
472        // We cannot rely on DCE to remove the class because the `HLoadClass` thinks it can throw.
473        // However, here we know that it cannot because the checkcast was successfull, hence
474        // the class was already loaded.
475        load_class->GetBlock()->RemoveInstruction(load_class);
476      }
477    } else {
478      // Don't do anything for exceptional cases for now. Ideally we should remove
479      // all instructions and blocks this instruction dominates.
480    }
481  }
482}
483
484void InstructionSimplifierVisitor::VisitInstanceOf(HInstanceOf* instruction) {
485  HInstruction* object = instruction->InputAt(0);
486  HLoadClass* load_class = instruction->InputAt(1)->AsLoadClass();
487  if (load_class->NeedsAccessCheck()) {
488    // If we need to perform an access check we cannot remove the instruction.
489    return;
490  }
491
492  bool can_be_null = true;
493  if (CanEnsureNotNullAt(object, instruction)) {
494    can_be_null = false;
495    instruction->ClearMustDoNullCheck();
496  }
497
498  HGraph* graph = GetGraph();
499  if (object->IsNullConstant()) {
500    instruction->ReplaceWith(graph->GetIntConstant(0));
501    instruction->GetBlock()->RemoveInstruction(instruction);
502    RecordSimplification();
503    return;
504  }
505
506  bool outcome;
507  if (TypeCheckHasKnownOutcome(load_class, object, &outcome)) {
508    if (outcome && can_be_null) {
509      // Type test will succeed, we just need a null test.
510      HNotEqual* test = new (graph->GetArena()) HNotEqual(graph->GetNullConstant(), object);
511      instruction->GetBlock()->InsertInstructionBefore(test, instruction);
512      instruction->ReplaceWith(test);
513    } else {
514      // We've statically determined the result of the instanceof.
515      instruction->ReplaceWith(graph->GetIntConstant(outcome));
516    }
517    RecordSimplification();
518    instruction->GetBlock()->RemoveInstruction(instruction);
519    if (outcome && !load_class->HasUses()) {
520      // We cannot rely on DCE to remove the class because the `HLoadClass` thinks it can throw.
521      // However, here we know that it cannot because the instanceof check was successfull, hence
522      // the class was already loaded.
523      load_class->GetBlock()->RemoveInstruction(load_class);
524    }
525  }
526}
527
528void InstructionSimplifierVisitor::VisitInstanceFieldSet(HInstanceFieldSet* instruction) {
529  if ((instruction->GetValue()->GetType() == Primitive::kPrimNot)
530      && CanEnsureNotNullAt(instruction->GetValue(), instruction)) {
531    instruction->ClearValueCanBeNull();
532  }
533}
534
535void InstructionSimplifierVisitor::VisitStaticFieldSet(HStaticFieldSet* instruction) {
536  if ((instruction->GetValue()->GetType() == Primitive::kPrimNot)
537      && CanEnsureNotNullAt(instruction->GetValue(), instruction)) {
538    instruction->ClearValueCanBeNull();
539  }
540}
541
542void InstructionSimplifierVisitor::VisitSuspendCheck(HSuspendCheck* check) {
543  HBasicBlock* block = check->GetBlock();
544  // Currently always keep the suspend check at entry.
545  if (block->IsEntryBlock()) return;
546
547  // Currently always keep suspend checks at loop entry.
548  if (block->IsLoopHeader() && block->GetFirstInstruction() == check) {
549    DCHECK(block->GetLoopInformation()->GetSuspendCheck() == check);
550    return;
551  }
552
553  // Remove the suspend check that was added at build time for the baseline
554  // compiler.
555  block->RemoveInstruction(check);
556}
557
558void InstructionSimplifierVisitor::VisitEqual(HEqual* equal) {
559  HInstruction* input_const = equal->GetConstantRight();
560  if (input_const != nullptr) {
561    HInstruction* input_value = equal->GetLeastConstantLeft();
562    if (input_value->GetType() == Primitive::kPrimBoolean && input_const->IsIntConstant()) {
563      HBasicBlock* block = equal->GetBlock();
564      // We are comparing the boolean to a constant which is of type int and can
565      // be any constant.
566      if (input_const->AsIntConstant()->IsOne()) {
567        // Replace (bool_value == true) with bool_value
568        equal->ReplaceWith(input_value);
569        block->RemoveInstruction(equal);
570        RecordSimplification();
571      } else if (input_const->AsIntConstant()->IsZero()) {
572        equal->ReplaceWith(GetGraph()->InsertOppositeCondition(input_value, equal));
573        block->RemoveInstruction(equal);
574        RecordSimplification();
575      } else {
576        // Replace (bool_value == integer_not_zero_nor_one_constant) with false
577        equal->ReplaceWith(GetGraph()->GetIntConstant(0));
578        block->RemoveInstruction(equal);
579        RecordSimplification();
580      }
581    } else {
582      VisitCondition(equal);
583    }
584  } else {
585    VisitCondition(equal);
586  }
587}
588
589void InstructionSimplifierVisitor::VisitNotEqual(HNotEqual* not_equal) {
590  HInstruction* input_const = not_equal->GetConstantRight();
591  if (input_const != nullptr) {
592    HInstruction* input_value = not_equal->GetLeastConstantLeft();
593    if (input_value->GetType() == Primitive::kPrimBoolean && input_const->IsIntConstant()) {
594      HBasicBlock* block = not_equal->GetBlock();
595      // We are comparing the boolean to a constant which is of type int and can
596      // be any constant.
597      if (input_const->AsIntConstant()->IsOne()) {
598        not_equal->ReplaceWith(GetGraph()->InsertOppositeCondition(input_value, not_equal));
599        block->RemoveInstruction(not_equal);
600        RecordSimplification();
601      } else if (input_const->AsIntConstant()->IsZero()) {
602        // Replace (bool_value != false) with bool_value
603        not_equal->ReplaceWith(input_value);
604        block->RemoveInstruction(not_equal);
605        RecordSimplification();
606      } else {
607        // Replace (bool_value != integer_not_zero_nor_one_constant) with true
608        not_equal->ReplaceWith(GetGraph()->GetIntConstant(1));
609        block->RemoveInstruction(not_equal);
610        RecordSimplification();
611      }
612    } else {
613      VisitCondition(not_equal);
614    }
615  } else {
616    VisitCondition(not_equal);
617  }
618}
619
620void InstructionSimplifierVisitor::VisitBooleanNot(HBooleanNot* bool_not) {
621  HInstruction* input = bool_not->InputAt(0);
622  HInstruction* replace_with = nullptr;
623
624  if (input->IsIntConstant()) {
625    // Replace !(true/false) with false/true.
626    if (input->AsIntConstant()->IsOne()) {
627      replace_with = GetGraph()->GetIntConstant(0);
628    } else {
629      DCHECK(input->AsIntConstant()->IsZero());
630      replace_with = GetGraph()->GetIntConstant(1);
631    }
632  } else if (input->IsBooleanNot()) {
633    // Replace (!(!bool_value)) with bool_value.
634    replace_with = input->InputAt(0);
635  } else if (input->IsCondition() &&
636             // Don't change FP compares. The definition of compares involving
637             // NaNs forces the compares to be done as written by the user.
638             !Primitive::IsFloatingPointType(input->InputAt(0)->GetType())) {
639    // Replace condition with its opposite.
640    replace_with = GetGraph()->InsertOppositeCondition(input->AsCondition(), bool_not);
641  }
642
643  if (replace_with != nullptr) {
644    bool_not->ReplaceWith(replace_with);
645    bool_not->GetBlock()->RemoveInstruction(bool_not);
646    RecordSimplification();
647  }
648}
649
650void InstructionSimplifierVisitor::VisitSelect(HSelect* select) {
651  HInstruction* replace_with = nullptr;
652  HInstruction* condition = select->GetCondition();
653  HInstruction* true_value = select->GetTrueValue();
654  HInstruction* false_value = select->GetFalseValue();
655
656  if (condition->IsBooleanNot()) {
657    // Change ((!cond) ? x : y) to (cond ? y : x).
658    condition = condition->InputAt(0);
659    std::swap(true_value, false_value);
660    select->ReplaceInput(false_value, 0);
661    select->ReplaceInput(true_value, 1);
662    select->ReplaceInput(condition, 2);
663    RecordSimplification();
664  }
665
666  if (true_value == false_value) {
667    // Replace (cond ? x : x) with (x).
668    replace_with = true_value;
669  } else if (condition->IsIntConstant()) {
670    if (condition->AsIntConstant()->IsOne()) {
671      // Replace (true ? x : y) with (x).
672      replace_with = true_value;
673    } else {
674      // Replace (false ? x : y) with (y).
675      DCHECK(condition->AsIntConstant()->IsZero());
676      replace_with = false_value;
677    }
678  } else if (true_value->IsIntConstant() && false_value->IsIntConstant()) {
679    if (true_value->AsIntConstant()->IsOne() && false_value->AsIntConstant()->IsZero()) {
680      // Replace (cond ? true : false) with (cond).
681      replace_with = condition;
682    } else if (true_value->AsIntConstant()->IsZero() && false_value->AsIntConstant()->IsOne()) {
683      // Replace (cond ? false : true) with (!cond).
684      replace_with = GetGraph()->InsertOppositeCondition(condition, select);
685    }
686  }
687
688  if (replace_with != nullptr) {
689    select->ReplaceWith(replace_with);
690    select->GetBlock()->RemoveInstruction(select);
691    RecordSimplification();
692  }
693}
694
695void InstructionSimplifierVisitor::VisitIf(HIf* instruction) {
696  HInstruction* condition = instruction->InputAt(0);
697  if (condition->IsBooleanNot()) {
698    // Swap successors if input is negated.
699    instruction->ReplaceInput(condition->InputAt(0), 0);
700    instruction->GetBlock()->SwapSuccessors();
701    RecordSimplification();
702  }
703}
704
705void InstructionSimplifierVisitor::VisitArrayLength(HArrayLength* instruction) {
706  HInstruction* input = instruction->InputAt(0);
707  // If the array is a NewArray with constant size, replace the array length
708  // with the constant instruction. This helps the bounds check elimination phase.
709  if (input->IsNewArray()) {
710    input = input->InputAt(0);
711    if (input->IsIntConstant()) {
712      instruction->ReplaceWith(input);
713    }
714  }
715}
716
717void InstructionSimplifierVisitor::VisitArraySet(HArraySet* instruction) {
718  HInstruction* value = instruction->GetValue();
719  if (value->GetType() != Primitive::kPrimNot) return;
720
721  if (CanEnsureNotNullAt(value, instruction)) {
722    instruction->ClearValueCanBeNull();
723  }
724
725  if (value->IsArrayGet()) {
726    if (value->AsArrayGet()->GetArray() == instruction->GetArray()) {
727      // If the code is just swapping elements in the array, no need for a type check.
728      instruction->ClearNeedsTypeCheck();
729      return;
730    }
731  }
732
733  if (value->IsNullConstant()) {
734    instruction->ClearNeedsTypeCheck();
735    return;
736  }
737
738  ScopedObjectAccess soa(Thread::Current());
739  ReferenceTypeInfo array_rti = instruction->GetArray()->GetReferenceTypeInfo();
740  ReferenceTypeInfo value_rti = value->GetReferenceTypeInfo();
741  if (!array_rti.IsValid()) {
742    return;
743  }
744
745  if (value_rti.IsValid() && array_rti.CanArrayHold(value_rti)) {
746    instruction->ClearNeedsTypeCheck();
747    return;
748  }
749
750  if (array_rti.IsObjectArray()) {
751    if (array_rti.IsExact()) {
752      instruction->ClearNeedsTypeCheck();
753      return;
754    }
755    instruction->SetStaticTypeOfArrayIsObjectArray();
756  }
757}
758
759void InstructionSimplifierVisitor::VisitTypeConversion(HTypeConversion* instruction) {
760  if (instruction->GetResultType() == instruction->GetInputType()) {
761    // Remove the instruction if it's converting to the same type.
762    instruction->ReplaceWith(instruction->GetInput());
763    instruction->GetBlock()->RemoveInstruction(instruction);
764  }
765}
766
767void InstructionSimplifierVisitor::VisitAdd(HAdd* instruction) {
768  HConstant* input_cst = instruction->GetConstantRight();
769  HInstruction* input_other = instruction->GetLeastConstantLeft();
770  if ((input_cst != nullptr) && input_cst->IsZero()) {
771    // Replace code looking like
772    //    ADD dst, src, 0
773    // with
774    //    src
775    // Note that we cannot optimize `x + 0.0` to `x` for floating-point. When
776    // `x` is `-0.0`, the former expression yields `0.0`, while the later
777    // yields `-0.0`.
778    if (Primitive::IsIntegralType(instruction->GetType())) {
779      instruction->ReplaceWith(input_other);
780      instruction->GetBlock()->RemoveInstruction(instruction);
781      return;
782    }
783  }
784
785  HInstruction* left = instruction->GetLeft();
786  HInstruction* right = instruction->GetRight();
787  bool left_is_neg = left->IsNeg();
788  bool right_is_neg = right->IsNeg();
789
790  if (left_is_neg && right_is_neg) {
791    if (TryMoveNegOnInputsAfterBinop(instruction)) {
792      return;
793    }
794  }
795
796  HNeg* neg = left_is_neg ? left->AsNeg() : right->AsNeg();
797  if ((left_is_neg ^ right_is_neg) && neg->HasOnlyOneNonEnvironmentUse()) {
798    // Replace code looking like
799    //    NEG tmp, b
800    //    ADD dst, a, tmp
801    // with
802    //    SUB dst, a, b
803    // We do not perform the optimization if the input negation has environment
804    // uses or multiple non-environment uses as it could lead to worse code. In
805    // particular, we do not want the live range of `b` to be extended if we are
806    // not sure the initial 'NEG' instruction can be removed.
807    HInstruction* other = left_is_neg ? right : left;
808    HSub* sub = new(GetGraph()->GetArena()) HSub(instruction->GetType(), other, neg->GetInput());
809    instruction->GetBlock()->ReplaceAndRemoveInstructionWith(instruction, sub);
810    RecordSimplification();
811    neg->GetBlock()->RemoveInstruction(neg);
812    return;
813  }
814
815  TryReplaceWithRotate(instruction);
816}
817
818void InstructionSimplifierVisitor::VisitAnd(HAnd* instruction) {
819  HConstant* input_cst = instruction->GetConstantRight();
820  HInstruction* input_other = instruction->GetLeastConstantLeft();
821
822  if (input_cst != nullptr) {
823    int64_t value = Int64FromConstant(input_cst);
824    if (value == -1) {
825      // Replace code looking like
826      //    AND dst, src, 0xFFF...FF
827      // with
828      //    src
829      instruction->ReplaceWith(input_other);
830      instruction->GetBlock()->RemoveInstruction(instruction);
831      RecordSimplification();
832      return;
833    }
834    // Eliminate And from UShr+And if the And-mask contains all the bits that
835    // can be non-zero after UShr. Transform Shr+And to UShr if the And-mask
836    // precisely clears the shifted-in sign bits.
837    if ((input_other->IsUShr() || input_other->IsShr()) && input_other->InputAt(1)->IsConstant()) {
838      size_t reg_bits = (instruction->GetResultType() == Primitive::kPrimLong) ? 64 : 32;
839      size_t shift = Int64FromConstant(input_other->InputAt(1)->AsConstant()) & (reg_bits - 1);
840      size_t num_tail_bits_set = CTZ(value + 1);
841      if ((num_tail_bits_set >= reg_bits - shift) && input_other->IsUShr()) {
842        // This AND clears only bits known to be clear, for example "(x >>> 24) & 0xff".
843        instruction->ReplaceWith(input_other);
844        instruction->GetBlock()->RemoveInstruction(instruction);
845        RecordSimplification();
846        return;
847      }  else if ((num_tail_bits_set == reg_bits - shift) && IsPowerOfTwo(value + 1) &&
848          input_other->HasOnlyOneNonEnvironmentUse()) {
849        DCHECK(input_other->IsShr());  // For UShr, we would have taken the branch above.
850        // Replace SHR+AND with USHR, for example "(x >> 24) & 0xff" -> "x >>> 24".
851        HUShr* ushr = new (GetGraph()->GetArena()) HUShr(instruction->GetType(),
852                                                         input_other->InputAt(0),
853                                                         input_other->InputAt(1),
854                                                         input_other->GetDexPc());
855        instruction->GetBlock()->ReplaceAndRemoveInstructionWith(instruction, ushr);
856        input_other->GetBlock()->RemoveInstruction(input_other);
857        RecordSimplification();
858        return;
859      }
860    }
861  }
862
863  // We assume that GVN has run before, so we only perform a pointer comparison.
864  // If for some reason the values are equal but the pointers are different, we
865  // are still correct and only miss an optimization opportunity.
866  if (instruction->GetLeft() == instruction->GetRight()) {
867    // Replace code looking like
868    //    AND dst, src, src
869    // with
870    //    src
871    instruction->ReplaceWith(instruction->GetLeft());
872    instruction->GetBlock()->RemoveInstruction(instruction);
873    return;
874  }
875
876  TryDeMorganNegationFactoring(instruction);
877}
878
879void InstructionSimplifierVisitor::VisitGreaterThan(HGreaterThan* condition) {
880  VisitCondition(condition);
881}
882
883void InstructionSimplifierVisitor::VisitGreaterThanOrEqual(HGreaterThanOrEqual* condition) {
884  VisitCondition(condition);
885}
886
887void InstructionSimplifierVisitor::VisitLessThan(HLessThan* condition) {
888  VisitCondition(condition);
889}
890
891void InstructionSimplifierVisitor::VisitLessThanOrEqual(HLessThanOrEqual* condition) {
892  VisitCondition(condition);
893}
894
895// TODO: unsigned comparisons too?
896
897void InstructionSimplifierVisitor::VisitCondition(HCondition* condition) {
898  // Try to fold an HCompare into this HCondition.
899
900  HInstruction* left = condition->GetLeft();
901  HInstruction* right = condition->GetRight();
902  // We can only replace an HCondition which compares a Compare to 0.
903  // Both 'dx' and 'jack' generate a compare to 0 when compiling a
904  // condition with a long, float or double comparison as input.
905  if (!left->IsCompare() || !right->IsConstant() || right->AsIntConstant()->GetValue() != 0) {
906    // Conversion is not possible.
907    return;
908  }
909
910  // Is the Compare only used for this purpose?
911  if (!left->GetUses().HasOnlyOneUse()) {
912    // Someone else also wants the result of the compare.
913    return;
914  }
915
916  if (!left->GetEnvUses().IsEmpty()) {
917    // There is a reference to the compare result in an environment. Do we really need it?
918    if (GetGraph()->IsDebuggable()) {
919      return;
920    }
921
922    // We have to ensure that there are no deopt points in the sequence.
923    if (left->HasAnyEnvironmentUseBefore(condition)) {
924      return;
925    }
926  }
927
928  // Clean up any environment uses from the HCompare, if any.
929  left->RemoveEnvironmentUsers();
930
931  // We have decided to fold the HCompare into the HCondition. Transfer the information.
932  condition->SetBias(left->AsCompare()->GetBias());
933
934  // Replace the operands of the HCondition.
935  condition->ReplaceInput(left->InputAt(0), 0);
936  condition->ReplaceInput(left->InputAt(1), 1);
937
938  // Remove the HCompare.
939  left->GetBlock()->RemoveInstruction(left);
940
941  RecordSimplification();
942}
943
944void InstructionSimplifierVisitor::VisitDiv(HDiv* instruction) {
945  HConstant* input_cst = instruction->GetConstantRight();
946  HInstruction* input_other = instruction->GetLeastConstantLeft();
947  Primitive::Type type = instruction->GetType();
948
949  if ((input_cst != nullptr) && input_cst->IsOne()) {
950    // Replace code looking like
951    //    DIV dst, src, 1
952    // with
953    //    src
954    instruction->ReplaceWith(input_other);
955    instruction->GetBlock()->RemoveInstruction(instruction);
956    return;
957  }
958
959  if ((input_cst != nullptr) && input_cst->IsMinusOne()) {
960    // Replace code looking like
961    //    DIV dst, src, -1
962    // with
963    //    NEG dst, src
964    instruction->GetBlock()->ReplaceAndRemoveInstructionWith(
965        instruction, new (GetGraph()->GetArena()) HNeg(type, input_other));
966    RecordSimplification();
967    return;
968  }
969
970  if ((input_cst != nullptr) && Primitive::IsFloatingPointType(type)) {
971    // Try replacing code looking like
972    //    DIV dst, src, constant
973    // with
974    //    MUL dst, src, 1 / constant
975    HConstant* reciprocal = nullptr;
976    if (type == Primitive::Primitive::kPrimDouble) {
977      double value = input_cst->AsDoubleConstant()->GetValue();
978      if (CanDivideByReciprocalMultiplyDouble(bit_cast<int64_t, double>(value))) {
979        reciprocal = GetGraph()->GetDoubleConstant(1.0 / value);
980      }
981    } else {
982      DCHECK_EQ(type, Primitive::kPrimFloat);
983      float value = input_cst->AsFloatConstant()->GetValue();
984      if (CanDivideByReciprocalMultiplyFloat(bit_cast<int32_t, float>(value))) {
985        reciprocal = GetGraph()->GetFloatConstant(1.0f / value);
986      }
987    }
988
989    if (reciprocal != nullptr) {
990      instruction->GetBlock()->ReplaceAndRemoveInstructionWith(
991          instruction, new (GetGraph()->GetArena()) HMul(type, input_other, reciprocal));
992      RecordSimplification();
993      return;
994    }
995  }
996}
997
998void InstructionSimplifierVisitor::VisitMul(HMul* instruction) {
999  HConstant* input_cst = instruction->GetConstantRight();
1000  HInstruction* input_other = instruction->GetLeastConstantLeft();
1001  Primitive::Type type = instruction->GetType();
1002  HBasicBlock* block = instruction->GetBlock();
1003  ArenaAllocator* allocator = GetGraph()->GetArena();
1004
1005  if (input_cst == nullptr) {
1006    return;
1007  }
1008
1009  if (input_cst->IsOne()) {
1010    // Replace code looking like
1011    //    MUL dst, src, 1
1012    // with
1013    //    src
1014    instruction->ReplaceWith(input_other);
1015    instruction->GetBlock()->RemoveInstruction(instruction);
1016    return;
1017  }
1018
1019  if (input_cst->IsMinusOne() &&
1020      (Primitive::IsFloatingPointType(type) || Primitive::IsIntOrLongType(type))) {
1021    // Replace code looking like
1022    //    MUL dst, src, -1
1023    // with
1024    //    NEG dst, src
1025    HNeg* neg = new (allocator) HNeg(type, input_other);
1026    block->ReplaceAndRemoveInstructionWith(instruction, neg);
1027    RecordSimplification();
1028    return;
1029  }
1030
1031  if (Primitive::IsFloatingPointType(type) &&
1032      ((input_cst->IsFloatConstant() && input_cst->AsFloatConstant()->GetValue() == 2.0f) ||
1033       (input_cst->IsDoubleConstant() && input_cst->AsDoubleConstant()->GetValue() == 2.0))) {
1034    // Replace code looking like
1035    //    FP_MUL dst, src, 2.0
1036    // with
1037    //    FP_ADD dst, src, src
1038    // The 'int' and 'long' cases are handled below.
1039    block->ReplaceAndRemoveInstructionWith(instruction,
1040                                           new (allocator) HAdd(type, input_other, input_other));
1041    RecordSimplification();
1042    return;
1043  }
1044
1045  if (Primitive::IsIntOrLongType(type)) {
1046    int64_t factor = Int64FromConstant(input_cst);
1047    // Even though constant propagation also takes care of the zero case, other
1048    // optimizations can lead to having a zero multiplication.
1049    if (factor == 0) {
1050      // Replace code looking like
1051      //    MUL dst, src, 0
1052      // with
1053      //    0
1054      instruction->ReplaceWith(input_cst);
1055      instruction->GetBlock()->RemoveInstruction(instruction);
1056    } else if (IsPowerOfTwo(factor)) {
1057      // Replace code looking like
1058      //    MUL dst, src, pow_of_2
1059      // with
1060      //    SHL dst, src, log2(pow_of_2)
1061      HIntConstant* shift = GetGraph()->GetIntConstant(WhichPowerOf2(factor));
1062      HShl* shl = new(allocator) HShl(type, input_other, shift);
1063      block->ReplaceAndRemoveInstructionWith(instruction, shl);
1064      RecordSimplification();
1065    } else if (IsPowerOfTwo(factor - 1)) {
1066      // Transform code looking like
1067      //    MUL dst, src, (2^n + 1)
1068      // into
1069      //    SHL tmp, src, n
1070      //    ADD dst, src, tmp
1071      HShl* shl = new (allocator) HShl(type,
1072                                       input_other,
1073                                       GetGraph()->GetIntConstant(WhichPowerOf2(factor - 1)));
1074      HAdd* add = new (allocator) HAdd(type, input_other, shl);
1075
1076      block->InsertInstructionBefore(shl, instruction);
1077      block->ReplaceAndRemoveInstructionWith(instruction, add);
1078      RecordSimplification();
1079    } else if (IsPowerOfTwo(factor + 1)) {
1080      // Transform code looking like
1081      //    MUL dst, src, (2^n - 1)
1082      // into
1083      //    SHL tmp, src, n
1084      //    SUB dst, tmp, src
1085      HShl* shl = new (allocator) HShl(type,
1086                                       input_other,
1087                                       GetGraph()->GetIntConstant(WhichPowerOf2(factor + 1)));
1088      HSub* sub = new (allocator) HSub(type, shl, input_other);
1089
1090      block->InsertInstructionBefore(shl, instruction);
1091      block->ReplaceAndRemoveInstructionWith(instruction, sub);
1092      RecordSimplification();
1093    }
1094  }
1095}
1096
1097void InstructionSimplifierVisitor::VisitNeg(HNeg* instruction) {
1098  HInstruction* input = instruction->GetInput();
1099  if (input->IsNeg()) {
1100    // Replace code looking like
1101    //    NEG tmp, src
1102    //    NEG dst, tmp
1103    // with
1104    //    src
1105    HNeg* previous_neg = input->AsNeg();
1106    instruction->ReplaceWith(previous_neg->GetInput());
1107    instruction->GetBlock()->RemoveInstruction(instruction);
1108    // We perform the optimization even if the input negation has environment
1109    // uses since it allows removing the current instruction. But we only delete
1110    // the input negation only if it is does not have any uses left.
1111    if (!previous_neg->HasUses()) {
1112      previous_neg->GetBlock()->RemoveInstruction(previous_neg);
1113    }
1114    RecordSimplification();
1115    return;
1116  }
1117
1118  if (input->IsSub() && input->HasOnlyOneNonEnvironmentUse() &&
1119      !Primitive::IsFloatingPointType(input->GetType())) {
1120    // Replace code looking like
1121    //    SUB tmp, a, b
1122    //    NEG dst, tmp
1123    // with
1124    //    SUB dst, b, a
1125    // We do not perform the optimization if the input subtraction has
1126    // environment uses or multiple non-environment uses as it could lead to
1127    // worse code. In particular, we do not want the live ranges of `a` and `b`
1128    // to be extended if we are not sure the initial 'SUB' instruction can be
1129    // removed.
1130    // We do not perform optimization for fp because we could lose the sign of zero.
1131    HSub* sub = input->AsSub();
1132    HSub* new_sub =
1133        new (GetGraph()->GetArena()) HSub(instruction->GetType(), sub->GetRight(), sub->GetLeft());
1134    instruction->GetBlock()->ReplaceAndRemoveInstructionWith(instruction, new_sub);
1135    if (!sub->HasUses()) {
1136      sub->GetBlock()->RemoveInstruction(sub);
1137    }
1138    RecordSimplification();
1139  }
1140}
1141
1142void InstructionSimplifierVisitor::VisitNot(HNot* instruction) {
1143  HInstruction* input = instruction->GetInput();
1144  if (input->IsNot()) {
1145    // Replace code looking like
1146    //    NOT tmp, src
1147    //    NOT dst, tmp
1148    // with
1149    //    src
1150    // We perform the optimization even if the input negation has environment
1151    // uses since it allows removing the current instruction. But we only delete
1152    // the input negation only if it is does not have any uses left.
1153    HNot* previous_not = input->AsNot();
1154    instruction->ReplaceWith(previous_not->GetInput());
1155    instruction->GetBlock()->RemoveInstruction(instruction);
1156    if (!previous_not->HasUses()) {
1157      previous_not->GetBlock()->RemoveInstruction(previous_not);
1158    }
1159    RecordSimplification();
1160  }
1161}
1162
1163void InstructionSimplifierVisitor::VisitOr(HOr* instruction) {
1164  HConstant* input_cst = instruction->GetConstantRight();
1165  HInstruction* input_other = instruction->GetLeastConstantLeft();
1166
1167  if ((input_cst != nullptr) && input_cst->IsZero()) {
1168    // Replace code looking like
1169    //    OR dst, src, 0
1170    // with
1171    //    src
1172    instruction->ReplaceWith(input_other);
1173    instruction->GetBlock()->RemoveInstruction(instruction);
1174    return;
1175  }
1176
1177  // We assume that GVN has run before, so we only perform a pointer comparison.
1178  // If for some reason the values are equal but the pointers are different, we
1179  // are still correct and only miss an optimization opportunity.
1180  if (instruction->GetLeft() == instruction->GetRight()) {
1181    // Replace code looking like
1182    //    OR dst, src, src
1183    // with
1184    //    src
1185    instruction->ReplaceWith(instruction->GetLeft());
1186    instruction->GetBlock()->RemoveInstruction(instruction);
1187    return;
1188  }
1189
1190  if (TryDeMorganNegationFactoring(instruction)) return;
1191
1192  TryReplaceWithRotate(instruction);
1193}
1194
1195void InstructionSimplifierVisitor::VisitShl(HShl* instruction) {
1196  VisitShift(instruction);
1197}
1198
1199void InstructionSimplifierVisitor::VisitShr(HShr* instruction) {
1200  VisitShift(instruction);
1201}
1202
1203void InstructionSimplifierVisitor::VisitSub(HSub* instruction) {
1204  HConstant* input_cst = instruction->GetConstantRight();
1205  HInstruction* input_other = instruction->GetLeastConstantLeft();
1206
1207  Primitive::Type type = instruction->GetType();
1208  if (Primitive::IsFloatingPointType(type)) {
1209    return;
1210  }
1211
1212  if ((input_cst != nullptr) && input_cst->IsZero()) {
1213    // Replace code looking like
1214    //    SUB dst, src, 0
1215    // with
1216    //    src
1217    // Note that we cannot optimize `x - 0.0` to `x` for floating-point. When
1218    // `x` is `-0.0`, the former expression yields `0.0`, while the later
1219    // yields `-0.0`.
1220    instruction->ReplaceWith(input_other);
1221    instruction->GetBlock()->RemoveInstruction(instruction);
1222    return;
1223  }
1224
1225  HBasicBlock* block = instruction->GetBlock();
1226  ArenaAllocator* allocator = GetGraph()->GetArena();
1227
1228  HInstruction* left = instruction->GetLeft();
1229  HInstruction* right = instruction->GetRight();
1230  if (left->IsConstant()) {
1231    if (Int64FromConstant(left->AsConstant()) == 0) {
1232      // Replace code looking like
1233      //    SUB dst, 0, src
1234      // with
1235      //    NEG dst, src
1236      // Note that we cannot optimize `0.0 - x` to `-x` for floating-point. When
1237      // `x` is `0.0`, the former expression yields `0.0`, while the later
1238      // yields `-0.0`.
1239      HNeg* neg = new (allocator) HNeg(type, right);
1240      block->ReplaceAndRemoveInstructionWith(instruction, neg);
1241      RecordSimplification();
1242      return;
1243    }
1244  }
1245
1246  if (left->IsNeg() && right->IsNeg()) {
1247    if (TryMoveNegOnInputsAfterBinop(instruction)) {
1248      return;
1249    }
1250  }
1251
1252  if (right->IsNeg() && right->HasOnlyOneNonEnvironmentUse()) {
1253    // Replace code looking like
1254    //    NEG tmp, b
1255    //    SUB dst, a, tmp
1256    // with
1257    //    ADD dst, a, b
1258    HAdd* add = new(GetGraph()->GetArena()) HAdd(type, left, right->AsNeg()->GetInput());
1259    instruction->GetBlock()->ReplaceAndRemoveInstructionWith(instruction, add);
1260    RecordSimplification();
1261    right->GetBlock()->RemoveInstruction(right);
1262    return;
1263  }
1264
1265  if (left->IsNeg() && left->HasOnlyOneNonEnvironmentUse()) {
1266    // Replace code looking like
1267    //    NEG tmp, a
1268    //    SUB dst, tmp, b
1269    // with
1270    //    ADD tmp, a, b
1271    //    NEG dst, tmp
1272    // The second version is not intrinsically better, but enables more
1273    // transformations.
1274    HAdd* add = new(GetGraph()->GetArena()) HAdd(type, left->AsNeg()->GetInput(), right);
1275    instruction->GetBlock()->InsertInstructionBefore(add, instruction);
1276    HNeg* neg = new (GetGraph()->GetArena()) HNeg(instruction->GetType(), add);
1277    instruction->GetBlock()->InsertInstructionBefore(neg, instruction);
1278    instruction->ReplaceWith(neg);
1279    instruction->GetBlock()->RemoveInstruction(instruction);
1280    RecordSimplification();
1281    left->GetBlock()->RemoveInstruction(left);
1282  }
1283}
1284
1285void InstructionSimplifierVisitor::VisitUShr(HUShr* instruction) {
1286  VisitShift(instruction);
1287}
1288
1289void InstructionSimplifierVisitor::VisitXor(HXor* instruction) {
1290  HConstant* input_cst = instruction->GetConstantRight();
1291  HInstruction* input_other = instruction->GetLeastConstantLeft();
1292
1293  if ((input_cst != nullptr) && input_cst->IsZero()) {
1294    // Replace code looking like
1295    //    XOR dst, src, 0
1296    // with
1297    //    src
1298    instruction->ReplaceWith(input_other);
1299    instruction->GetBlock()->RemoveInstruction(instruction);
1300    return;
1301  }
1302
1303  if ((input_cst != nullptr) && AreAllBitsSet(input_cst)) {
1304    // Replace code looking like
1305    //    XOR dst, src, 0xFFF...FF
1306    // with
1307    //    NOT dst, src
1308    HNot* bitwise_not = new (GetGraph()->GetArena()) HNot(instruction->GetType(), input_other);
1309    instruction->GetBlock()->ReplaceAndRemoveInstructionWith(instruction, bitwise_not);
1310    RecordSimplification();
1311    return;
1312  }
1313
1314  HInstruction* left = instruction->GetLeft();
1315  HInstruction* right = instruction->GetRight();
1316  if (((left->IsNot() && right->IsNot()) ||
1317       (left->IsBooleanNot() && right->IsBooleanNot())) &&
1318      left->HasOnlyOneNonEnvironmentUse() &&
1319      right->HasOnlyOneNonEnvironmentUse()) {
1320    // Replace code looking like
1321    //    NOT nota, a
1322    //    NOT notb, b
1323    //    XOR dst, nota, notb
1324    // with
1325    //    XOR dst, a, b
1326    instruction->ReplaceInput(left->InputAt(0), 0);
1327    instruction->ReplaceInput(right->InputAt(0), 1);
1328    left->GetBlock()->RemoveInstruction(left);
1329    right->GetBlock()->RemoveInstruction(right);
1330    RecordSimplification();
1331    return;
1332  }
1333
1334  TryReplaceWithRotate(instruction);
1335}
1336
1337void InstructionSimplifierVisitor::SimplifyStringEquals(HInvoke* instruction) {
1338  HInstruction* argument = instruction->InputAt(1);
1339  HInstruction* receiver = instruction->InputAt(0);
1340  if (receiver == argument) {
1341    // Because String.equals is an instance call, the receiver is
1342    // a null check if we don't know it's null. The argument however, will
1343    // be the actual object. So we cannot end up in a situation where both
1344    // are equal but could be null.
1345    DCHECK(CanEnsureNotNullAt(argument, instruction));
1346    instruction->ReplaceWith(GetGraph()->GetIntConstant(1));
1347    instruction->GetBlock()->RemoveInstruction(instruction);
1348  } else {
1349    StringEqualsOptimizations optimizations(instruction);
1350    if (CanEnsureNotNullAt(argument, instruction)) {
1351      optimizations.SetArgumentNotNull();
1352    }
1353    ScopedObjectAccess soa(Thread::Current());
1354    ReferenceTypeInfo argument_rti = argument->GetReferenceTypeInfo();
1355    if (argument_rti.IsValid() && argument_rti.IsStringClass()) {
1356      optimizations.SetArgumentIsString();
1357    }
1358  }
1359}
1360
1361void InstructionSimplifierVisitor::SimplifyRotate(HInvoke* invoke, bool is_left) {
1362  DCHECK(invoke->IsInvokeStaticOrDirect());
1363  DCHECK_EQ(invoke->GetOriginalInvokeType(), InvokeType::kStatic);
1364  HInstruction* value = invoke->InputAt(0);
1365  HInstruction* distance = invoke->InputAt(1);
1366  // Replace the invoke with an HRor.
1367  if (is_left) {
1368    distance = new (GetGraph()->GetArena()) HNeg(distance->GetType(), distance);
1369    invoke->GetBlock()->InsertInstructionBefore(distance, invoke);
1370  }
1371  HRor* ror = new (GetGraph()->GetArena()) HRor(value->GetType(), value, distance);
1372  invoke->GetBlock()->ReplaceAndRemoveInstructionWith(invoke, ror);
1373  // Remove ClinitCheck and LoadClass, if possible.
1374  HInstruction* clinit = invoke->InputAt(invoke->InputCount() - 1);
1375  if (clinit->IsClinitCheck() && !clinit->HasUses()) {
1376    clinit->GetBlock()->RemoveInstruction(clinit);
1377    HInstruction* ldclass = clinit->InputAt(0);
1378    if (ldclass->IsLoadClass() && !ldclass->HasUses()) {
1379      ldclass->GetBlock()->RemoveInstruction(ldclass);
1380    }
1381  }
1382}
1383
1384static bool IsArrayLengthOf(HInstruction* potential_length, HInstruction* potential_array) {
1385  if (potential_length->IsArrayLength()) {
1386    return potential_length->InputAt(0) == potential_array;
1387  }
1388
1389  if (potential_array->IsNewArray()) {
1390    return potential_array->InputAt(0) == potential_length;
1391  }
1392
1393  return false;
1394}
1395
1396void InstructionSimplifierVisitor::SimplifySystemArrayCopy(HInvoke* instruction) {
1397  HInstruction* source = instruction->InputAt(0);
1398  HInstruction* destination = instruction->InputAt(2);
1399  HInstruction* count = instruction->InputAt(4);
1400  SystemArrayCopyOptimizations optimizations(instruction);
1401  if (CanEnsureNotNullAt(source, instruction)) {
1402    optimizations.SetSourceIsNotNull();
1403  }
1404  if (CanEnsureNotNullAt(destination, instruction)) {
1405    optimizations.SetDestinationIsNotNull();
1406  }
1407  if (destination == source) {
1408    optimizations.SetDestinationIsSource();
1409  }
1410
1411  if (IsArrayLengthOf(count, source)) {
1412    optimizations.SetCountIsSourceLength();
1413  }
1414
1415  if (IsArrayLengthOf(count, destination)) {
1416    optimizations.SetCountIsDestinationLength();
1417  }
1418
1419  {
1420    ScopedObjectAccess soa(Thread::Current());
1421    ReferenceTypeInfo destination_rti = destination->GetReferenceTypeInfo();
1422    if (destination_rti.IsValid()) {
1423      if (destination_rti.IsObjectArray()) {
1424        if (destination_rti.IsExact()) {
1425          optimizations.SetDoesNotNeedTypeCheck();
1426        }
1427        optimizations.SetDestinationIsTypedObjectArray();
1428      }
1429      if (destination_rti.IsPrimitiveArrayClass()) {
1430        optimizations.SetDestinationIsPrimitiveArray();
1431      } else if (destination_rti.IsNonPrimitiveArrayClass()) {
1432        optimizations.SetDestinationIsNonPrimitiveArray();
1433      }
1434    }
1435    ReferenceTypeInfo source_rti = source->GetReferenceTypeInfo();
1436    if (source_rti.IsValid()) {
1437      if (destination_rti.IsValid() && destination_rti.CanArrayHoldValuesOf(source_rti)) {
1438        optimizations.SetDoesNotNeedTypeCheck();
1439      }
1440      if (source_rti.IsPrimitiveArrayClass()) {
1441        optimizations.SetSourceIsPrimitiveArray();
1442      } else if (source_rti.IsNonPrimitiveArrayClass()) {
1443        optimizations.SetSourceIsNonPrimitiveArray();
1444      }
1445    }
1446  }
1447}
1448
1449void InstructionSimplifierVisitor::VisitInvoke(HInvoke* instruction) {
1450  if (instruction->GetIntrinsic() == Intrinsics::kStringEquals) {
1451    SimplifyStringEquals(instruction);
1452  } else if (instruction->GetIntrinsic() == Intrinsics::kSystemArrayCopy) {
1453    SimplifySystemArrayCopy(instruction);
1454  } else if (instruction->GetIntrinsic() == Intrinsics::kIntegerRotateRight ||
1455             instruction->GetIntrinsic() == Intrinsics::kLongRotateRight) {
1456    SimplifyRotate(instruction, false);
1457  } else if (instruction->GetIntrinsic() == Intrinsics::kIntegerRotateLeft ||
1458             instruction->GetIntrinsic() == Intrinsics::kLongRotateLeft) {
1459    SimplifyRotate(instruction, true);
1460  }
1461}
1462
1463void InstructionSimplifierVisitor::VisitDeoptimize(HDeoptimize* deoptimize) {
1464  HInstruction* cond = deoptimize->InputAt(0);
1465  if (cond->IsConstant()) {
1466    if (cond->AsIntConstant()->IsZero()) {
1467      // Never deopt: instruction can be removed.
1468      deoptimize->GetBlock()->RemoveInstruction(deoptimize);
1469    } else {
1470      // Always deopt.
1471    }
1472  }
1473}
1474
1475}  // namespace art
1476