instruction_simplifier.cc revision aae9e66a727756bc965121a60ffcef89ed370e6c
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 "mirror/class-inl.h"
20#include "scoped_thread_state_change.h"
21
22namespace art {
23
24class InstructionSimplifierVisitor : public HGraphVisitor {
25 public:
26  InstructionSimplifierVisitor(HGraph* graph, OptimizingCompilerStats* stats)
27      : HGraphVisitor(graph),
28        stats_(stats) {}
29
30  void Run();
31
32 private:
33  void RecordSimplification() {
34    simplification_occurred_ = true;
35    simplifications_at_current_position_++;
36    if (stats_) {
37      stats_->RecordStat(kInstructionSimplifications);
38    }
39  }
40
41  bool TryMoveNegOnInputsAfterBinop(HBinaryOperation* binop);
42  void VisitShift(HBinaryOperation* shift);
43
44  void VisitSuspendCheck(HSuspendCheck* check) OVERRIDE;
45  void VisitEqual(HEqual* equal) OVERRIDE;
46  void VisitNotEqual(HNotEqual* equal) OVERRIDE;
47  void VisitBooleanNot(HBooleanNot* bool_not) OVERRIDE;
48  void VisitInstanceFieldSet(HInstanceFieldSet* equal) OVERRIDE;
49  void VisitStaticFieldSet(HStaticFieldSet* equal) OVERRIDE;
50  void VisitArraySet(HArraySet* equal) OVERRIDE;
51  void VisitTypeConversion(HTypeConversion* instruction) OVERRIDE;
52  void VisitNullCheck(HNullCheck* instruction) OVERRIDE;
53  void VisitArrayLength(HArrayLength* instruction) OVERRIDE;
54  void VisitCheckCast(HCheckCast* instruction) OVERRIDE;
55  void VisitAdd(HAdd* instruction) OVERRIDE;
56  void VisitAnd(HAnd* instruction) OVERRIDE;
57  void VisitCondition(HCondition* instruction) OVERRIDE;
58  void VisitGreaterThan(HGreaterThan* condition) OVERRIDE;
59  void VisitGreaterThanOrEqual(HGreaterThanOrEqual* condition) OVERRIDE;
60  void VisitLessThan(HLessThan* condition) OVERRIDE;
61  void VisitLessThanOrEqual(HLessThanOrEqual* condition) OVERRIDE;
62  void VisitDiv(HDiv* instruction) OVERRIDE;
63  void VisitMul(HMul* instruction) OVERRIDE;
64  void VisitNeg(HNeg* instruction) OVERRIDE;
65  void VisitNot(HNot* instruction) OVERRIDE;
66  void VisitOr(HOr* instruction) OVERRIDE;
67  void VisitShl(HShl* instruction) OVERRIDE;
68  void VisitShr(HShr* instruction) OVERRIDE;
69  void VisitSub(HSub* instruction) OVERRIDE;
70  void VisitUShr(HUShr* instruction) OVERRIDE;
71  void VisitXor(HXor* instruction) OVERRIDE;
72  void VisitInstanceOf(HInstanceOf* instruction) OVERRIDE;
73  void VisitFakeString(HFakeString* fake_string) OVERRIDE;
74  bool IsDominatedByInputNullCheck(HInstruction* instr);
75
76  OptimizingCompilerStats* stats_;
77  bool simplification_occurred_ = false;
78  int simplifications_at_current_position_ = 0;
79  // We ensure we do not loop infinitely. The value is a finger in the air guess
80  // that should allow enough simplification.
81  static constexpr int kMaxSamePositionSimplifications = 10;
82};
83
84void InstructionSimplifier::Run() {
85  InstructionSimplifierVisitor visitor(graph_, stats_);
86  visitor.Run();
87}
88
89void InstructionSimplifierVisitor::Run() {
90  // Iterate in reverse post order to open up more simplifications to users
91  // of instructions that got simplified.
92  for (HReversePostOrderIterator it(*GetGraph()); !it.Done();) {
93    // The simplification of an instruction to another instruction may yield
94    // possibilities for other simplifications. So although we perform a reverse
95    // post order visit, we sometimes need to revisit an instruction index.
96    simplification_occurred_ = false;
97    VisitBasicBlock(it.Current());
98    if (simplification_occurred_ &&
99        (simplifications_at_current_position_ < kMaxSamePositionSimplifications)) {
100      // New simplifications may be applicable to the instruction at the
101      // current index, so don't advance the iterator.
102      continue;
103    }
104    simplifications_at_current_position_ = 0;
105    it.Advance();
106  }
107}
108
109namespace {
110
111bool AreAllBitsSet(HConstant* constant) {
112  return Int64FromConstant(constant) == -1;
113}
114
115}  // namespace
116
117// Returns true if the code was simplified to use only one negation operation
118// after the binary operation instead of one on each of the inputs.
119bool InstructionSimplifierVisitor::TryMoveNegOnInputsAfterBinop(HBinaryOperation* binop) {
120  DCHECK(binop->IsAdd() || binop->IsSub());
121  DCHECK(binop->GetLeft()->IsNeg() && binop->GetRight()->IsNeg());
122  HNeg* left_neg = binop->GetLeft()->AsNeg();
123  HNeg* right_neg = binop->GetRight()->AsNeg();
124  if (!left_neg->HasOnlyOneNonEnvironmentUse() ||
125      !right_neg->HasOnlyOneNonEnvironmentUse()) {
126    return false;
127  }
128  // Replace code looking like
129  //    NEG tmp1, a
130  //    NEG tmp2, b
131  //    ADD dst, tmp1, tmp2
132  // with
133  //    ADD tmp, a, b
134  //    NEG dst, tmp
135  // Note that we cannot optimize `(-a) + (-b)` to `-(a + b)` for floating-point.
136  // When `a` is `-0.0` and `b` is `0.0`, the former expression yields `0.0`,
137  // while the later yields `-0.0`.
138  if (!Primitive::IsIntegralType(binop->GetType())) {
139    return false;
140  }
141  binop->ReplaceInput(left_neg->GetInput(), 0);
142  binop->ReplaceInput(right_neg->GetInput(), 1);
143  left_neg->GetBlock()->RemoveInstruction(left_neg);
144  right_neg->GetBlock()->RemoveInstruction(right_neg);
145  HNeg* neg = new (GetGraph()->GetArena()) HNeg(binop->GetType(), binop);
146  binop->GetBlock()->InsertInstructionBefore(neg, binop->GetNext());
147  binop->ReplaceWithExceptInReplacementAtIndex(neg, 0);
148  RecordSimplification();
149  return true;
150}
151
152void InstructionSimplifierVisitor::VisitShift(HBinaryOperation* instruction) {
153  DCHECK(instruction->IsShl() || instruction->IsShr() || instruction->IsUShr());
154  HConstant* input_cst = instruction->GetConstantRight();
155  HInstruction* input_other = instruction->GetLeastConstantLeft();
156
157  if (input_cst != nullptr) {
158    if (input_cst->IsZero()) {
159      // Replace code looking like
160      //    SHL dst, src, 0
161      // with
162      //    src
163      instruction->ReplaceWith(input_other);
164      instruction->GetBlock()->RemoveInstruction(instruction);
165    } else if (instruction->IsShl() && input_cst->IsOne()) {
166      // Replace Shl looking like
167      //    SHL dst, src, 1
168      // with
169      //    ADD dst, src, src
170      HAdd *add = new(GetGraph()->GetArena()) HAdd(instruction->GetType(),
171                                                   input_other,
172                                                   input_other);
173      instruction->GetBlock()->ReplaceAndRemoveInstructionWith(instruction, add);
174      RecordSimplification();
175    }
176  }
177}
178
179void InstructionSimplifierVisitor::VisitNullCheck(HNullCheck* null_check) {
180  HInstruction* obj = null_check->InputAt(0);
181  if (!obj->CanBeNull()) {
182    null_check->ReplaceWith(obj);
183    null_check->GetBlock()->RemoveInstruction(null_check);
184    if (stats_ != nullptr) {
185      stats_->RecordStat(MethodCompilationStat::kRemovedNullCheck);
186    }
187  }
188}
189
190bool InstructionSimplifierVisitor::IsDominatedByInputNullCheck(HInstruction* instr) {
191  HInstruction* input = instr->InputAt(0);
192  for (HUseIterator<HInstruction*> it(input->GetUses()); !it.Done(); it.Advance()) {
193    HInstruction* use = it.Current()->GetUser();
194    if (use->IsNullCheck() && use->StrictlyDominates(instr)) {
195      return true;
196    }
197  }
198  return false;
199}
200
201// Returns whether doing a type test between the class of `object` against `klass` has
202// a statically known outcome. The result of the test is stored in `outcome`.
203static bool TypeCheckHasKnownOutcome(HLoadClass* klass, HInstruction* object, bool* outcome) {
204  DCHECK(!object->IsNullConstant()) << "Null constants should be special cased";
205  ReferenceTypeInfo obj_rti = object->GetReferenceTypeInfo();
206  ScopedObjectAccess soa(Thread::Current());
207  if (!obj_rti.IsValid()) {
208    // We run the simplifier before the reference type propagation so type info might not be
209    // available.
210    return false;
211  }
212
213  ReferenceTypeInfo class_rti = klass->GetLoadedClassRTI();
214  DCHECK(class_rti.IsValid() && class_rti.IsExact());
215  if (class_rti.IsSupertypeOf(obj_rti)) {
216    *outcome = true;
217    return true;
218  } else if (obj_rti.IsExact()) {
219    // The test failed at compile time so will also fail at runtime.
220    *outcome = false;
221    return true;
222  } else if (!class_rti.IsInterface()
223             && !obj_rti.IsInterface()
224             && !obj_rti.IsSupertypeOf(class_rti)) {
225    // Different type hierarchy. The test will fail.
226    *outcome = false;
227    return true;
228  }
229  return false;
230}
231
232void InstructionSimplifierVisitor::VisitCheckCast(HCheckCast* check_cast) {
233  HInstruction* object = check_cast->InputAt(0);
234  if (!object->CanBeNull() || IsDominatedByInputNullCheck(check_cast)) {
235    check_cast->ClearMustDoNullCheck();
236  }
237
238  if (object->IsNullConstant()) {
239    check_cast->GetBlock()->RemoveInstruction(check_cast);
240    if (stats_ != nullptr) {
241      stats_->RecordStat(MethodCompilationStat::kRemovedCheckedCast);
242    }
243    return;
244  }
245
246  bool outcome;
247  HLoadClass* load_class = check_cast->InputAt(1)->AsLoadClass();
248  if (TypeCheckHasKnownOutcome(load_class, object, &outcome)) {
249    if (outcome) {
250      check_cast->GetBlock()->RemoveInstruction(check_cast);
251      if (stats_ != nullptr) {
252        stats_->RecordStat(MethodCompilationStat::kRemovedCheckedCast);
253      }
254      if (!load_class->HasUses()) {
255        // We cannot rely on DCE to remove the class because the `HLoadClass` thinks it can throw.
256        // However, here we know that it cannot because the checkcast was successfull, hence
257        // the class was already loaded.
258        load_class->GetBlock()->RemoveInstruction(load_class);
259      }
260    } else {
261      // Don't do anything for exceptional cases for now. Ideally we should remove
262      // all instructions and blocks this instruction dominates.
263    }
264  }
265}
266
267void InstructionSimplifierVisitor::VisitInstanceOf(HInstanceOf* instruction) {
268  HInstruction* object = instruction->InputAt(0);
269  bool can_be_null = true;
270  if (!object->CanBeNull() || IsDominatedByInputNullCheck(instruction)) {
271    can_be_null = false;
272    instruction->ClearMustDoNullCheck();
273  }
274
275  HGraph* graph = GetGraph();
276  if (object->IsNullConstant()) {
277    instruction->ReplaceWith(graph->GetIntConstant(0));
278    instruction->GetBlock()->RemoveInstruction(instruction);
279    RecordSimplification();
280    return;
281  }
282
283  bool outcome;
284  HLoadClass* load_class = instruction->InputAt(1)->AsLoadClass();
285  if (TypeCheckHasKnownOutcome(load_class, object, &outcome)) {
286    if (outcome && can_be_null) {
287      // Type test will succeed, we just need a null test.
288      HNotEqual* test = new (graph->GetArena()) HNotEqual(graph->GetNullConstant(), object);
289      instruction->GetBlock()->InsertInstructionBefore(test, instruction);
290      instruction->ReplaceWith(test);
291    } else {
292      // We've statically determined the result of the instanceof.
293      instruction->ReplaceWith(graph->GetIntConstant(outcome));
294    }
295    RecordSimplification();
296    instruction->GetBlock()->RemoveInstruction(instruction);
297    if (outcome && !load_class->HasUses()) {
298      // We cannot rely on DCE to remove the class because the `HLoadClass` thinks it can throw.
299      // However, here we know that it cannot because the instanceof check was successfull, hence
300      // the class was already loaded.
301      load_class->GetBlock()->RemoveInstruction(load_class);
302    }
303  }
304}
305
306void InstructionSimplifierVisitor::VisitInstanceFieldSet(HInstanceFieldSet* instruction) {
307  if ((instruction->GetValue()->GetType() == Primitive::kPrimNot)
308      && !instruction->GetValue()->CanBeNull()) {
309    instruction->ClearValueCanBeNull();
310  }
311}
312
313void InstructionSimplifierVisitor::VisitStaticFieldSet(HStaticFieldSet* instruction) {
314  if ((instruction->GetValue()->GetType() == Primitive::kPrimNot)
315      && !instruction->GetValue()->CanBeNull()) {
316    instruction->ClearValueCanBeNull();
317  }
318}
319
320void InstructionSimplifierVisitor::VisitSuspendCheck(HSuspendCheck* check) {
321  HBasicBlock* block = check->GetBlock();
322  // Currently always keep the suspend check at entry.
323  if (block->IsEntryBlock()) return;
324
325  // Currently always keep suspend checks at loop entry.
326  if (block->IsLoopHeader() && block->GetFirstInstruction() == check) {
327    DCHECK(block->GetLoopInformation()->GetSuspendCheck() == check);
328    return;
329  }
330
331  // Remove the suspend check that was added at build time for the baseline
332  // compiler.
333  block->RemoveInstruction(check);
334}
335
336void InstructionSimplifierVisitor::VisitEqual(HEqual* equal) {
337  HInstruction* input_const = equal->GetConstantRight();
338  if (input_const != nullptr) {
339    HInstruction* input_value = equal->GetLeastConstantLeft();
340    if (input_value->GetType() == Primitive::kPrimBoolean && input_const->IsIntConstant()) {
341      HBasicBlock* block = equal->GetBlock();
342      // We are comparing the boolean to a constant which is of type int and can
343      // be any constant.
344      if (input_const->AsIntConstant()->IsOne()) {
345        // Replace (bool_value == true) with bool_value
346        equal->ReplaceWith(input_value);
347        block->RemoveInstruction(equal);
348        RecordSimplification();
349      } else if (input_const->AsIntConstant()->IsZero()) {
350        // Replace (bool_value == false) with !bool_value
351        block->ReplaceAndRemoveInstructionWith(
352            equal, new (block->GetGraph()->GetArena()) HBooleanNot(input_value));
353        RecordSimplification();
354      } else {
355        // Replace (bool_value == integer_not_zero_nor_one_constant) with false
356        equal->ReplaceWith(GetGraph()->GetIntConstant(0));
357        block->RemoveInstruction(equal);
358        RecordSimplification();
359      }
360    } else {
361      VisitCondition(equal);
362    }
363  } else {
364    VisitCondition(equal);
365  }
366}
367
368void InstructionSimplifierVisitor::VisitNotEqual(HNotEqual* not_equal) {
369  HInstruction* input_const = not_equal->GetConstantRight();
370  if (input_const != nullptr) {
371    HInstruction* input_value = not_equal->GetLeastConstantLeft();
372    if (input_value->GetType() == Primitive::kPrimBoolean && input_const->IsIntConstant()) {
373      HBasicBlock* block = not_equal->GetBlock();
374      // We are comparing the boolean to a constant which is of type int and can
375      // be any constant.
376      if (input_const->AsIntConstant()->IsOne()) {
377        // Replace (bool_value != true) with !bool_value
378        block->ReplaceAndRemoveInstructionWith(
379            not_equal, new (block->GetGraph()->GetArena()) HBooleanNot(input_value));
380        RecordSimplification();
381      } else if (input_const->AsIntConstant()->IsZero()) {
382        // Replace (bool_value != false) with bool_value
383        not_equal->ReplaceWith(input_value);
384        block->RemoveInstruction(not_equal);
385        RecordSimplification();
386      } else {
387        // Replace (bool_value != integer_not_zero_nor_one_constant) with true
388        not_equal->ReplaceWith(GetGraph()->GetIntConstant(1));
389        block->RemoveInstruction(not_equal);
390        RecordSimplification();
391      }
392    } else {
393      VisitCondition(not_equal);
394    }
395  } else {
396    VisitCondition(not_equal);
397  }
398}
399
400void InstructionSimplifierVisitor::VisitBooleanNot(HBooleanNot* bool_not) {
401  HInstruction* parent = bool_not->InputAt(0);
402  if (parent->IsBooleanNot()) {
403    HInstruction* value = parent->InputAt(0);
404    // Replace (!(!bool_value)) with bool_value
405    bool_not->ReplaceWith(value);
406    bool_not->GetBlock()->RemoveInstruction(bool_not);
407    // It is possible that `parent` is dead at this point but we leave
408    // its removal to DCE for simplicity.
409    RecordSimplification();
410  }
411}
412
413void InstructionSimplifierVisitor::VisitArrayLength(HArrayLength* instruction) {
414  HInstruction* input = instruction->InputAt(0);
415  // If the array is a NewArray with constant size, replace the array length
416  // with the constant instruction. This helps the bounds check elimination phase.
417  if (input->IsNewArray()) {
418    input = input->InputAt(0);
419    if (input->IsIntConstant()) {
420      instruction->ReplaceWith(input);
421    }
422  }
423}
424
425void InstructionSimplifierVisitor::VisitArraySet(HArraySet* instruction) {
426  HInstruction* value = instruction->GetValue();
427  if (value->GetType() != Primitive::kPrimNot) return;
428
429  if (value->IsArrayGet()) {
430    if (value->AsArrayGet()->GetArray() == instruction->GetArray()) {
431      // If the code is just swapping elements in the array, no need for a type check.
432      instruction->ClearNeedsTypeCheck();
433    }
434  }
435
436  if (value->IsNullConstant()) {
437    instruction->ClearNeedsTypeCheck();
438  }
439
440  if (!value->CanBeNull()) {
441    instruction->ClearValueCanBeNull();
442  }
443}
444
445void InstructionSimplifierVisitor::VisitTypeConversion(HTypeConversion* instruction) {
446  if (instruction->GetResultType() == instruction->GetInputType()) {
447    // Remove the instruction if it's converting to the same type.
448    instruction->ReplaceWith(instruction->GetInput());
449    instruction->GetBlock()->RemoveInstruction(instruction);
450  }
451}
452
453void InstructionSimplifierVisitor::VisitAdd(HAdd* instruction) {
454  HConstant* input_cst = instruction->GetConstantRight();
455  HInstruction* input_other = instruction->GetLeastConstantLeft();
456  if ((input_cst != nullptr) && input_cst->IsZero()) {
457    // Replace code looking like
458    //    ADD dst, src, 0
459    // with
460    //    src
461    // Note that we cannot optimize `x + 0.0` to `x` for floating-point. When
462    // `x` is `-0.0`, the former expression yields `0.0`, while the later
463    // yields `-0.0`.
464    if (Primitive::IsIntegralType(instruction->GetType())) {
465      instruction->ReplaceWith(input_other);
466      instruction->GetBlock()->RemoveInstruction(instruction);
467      return;
468    }
469  }
470
471  HInstruction* left = instruction->GetLeft();
472  HInstruction* right = instruction->GetRight();
473  bool left_is_neg = left->IsNeg();
474  bool right_is_neg = right->IsNeg();
475
476  if (left_is_neg && right_is_neg) {
477    if (TryMoveNegOnInputsAfterBinop(instruction)) {
478      return;
479    }
480  }
481
482  HNeg* neg = left_is_neg ? left->AsNeg() : right->AsNeg();
483  if ((left_is_neg ^ right_is_neg) && neg->HasOnlyOneNonEnvironmentUse()) {
484    // Replace code looking like
485    //    NEG tmp, b
486    //    ADD dst, a, tmp
487    // with
488    //    SUB dst, a, b
489    // We do not perform the optimization if the input negation has environment
490    // uses or multiple non-environment uses as it could lead to worse code. In
491    // particular, we do not want the live range of `b` to be extended if we are
492    // not sure the initial 'NEG' instruction can be removed.
493    HInstruction* other = left_is_neg ? right : left;
494    HSub* sub = new(GetGraph()->GetArena()) HSub(instruction->GetType(), other, neg->GetInput());
495    instruction->GetBlock()->ReplaceAndRemoveInstructionWith(instruction, sub);
496    RecordSimplification();
497    neg->GetBlock()->RemoveInstruction(neg);
498  }
499}
500
501void InstructionSimplifierVisitor::VisitAnd(HAnd* instruction) {
502  HConstant* input_cst = instruction->GetConstantRight();
503  HInstruction* input_other = instruction->GetLeastConstantLeft();
504
505  if ((input_cst != nullptr) && AreAllBitsSet(input_cst)) {
506    // Replace code looking like
507    //    AND dst, src, 0xFFF...FF
508    // with
509    //    src
510    instruction->ReplaceWith(input_other);
511    instruction->GetBlock()->RemoveInstruction(instruction);
512    return;
513  }
514
515  // We assume that GVN has run before, so we only perform a pointer comparison.
516  // If for some reason the values are equal but the pointers are different, we
517  // are still correct and only miss an optimization opportunity.
518  if (instruction->GetLeft() == instruction->GetRight()) {
519    // Replace code looking like
520    //    AND dst, src, src
521    // with
522    //    src
523    instruction->ReplaceWith(instruction->GetLeft());
524    instruction->GetBlock()->RemoveInstruction(instruction);
525  }
526}
527
528void InstructionSimplifierVisitor::VisitGreaterThan(HGreaterThan* condition) {
529  VisitCondition(condition);
530}
531
532void InstructionSimplifierVisitor::VisitGreaterThanOrEqual(HGreaterThanOrEqual* condition) {
533  VisitCondition(condition);
534}
535
536void InstructionSimplifierVisitor::VisitLessThan(HLessThan* condition) {
537  VisitCondition(condition);
538}
539
540void InstructionSimplifierVisitor::VisitLessThanOrEqual(HLessThanOrEqual* condition) {
541  VisitCondition(condition);
542}
543
544void InstructionSimplifierVisitor::VisitCondition(HCondition* condition) {
545  // Try to fold an HCompare into this HCondition.
546
547  // This simplification is currently supported on x86, x86_64, ARM and ARM64.
548  // TODO: Implement it for MIPS64.
549  InstructionSet instruction_set = GetGraph()->GetInstructionSet();
550  if (instruction_set == kMips64) {
551    return;
552  }
553
554  HInstruction* left = condition->GetLeft();
555  HInstruction* right = condition->GetRight();
556  // We can only replace an HCondition which compares a Compare to 0.
557  // Both 'dx' and 'jack' generate a compare to 0 when compiling a
558  // condition with a long, float or double comparison as input.
559  if (!left->IsCompare() || !right->IsConstant() || right->AsIntConstant()->GetValue() != 0) {
560    // Conversion is not possible.
561    return;
562  }
563
564  // Is the Compare only used for this purpose?
565  if (!left->GetUses().HasOnlyOneUse()) {
566    // Someone else also wants the result of the compare.
567    return;
568  }
569
570  if (!left->GetEnvUses().IsEmpty()) {
571    // There is a reference to the compare result in an environment. Do we really need it?
572    if (GetGraph()->IsDebuggable()) {
573      return;
574    }
575
576    // We have to ensure that there are no deopt points in the sequence.
577    if (left->HasAnyEnvironmentUseBefore(condition)) {
578      return;
579    }
580  }
581
582  // Clean up any environment uses from the HCompare, if any.
583  left->RemoveEnvironmentUsers();
584
585  // We have decided to fold the HCompare into the HCondition. Transfer the information.
586  condition->SetBias(left->AsCompare()->GetBias());
587
588  // Replace the operands of the HCondition.
589  condition->ReplaceInput(left->InputAt(0), 0);
590  condition->ReplaceInput(left->InputAt(1), 1);
591
592  // Remove the HCompare.
593  left->GetBlock()->RemoveInstruction(left);
594
595  RecordSimplification();
596}
597
598void InstructionSimplifierVisitor::VisitDiv(HDiv* instruction) {
599  HConstant* input_cst = instruction->GetConstantRight();
600  HInstruction* input_other = instruction->GetLeastConstantLeft();
601  Primitive::Type type = instruction->GetType();
602
603  if ((input_cst != nullptr) && input_cst->IsOne()) {
604    // Replace code looking like
605    //    DIV dst, src, 1
606    // with
607    //    src
608    instruction->ReplaceWith(input_other);
609    instruction->GetBlock()->RemoveInstruction(instruction);
610    return;
611  }
612
613  if ((input_cst != nullptr) && input_cst->IsMinusOne()) {
614    // Replace code looking like
615    //    DIV dst, src, -1
616    // with
617    //    NEG dst, src
618    instruction->GetBlock()->ReplaceAndRemoveInstructionWith(
619        instruction, new (GetGraph()->GetArena()) HNeg(type, input_other));
620    RecordSimplification();
621    return;
622  }
623
624  if ((input_cst != nullptr) && Primitive::IsFloatingPointType(type)) {
625    // Try replacing code looking like
626    //    DIV dst, src, constant
627    // with
628    //    MUL dst, src, 1 / constant
629    HConstant* reciprocal = nullptr;
630    if (type == Primitive::Primitive::kPrimDouble) {
631      double value = input_cst->AsDoubleConstant()->GetValue();
632      if (CanDivideByReciprocalMultiplyDouble(bit_cast<int64_t, double>(value))) {
633        reciprocal = GetGraph()->GetDoubleConstant(1.0 / value);
634      }
635    } else {
636      DCHECK_EQ(type, Primitive::kPrimFloat);
637      float value = input_cst->AsFloatConstant()->GetValue();
638      if (CanDivideByReciprocalMultiplyFloat(bit_cast<int32_t, float>(value))) {
639        reciprocal = GetGraph()->GetFloatConstant(1.0f / value);
640      }
641    }
642
643    if (reciprocal != nullptr) {
644      instruction->GetBlock()->ReplaceAndRemoveInstructionWith(
645          instruction, new (GetGraph()->GetArena()) HMul(type, input_other, reciprocal));
646      RecordSimplification();
647      return;
648    }
649  }
650}
651
652void InstructionSimplifierVisitor::VisitMul(HMul* instruction) {
653  HConstant* input_cst = instruction->GetConstantRight();
654  HInstruction* input_other = instruction->GetLeastConstantLeft();
655  Primitive::Type type = instruction->GetType();
656  HBasicBlock* block = instruction->GetBlock();
657  ArenaAllocator* allocator = GetGraph()->GetArena();
658
659  if (input_cst == nullptr) {
660    return;
661  }
662
663  if (input_cst->IsOne()) {
664    // Replace code looking like
665    //    MUL dst, src, 1
666    // with
667    //    src
668    instruction->ReplaceWith(input_other);
669    instruction->GetBlock()->RemoveInstruction(instruction);
670    return;
671  }
672
673  if (input_cst->IsMinusOne() &&
674      (Primitive::IsFloatingPointType(type) || Primitive::IsIntOrLongType(type))) {
675    // Replace code looking like
676    //    MUL dst, src, -1
677    // with
678    //    NEG dst, src
679    HNeg* neg = new (allocator) HNeg(type, input_other);
680    block->ReplaceAndRemoveInstructionWith(instruction, neg);
681    RecordSimplification();
682    return;
683  }
684
685  if (Primitive::IsFloatingPointType(type) &&
686      ((input_cst->IsFloatConstant() && input_cst->AsFloatConstant()->GetValue() == 2.0f) ||
687       (input_cst->IsDoubleConstant() && input_cst->AsDoubleConstant()->GetValue() == 2.0))) {
688    // Replace code looking like
689    //    FP_MUL dst, src, 2.0
690    // with
691    //    FP_ADD dst, src, src
692    // The 'int' and 'long' cases are handled below.
693    block->ReplaceAndRemoveInstructionWith(instruction,
694                                           new (allocator) HAdd(type, input_other, input_other));
695    RecordSimplification();
696    return;
697  }
698
699  if (Primitive::IsIntOrLongType(type)) {
700    int64_t factor = Int64FromConstant(input_cst);
701    // Even though constant propagation also takes care of the zero case, other
702    // optimizations can lead to having a zero multiplication.
703    if (factor == 0) {
704      // Replace code looking like
705      //    MUL dst, src, 0
706      // with
707      //    0
708      instruction->ReplaceWith(input_cst);
709      instruction->GetBlock()->RemoveInstruction(instruction);
710    } else if (IsPowerOfTwo(factor)) {
711      // Replace code looking like
712      //    MUL dst, src, pow_of_2
713      // with
714      //    SHL dst, src, log2(pow_of_2)
715      HIntConstant* shift = GetGraph()->GetIntConstant(WhichPowerOf2(factor));
716      HShl* shl = new(allocator) HShl(type, input_other, shift);
717      block->ReplaceAndRemoveInstructionWith(instruction, shl);
718      RecordSimplification();
719    }
720  }
721}
722
723void InstructionSimplifierVisitor::VisitNeg(HNeg* instruction) {
724  HInstruction* input = instruction->GetInput();
725  if (input->IsNeg()) {
726    // Replace code looking like
727    //    NEG tmp, src
728    //    NEG dst, tmp
729    // with
730    //    src
731    HNeg* previous_neg = input->AsNeg();
732    instruction->ReplaceWith(previous_neg->GetInput());
733    instruction->GetBlock()->RemoveInstruction(instruction);
734    // We perform the optimization even if the input negation has environment
735    // uses since it allows removing the current instruction. But we only delete
736    // the input negation only if it is does not have any uses left.
737    if (!previous_neg->HasUses()) {
738      previous_neg->GetBlock()->RemoveInstruction(previous_neg);
739    }
740    RecordSimplification();
741    return;
742  }
743
744  if (input->IsSub() && input->HasOnlyOneNonEnvironmentUse() &&
745      !Primitive::IsFloatingPointType(input->GetType())) {
746    // Replace code looking like
747    //    SUB tmp, a, b
748    //    NEG dst, tmp
749    // with
750    //    SUB dst, b, a
751    // We do not perform the optimization if the input subtraction has
752    // environment uses or multiple non-environment uses as it could lead to
753    // worse code. In particular, we do not want the live ranges of `a` and `b`
754    // to be extended if we are not sure the initial 'SUB' instruction can be
755    // removed.
756    // We do not perform optimization for fp because we could lose the sign of zero.
757    HSub* sub = input->AsSub();
758    HSub* new_sub =
759        new (GetGraph()->GetArena()) HSub(instruction->GetType(), sub->GetRight(), sub->GetLeft());
760    instruction->GetBlock()->ReplaceAndRemoveInstructionWith(instruction, new_sub);
761    if (!sub->HasUses()) {
762      sub->GetBlock()->RemoveInstruction(sub);
763    }
764    RecordSimplification();
765  }
766}
767
768void InstructionSimplifierVisitor::VisitNot(HNot* instruction) {
769  HInstruction* input = instruction->GetInput();
770  if (input->IsNot()) {
771    // Replace code looking like
772    //    NOT tmp, src
773    //    NOT dst, tmp
774    // with
775    //    src
776    // We perform the optimization even if the input negation has environment
777    // uses since it allows removing the current instruction. But we only delete
778    // the input negation only if it is does not have any uses left.
779    HNot* previous_not = input->AsNot();
780    instruction->ReplaceWith(previous_not->GetInput());
781    instruction->GetBlock()->RemoveInstruction(instruction);
782    if (!previous_not->HasUses()) {
783      previous_not->GetBlock()->RemoveInstruction(previous_not);
784    }
785    RecordSimplification();
786  }
787}
788
789void InstructionSimplifierVisitor::VisitOr(HOr* instruction) {
790  HConstant* input_cst = instruction->GetConstantRight();
791  HInstruction* input_other = instruction->GetLeastConstantLeft();
792
793  if ((input_cst != nullptr) && input_cst->IsZero()) {
794    // Replace code looking like
795    //    OR dst, src, 0
796    // with
797    //    src
798    instruction->ReplaceWith(input_other);
799    instruction->GetBlock()->RemoveInstruction(instruction);
800    return;
801  }
802
803  // We assume that GVN has run before, so we only perform a pointer comparison.
804  // If for some reason the values are equal but the pointers are different, we
805  // are still correct and only miss an optimization opportunity.
806  if (instruction->GetLeft() == instruction->GetRight()) {
807    // Replace code looking like
808    //    OR dst, src, src
809    // with
810    //    src
811    instruction->ReplaceWith(instruction->GetLeft());
812    instruction->GetBlock()->RemoveInstruction(instruction);
813  }
814}
815
816void InstructionSimplifierVisitor::VisitShl(HShl* instruction) {
817  VisitShift(instruction);
818}
819
820void InstructionSimplifierVisitor::VisitShr(HShr* instruction) {
821  VisitShift(instruction);
822}
823
824void InstructionSimplifierVisitor::VisitSub(HSub* instruction) {
825  HConstant* input_cst = instruction->GetConstantRight();
826  HInstruction* input_other = instruction->GetLeastConstantLeft();
827
828  Primitive::Type type = instruction->GetType();
829  if (Primitive::IsFloatingPointType(type)) {
830    return;
831  }
832
833  if ((input_cst != nullptr) && input_cst->IsZero()) {
834    // Replace code looking like
835    //    SUB dst, src, 0
836    // with
837    //    src
838    // Note that we cannot optimize `x - 0.0` to `x` for floating-point. When
839    // `x` is `-0.0`, the former expression yields `0.0`, while the later
840    // yields `-0.0`.
841    instruction->ReplaceWith(input_other);
842    instruction->GetBlock()->RemoveInstruction(instruction);
843    return;
844  }
845
846  HBasicBlock* block = instruction->GetBlock();
847  ArenaAllocator* allocator = GetGraph()->GetArena();
848
849  HInstruction* left = instruction->GetLeft();
850  HInstruction* right = instruction->GetRight();
851  if (left->IsConstant()) {
852    if (Int64FromConstant(left->AsConstant()) == 0) {
853      // Replace code looking like
854      //    SUB dst, 0, src
855      // with
856      //    NEG dst, src
857      // Note that we cannot optimize `0.0 - x` to `-x` for floating-point. When
858      // `x` is `0.0`, the former expression yields `0.0`, while the later
859      // yields `-0.0`.
860      HNeg* neg = new (allocator) HNeg(type, right);
861      block->ReplaceAndRemoveInstructionWith(instruction, neg);
862      RecordSimplification();
863      return;
864    }
865  }
866
867  if (left->IsNeg() && right->IsNeg()) {
868    if (TryMoveNegOnInputsAfterBinop(instruction)) {
869      return;
870    }
871  }
872
873  if (right->IsNeg() && right->HasOnlyOneNonEnvironmentUse()) {
874    // Replace code looking like
875    //    NEG tmp, b
876    //    SUB dst, a, tmp
877    // with
878    //    ADD dst, a, b
879    HAdd* add = new(GetGraph()->GetArena()) HAdd(type, left, right->AsNeg()->GetInput());
880    instruction->GetBlock()->ReplaceAndRemoveInstructionWith(instruction, add);
881    RecordSimplification();
882    right->GetBlock()->RemoveInstruction(right);
883    return;
884  }
885
886  if (left->IsNeg() && left->HasOnlyOneNonEnvironmentUse()) {
887    // Replace code looking like
888    //    NEG tmp, a
889    //    SUB dst, tmp, b
890    // with
891    //    ADD tmp, a, b
892    //    NEG dst, tmp
893    // The second version is not intrinsically better, but enables more
894    // transformations.
895    HAdd* add = new(GetGraph()->GetArena()) HAdd(type, left->AsNeg()->GetInput(), right);
896    instruction->GetBlock()->InsertInstructionBefore(add, instruction);
897    HNeg* neg = new (GetGraph()->GetArena()) HNeg(instruction->GetType(), add);
898    instruction->GetBlock()->InsertInstructionBefore(neg, instruction);
899    instruction->ReplaceWith(neg);
900    instruction->GetBlock()->RemoveInstruction(instruction);
901    RecordSimplification();
902    left->GetBlock()->RemoveInstruction(left);
903  }
904}
905
906void InstructionSimplifierVisitor::VisitUShr(HUShr* instruction) {
907  VisitShift(instruction);
908}
909
910void InstructionSimplifierVisitor::VisitXor(HXor* instruction) {
911  HConstant* input_cst = instruction->GetConstantRight();
912  HInstruction* input_other = instruction->GetLeastConstantLeft();
913
914  if ((input_cst != nullptr) && input_cst->IsZero()) {
915    // Replace code looking like
916    //    XOR dst, src, 0
917    // with
918    //    src
919    instruction->ReplaceWith(input_other);
920    instruction->GetBlock()->RemoveInstruction(instruction);
921    return;
922  }
923
924  if ((input_cst != nullptr) && AreAllBitsSet(input_cst)) {
925    // Replace code looking like
926    //    XOR dst, src, 0xFFF...FF
927    // with
928    //    NOT dst, src
929    HNot* bitwise_not = new (GetGraph()->GetArena()) HNot(instruction->GetType(), input_other);
930    instruction->GetBlock()->ReplaceAndRemoveInstructionWith(instruction, bitwise_not);
931    RecordSimplification();
932    return;
933  }
934}
935
936void InstructionSimplifierVisitor::VisitFakeString(HFakeString* instruction) {
937  HInstruction* actual_string = nullptr;
938
939  // Find the string we need to replace this instruction with. The actual string is
940  // the return value of a StringFactory call.
941  for (HUseIterator<HInstruction*> it(instruction->GetUses()); !it.Done(); it.Advance()) {
942    HInstruction* use = it.Current()->GetUser();
943    if (use->IsInvokeStaticOrDirect()
944        && use->AsInvokeStaticOrDirect()->IsStringFactoryFor(instruction)) {
945      use->AsInvokeStaticOrDirect()->RemoveFakeStringArgumentAsLastInput();
946      actual_string = use;
947      break;
948    }
949  }
950
951  // Check that there is no other instruction that thinks it is the factory for that string.
952  if (kIsDebugBuild) {
953    CHECK(actual_string != nullptr);
954    for (HUseIterator<HInstruction*> it(instruction->GetUses()); !it.Done(); it.Advance()) {
955      HInstruction* use = it.Current()->GetUser();
956      if (use->IsInvokeStaticOrDirect()) {
957        CHECK(!use->AsInvokeStaticOrDirect()->IsStringFactoryFor(instruction));
958      }
959    }
960  }
961
962  // We need to remove any environment uses of the fake string that are not dominated by
963  // `actual_string` to null.
964  for (HUseIterator<HEnvironment*> it(instruction->GetEnvUses()); !it.Done(); it.Advance()) {
965    HEnvironment* environment = it.Current()->GetUser();
966    if (!actual_string->StrictlyDominates(environment->GetHolder())) {
967      environment->RemoveAsUserOfInput(it.Current()->GetIndex());
968      environment->SetRawEnvAt(it.Current()->GetIndex(), nullptr);
969    }
970  }
971
972  // Only uses dominated by `actual_string` must remain. We can safely replace and remove
973  // `instruction`.
974  instruction->ReplaceWith(actual_string);
975  instruction->GetBlock()->RemoveInstruction(instruction);
976}
977
978}  // namespace art
979