• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "art_method-inl.h"
20 #include "class_linker-inl.h"
21 #include "escape.h"
22 #include "intrinsics.h"
23 #include "mirror/class-inl.h"
24 #include "sharpening.h"
25 #include "scoped_thread_state_change-inl.h"
26 
27 namespace art {
28 
29 class InstructionSimplifierVisitor : public HGraphDelegateVisitor {
30  public:
InstructionSimplifierVisitor(HGraph * graph,CodeGenerator * codegen,CompilerDriver * compiler_driver,OptimizingCompilerStats * stats)31   InstructionSimplifierVisitor(HGraph* graph,
32                                CodeGenerator* codegen,
33                                CompilerDriver* compiler_driver,
34                                OptimizingCompilerStats* stats)
35       : HGraphDelegateVisitor(graph),
36         codegen_(codegen),
37         compiler_driver_(compiler_driver),
38         stats_(stats) {}
39 
40   void Run();
41 
42  private:
RecordSimplification()43   void RecordSimplification() {
44     simplification_occurred_ = true;
45     simplifications_at_current_position_++;
46     MaybeRecordStat(kInstructionSimplifications);
47   }
48 
MaybeRecordStat(MethodCompilationStat stat)49   void MaybeRecordStat(MethodCompilationStat stat) {
50     if (stats_ != nullptr) {
51       stats_->RecordStat(stat);
52     }
53   }
54 
55   bool ReplaceRotateWithRor(HBinaryOperation* op, HUShr* ushr, HShl* shl);
56   bool TryReplaceWithRotate(HBinaryOperation* instruction);
57   bool TryReplaceWithRotateConstantPattern(HBinaryOperation* op, HUShr* ushr, HShl* shl);
58   bool TryReplaceWithRotateRegisterNegPattern(HBinaryOperation* op, HUShr* ushr, HShl* shl);
59   bool TryReplaceWithRotateRegisterSubPattern(HBinaryOperation* op, HUShr* ushr, HShl* shl);
60 
61   bool TryMoveNegOnInputsAfterBinop(HBinaryOperation* binop);
62   // `op` should be either HOr or HAnd.
63   // De Morgan's laws:
64   // ~a & ~b = ~(a | b)  and  ~a | ~b = ~(a & b)
65   bool TryDeMorganNegationFactoring(HBinaryOperation* op);
66   bool TryHandleAssociativeAndCommutativeOperation(HBinaryOperation* instruction);
67   bool TrySubtractionChainSimplification(HBinaryOperation* instruction);
68 
69   void VisitShift(HBinaryOperation* shift);
70 
71   void VisitEqual(HEqual* equal) OVERRIDE;
72   void VisitNotEqual(HNotEqual* equal) OVERRIDE;
73   void VisitBooleanNot(HBooleanNot* bool_not) OVERRIDE;
74   void VisitInstanceFieldSet(HInstanceFieldSet* equal) OVERRIDE;
75   void VisitStaticFieldSet(HStaticFieldSet* equal) OVERRIDE;
76   void VisitArraySet(HArraySet* equal) OVERRIDE;
77   void VisitTypeConversion(HTypeConversion* instruction) OVERRIDE;
78   void VisitNullCheck(HNullCheck* instruction) OVERRIDE;
79   void VisitArrayLength(HArrayLength* instruction) OVERRIDE;
80   void VisitCheckCast(HCheckCast* instruction) OVERRIDE;
81   void VisitAdd(HAdd* instruction) OVERRIDE;
82   void VisitAnd(HAnd* instruction) OVERRIDE;
83   void VisitCondition(HCondition* instruction) OVERRIDE;
84   void VisitGreaterThan(HGreaterThan* condition) OVERRIDE;
85   void VisitGreaterThanOrEqual(HGreaterThanOrEqual* condition) OVERRIDE;
86   void VisitLessThan(HLessThan* condition) OVERRIDE;
87   void VisitLessThanOrEqual(HLessThanOrEqual* condition) OVERRIDE;
88   void VisitBelow(HBelow* condition) OVERRIDE;
89   void VisitBelowOrEqual(HBelowOrEqual* condition) OVERRIDE;
90   void VisitAbove(HAbove* condition) OVERRIDE;
91   void VisitAboveOrEqual(HAboveOrEqual* condition) OVERRIDE;
92   void VisitDiv(HDiv* instruction) OVERRIDE;
93   void VisitMul(HMul* instruction) OVERRIDE;
94   void VisitNeg(HNeg* instruction) OVERRIDE;
95   void VisitNot(HNot* instruction) OVERRIDE;
96   void VisitOr(HOr* instruction) OVERRIDE;
97   void VisitShl(HShl* instruction) OVERRIDE;
98   void VisitShr(HShr* instruction) OVERRIDE;
99   void VisitSub(HSub* instruction) OVERRIDE;
100   void VisitUShr(HUShr* instruction) OVERRIDE;
101   void VisitXor(HXor* instruction) OVERRIDE;
102   void VisitSelect(HSelect* select) OVERRIDE;
103   void VisitIf(HIf* instruction) OVERRIDE;
104   void VisitInstanceOf(HInstanceOf* instruction) OVERRIDE;
105   void VisitInvoke(HInvoke* invoke) OVERRIDE;
106   void VisitDeoptimize(HDeoptimize* deoptimize) OVERRIDE;
107 
108   bool CanEnsureNotNullAt(HInstruction* instr, HInstruction* at) const;
109 
110   void SimplifyRotate(HInvoke* invoke, bool is_left, Primitive::Type type);
111   void SimplifySystemArrayCopy(HInvoke* invoke);
112   void SimplifyStringEquals(HInvoke* invoke);
113   void SimplifyCompare(HInvoke* invoke, bool is_signum, Primitive::Type type);
114   void SimplifyIsNaN(HInvoke* invoke);
115   void SimplifyFP2Int(HInvoke* invoke);
116   void SimplifyStringCharAt(HInvoke* invoke);
117   void SimplifyStringIsEmptyOrLength(HInvoke* invoke);
118   void SimplifyNPEOnArgN(HInvoke* invoke, size_t);
119   void SimplifyReturnThis(HInvoke* invoke);
120   void SimplifyAllocationIntrinsic(HInvoke* invoke);
121   void SimplifyMemBarrier(HInvoke* invoke, MemBarrierKind barrier_kind);
122 
123   CodeGenerator* codegen_;
124   CompilerDriver* compiler_driver_;
125   OptimizingCompilerStats* stats_;
126   bool simplification_occurred_ = false;
127   int simplifications_at_current_position_ = 0;
128   // We ensure we do not loop infinitely. The value should not be too high, since that
129   // would allow looping around the same basic block too many times. The value should
130   // not be too low either, however, since we want to allow revisiting a basic block
131   // with many statements and simplifications at least once.
132   static constexpr int kMaxSamePositionSimplifications = 50;
133 };
134 
Run()135 void InstructionSimplifier::Run() {
136   InstructionSimplifierVisitor visitor(graph_, codegen_, compiler_driver_, stats_);
137   visitor.Run();
138 }
139 
Run()140 void InstructionSimplifierVisitor::Run() {
141   // Iterate in reverse post order to open up more simplifications to users
142   // of instructions that got simplified.
143   for (HBasicBlock* block : GetGraph()->GetReversePostOrder()) {
144     // The simplification of an instruction to another instruction may yield
145     // possibilities for other simplifications. So although we perform a reverse
146     // post order visit, we sometimes need to revisit an instruction index.
147     do {
148       simplification_occurred_ = false;
149       VisitBasicBlock(block);
150     } while (simplification_occurred_ &&
151              (simplifications_at_current_position_ < kMaxSamePositionSimplifications));
152     simplifications_at_current_position_ = 0;
153   }
154 }
155 
156 namespace {
157 
AreAllBitsSet(HConstant * constant)158 bool AreAllBitsSet(HConstant* constant) {
159   return Int64FromConstant(constant) == -1;
160 }
161 
162 }  // namespace
163 
164 // Returns true if the code was simplified to use only one negation operation
165 // after the binary operation instead of one on each of the inputs.
TryMoveNegOnInputsAfterBinop(HBinaryOperation * binop)166 bool InstructionSimplifierVisitor::TryMoveNegOnInputsAfterBinop(HBinaryOperation* binop) {
167   DCHECK(binop->IsAdd() || binop->IsSub());
168   DCHECK(binop->GetLeft()->IsNeg() && binop->GetRight()->IsNeg());
169   HNeg* left_neg = binop->GetLeft()->AsNeg();
170   HNeg* right_neg = binop->GetRight()->AsNeg();
171   if (!left_neg->HasOnlyOneNonEnvironmentUse() ||
172       !right_neg->HasOnlyOneNonEnvironmentUse()) {
173     return false;
174   }
175   // Replace code looking like
176   //    NEG tmp1, a
177   //    NEG tmp2, b
178   //    ADD dst, tmp1, tmp2
179   // with
180   //    ADD tmp, a, b
181   //    NEG dst, tmp
182   // Note that we cannot optimize `(-a) + (-b)` to `-(a + b)` for floating-point.
183   // When `a` is `-0.0` and `b` is `0.0`, the former expression yields `0.0`,
184   // while the later yields `-0.0`.
185   if (!Primitive::IsIntegralType(binop->GetType())) {
186     return false;
187   }
188   binop->ReplaceInput(left_neg->GetInput(), 0);
189   binop->ReplaceInput(right_neg->GetInput(), 1);
190   left_neg->GetBlock()->RemoveInstruction(left_neg);
191   right_neg->GetBlock()->RemoveInstruction(right_neg);
192   HNeg* neg = new (GetGraph()->GetArena()) HNeg(binop->GetType(), binop);
193   binop->GetBlock()->InsertInstructionBefore(neg, binop->GetNext());
194   binop->ReplaceWithExceptInReplacementAtIndex(neg, 0);
195   RecordSimplification();
196   return true;
197 }
198 
TryDeMorganNegationFactoring(HBinaryOperation * op)199 bool InstructionSimplifierVisitor::TryDeMorganNegationFactoring(HBinaryOperation* op) {
200   DCHECK(op->IsAnd() || op->IsOr()) << op->DebugName();
201   Primitive::Type type = op->GetType();
202   HInstruction* left = op->GetLeft();
203   HInstruction* right = op->GetRight();
204 
205   // We can apply De Morgan's laws if both inputs are Not's and are only used
206   // by `op`.
207   if (((left->IsNot() && right->IsNot()) ||
208        (left->IsBooleanNot() && right->IsBooleanNot())) &&
209       left->HasOnlyOneNonEnvironmentUse() &&
210       right->HasOnlyOneNonEnvironmentUse()) {
211     // Replace code looking like
212     //    NOT nota, a
213     //    NOT notb, b
214     //    AND dst, nota, notb (respectively OR)
215     // with
216     //    OR or, a, b         (respectively AND)
217     //    NOT dest, or
218     HInstruction* src_left = left->InputAt(0);
219     HInstruction* src_right = right->InputAt(0);
220     uint32_t dex_pc = op->GetDexPc();
221 
222     // Remove the negations on the inputs.
223     left->ReplaceWith(src_left);
224     right->ReplaceWith(src_right);
225     left->GetBlock()->RemoveInstruction(left);
226     right->GetBlock()->RemoveInstruction(right);
227 
228     // Replace the `HAnd` or `HOr`.
229     HBinaryOperation* hbin;
230     if (op->IsAnd()) {
231       hbin = new (GetGraph()->GetArena()) HOr(type, src_left, src_right, dex_pc);
232     } else {
233       hbin = new (GetGraph()->GetArena()) HAnd(type, src_left, src_right, dex_pc);
234     }
235     HInstruction* hnot;
236     if (left->IsBooleanNot()) {
237       hnot = new (GetGraph()->GetArena()) HBooleanNot(hbin, dex_pc);
238     } else {
239       hnot = new (GetGraph()->GetArena()) HNot(type, hbin, dex_pc);
240     }
241 
242     op->GetBlock()->InsertInstructionBefore(hbin, op);
243     op->GetBlock()->ReplaceAndRemoveInstructionWith(op, hnot);
244 
245     RecordSimplification();
246     return true;
247   }
248 
249   return false;
250 }
251 
VisitShift(HBinaryOperation * instruction)252 void InstructionSimplifierVisitor::VisitShift(HBinaryOperation* instruction) {
253   DCHECK(instruction->IsShl() || instruction->IsShr() || instruction->IsUShr());
254   HInstruction* shift_amount = instruction->GetRight();
255   HInstruction* value = instruction->GetLeft();
256 
257   int64_t implicit_mask = (value->GetType() == Primitive::kPrimLong)
258       ? kMaxLongShiftDistance
259       : kMaxIntShiftDistance;
260 
261   if (shift_amount->IsConstant()) {
262     int64_t cst = Int64FromConstant(shift_amount->AsConstant());
263     int64_t masked_cst = cst & implicit_mask;
264     if (masked_cst == 0) {
265       // Replace code looking like
266       //    SHL dst, value, 0
267       // with
268       //    value
269       instruction->ReplaceWith(value);
270       instruction->GetBlock()->RemoveInstruction(instruction);
271       RecordSimplification();
272       return;
273     } else if (masked_cst != cst) {
274       // Replace code looking like
275       //    SHL dst, value, cst
276       // where cst exceeds maximum distance with the equivalent
277       //    SHL dst, value, cst & implicit_mask
278       // (as defined by shift semantics). This ensures other
279       // optimizations do not need to special case for such situations.
280       DCHECK_EQ(shift_amount->GetType(), Primitive::kPrimInt);
281       instruction->ReplaceInput(GetGraph()->GetIntConstant(masked_cst), /* index */ 1);
282       RecordSimplification();
283       return;
284     }
285   }
286 
287   // Shift operations implicitly mask the shift amount according to the type width. Get rid of
288   // unnecessary explicit masking operations on the shift amount.
289   // Replace code looking like
290   //    AND masked_shift, shift, <superset of implicit mask>
291   //    SHL dst, value, masked_shift
292   // with
293   //    SHL dst, value, shift
294   if (shift_amount->IsAnd()) {
295     HAnd* and_insn = shift_amount->AsAnd();
296     HConstant* mask = and_insn->GetConstantRight();
297     if ((mask != nullptr) && ((Int64FromConstant(mask) & implicit_mask) == implicit_mask)) {
298       instruction->ReplaceInput(and_insn->GetLeastConstantLeft(), 1);
299       RecordSimplification();
300     }
301   }
302 }
303 
IsSubRegBitsMinusOther(HSub * sub,size_t reg_bits,HInstruction * other)304 static bool IsSubRegBitsMinusOther(HSub* sub, size_t reg_bits, HInstruction* other) {
305   return (sub->GetRight() == other &&
306           sub->GetLeft()->IsConstant() &&
307           (Int64FromConstant(sub->GetLeft()->AsConstant()) & (reg_bits - 1)) == 0);
308 }
309 
ReplaceRotateWithRor(HBinaryOperation * op,HUShr * ushr,HShl * shl)310 bool InstructionSimplifierVisitor::ReplaceRotateWithRor(HBinaryOperation* op,
311                                                         HUShr* ushr,
312                                                         HShl* shl) {
313   DCHECK(op->IsAdd() || op->IsXor() || op->IsOr()) << op->DebugName();
314   HRor* ror = new (GetGraph()->GetArena()) HRor(ushr->GetType(), ushr->GetLeft(), ushr->GetRight());
315   op->GetBlock()->ReplaceAndRemoveInstructionWith(op, ror);
316   if (!ushr->HasUses()) {
317     ushr->GetBlock()->RemoveInstruction(ushr);
318   }
319   if (!ushr->GetRight()->HasUses()) {
320     ushr->GetRight()->GetBlock()->RemoveInstruction(ushr->GetRight());
321   }
322   if (!shl->HasUses()) {
323     shl->GetBlock()->RemoveInstruction(shl);
324   }
325   if (!shl->GetRight()->HasUses()) {
326     shl->GetRight()->GetBlock()->RemoveInstruction(shl->GetRight());
327   }
328   RecordSimplification();
329   return true;
330 }
331 
332 // Try to replace a binary operation flanked by one UShr and one Shl with a bitfield rotation.
TryReplaceWithRotate(HBinaryOperation * op)333 bool InstructionSimplifierVisitor::TryReplaceWithRotate(HBinaryOperation* op) {
334   DCHECK(op->IsAdd() || op->IsXor() || op->IsOr());
335   HInstruction* left = op->GetLeft();
336   HInstruction* right = op->GetRight();
337   // If we have an UShr and a Shl (in either order).
338   if ((left->IsUShr() && right->IsShl()) || (left->IsShl() && right->IsUShr())) {
339     HUShr* ushr = left->IsUShr() ? left->AsUShr() : right->AsUShr();
340     HShl* shl = left->IsShl() ? left->AsShl() : right->AsShl();
341     DCHECK(Primitive::IsIntOrLongType(ushr->GetType()));
342     if (ushr->GetType() == shl->GetType() &&
343         ushr->GetLeft() == shl->GetLeft()) {
344       if (ushr->GetRight()->IsConstant() && shl->GetRight()->IsConstant()) {
345         // Shift distances are both constant, try replacing with Ror if they
346         // add up to the register size.
347         return TryReplaceWithRotateConstantPattern(op, ushr, shl);
348       } else if (ushr->GetRight()->IsSub() || shl->GetRight()->IsSub()) {
349         // Shift distances are potentially of the form x and (reg_size - x).
350         return TryReplaceWithRotateRegisterSubPattern(op, ushr, shl);
351       } else if (ushr->GetRight()->IsNeg() || shl->GetRight()->IsNeg()) {
352         // Shift distances are potentially of the form d and -d.
353         return TryReplaceWithRotateRegisterNegPattern(op, ushr, shl);
354       }
355     }
356   }
357   return false;
358 }
359 
360 // Try replacing code looking like (x >>> #rdist OP x << #ldist):
361 //    UShr dst, x,   #rdist
362 //    Shl  tmp, x,   #ldist
363 //    OP   dst, dst, tmp
364 // or like (x >>> #rdist OP x << #-ldist):
365 //    UShr dst, x,   #rdist
366 //    Shl  tmp, x,   #-ldist
367 //    OP   dst, dst, tmp
368 // with
369 //    Ror  dst, x,   #rdist
TryReplaceWithRotateConstantPattern(HBinaryOperation * op,HUShr * ushr,HShl * shl)370 bool InstructionSimplifierVisitor::TryReplaceWithRotateConstantPattern(HBinaryOperation* op,
371                                                                        HUShr* ushr,
372                                                                        HShl* shl) {
373   DCHECK(op->IsAdd() || op->IsXor() || op->IsOr());
374   size_t reg_bits = Primitive::ComponentSize(ushr->GetType()) * kBitsPerByte;
375   size_t rdist = Int64FromConstant(ushr->GetRight()->AsConstant());
376   size_t ldist = Int64FromConstant(shl->GetRight()->AsConstant());
377   if (((ldist + rdist) & (reg_bits - 1)) == 0) {
378     ReplaceRotateWithRor(op, ushr, shl);
379     return true;
380   }
381   return false;
382 }
383 
384 // Replace code looking like (x >>> -d OP x << d):
385 //    Neg  neg, d
386 //    UShr dst, x,   neg
387 //    Shl  tmp, x,   d
388 //    OP   dst, dst, tmp
389 // with
390 //    Neg  neg, d
391 //    Ror  dst, x,   neg
392 // *** OR ***
393 // Replace code looking like (x >>> d OP x << -d):
394 //    UShr dst, x,   d
395 //    Neg  neg, d
396 //    Shl  tmp, x,   neg
397 //    OP   dst, dst, tmp
398 // with
399 //    Ror  dst, x,   d
TryReplaceWithRotateRegisterNegPattern(HBinaryOperation * op,HUShr * ushr,HShl * shl)400 bool InstructionSimplifierVisitor::TryReplaceWithRotateRegisterNegPattern(HBinaryOperation* op,
401                                                                           HUShr* ushr,
402                                                                           HShl* shl) {
403   DCHECK(op->IsAdd() || op->IsXor() || op->IsOr());
404   DCHECK(ushr->GetRight()->IsNeg() || shl->GetRight()->IsNeg());
405   bool neg_is_left = shl->GetRight()->IsNeg();
406   HNeg* neg = neg_is_left ? shl->GetRight()->AsNeg() : ushr->GetRight()->AsNeg();
407   // And the shift distance being negated is the distance being shifted the other way.
408   if (neg->InputAt(0) == (neg_is_left ? ushr->GetRight() : shl->GetRight())) {
409     ReplaceRotateWithRor(op, ushr, shl);
410   }
411   return false;
412 }
413 
414 // Try replacing code looking like (x >>> d OP x << (#bits - d)):
415 //    UShr dst, x,     d
416 //    Sub  ld,  #bits, d
417 //    Shl  tmp, x,     ld
418 //    OP   dst, dst,   tmp
419 // with
420 //    Ror  dst, x,     d
421 // *** OR ***
422 // Replace code looking like (x >>> (#bits - d) OP x << d):
423 //    Sub  rd,  #bits, d
424 //    UShr dst, x,     rd
425 //    Shl  tmp, x,     d
426 //    OP   dst, dst,   tmp
427 // with
428 //    Neg  neg, d
429 //    Ror  dst, x,     neg
TryReplaceWithRotateRegisterSubPattern(HBinaryOperation * op,HUShr * ushr,HShl * shl)430 bool InstructionSimplifierVisitor::TryReplaceWithRotateRegisterSubPattern(HBinaryOperation* op,
431                                                                           HUShr* ushr,
432                                                                           HShl* shl) {
433   DCHECK(op->IsAdd() || op->IsXor() || op->IsOr());
434   DCHECK(ushr->GetRight()->IsSub() || shl->GetRight()->IsSub());
435   size_t reg_bits = Primitive::ComponentSize(ushr->GetType()) * kBitsPerByte;
436   HInstruction* shl_shift = shl->GetRight();
437   HInstruction* ushr_shift = ushr->GetRight();
438   if ((shl_shift->IsSub() && IsSubRegBitsMinusOther(shl_shift->AsSub(), reg_bits, ushr_shift)) ||
439       (ushr_shift->IsSub() && IsSubRegBitsMinusOther(ushr_shift->AsSub(), reg_bits, shl_shift))) {
440     return ReplaceRotateWithRor(op, ushr, shl);
441   }
442   return false;
443 }
444 
VisitNullCheck(HNullCheck * null_check)445 void InstructionSimplifierVisitor::VisitNullCheck(HNullCheck* null_check) {
446   HInstruction* obj = null_check->InputAt(0);
447   if (!obj->CanBeNull()) {
448     null_check->ReplaceWith(obj);
449     null_check->GetBlock()->RemoveInstruction(null_check);
450     if (stats_ != nullptr) {
451       stats_->RecordStat(MethodCompilationStat::kRemovedNullCheck);
452     }
453   }
454 }
455 
CanEnsureNotNullAt(HInstruction * input,HInstruction * at) const456 bool InstructionSimplifierVisitor::CanEnsureNotNullAt(HInstruction* input, HInstruction* at) const {
457   if (!input->CanBeNull()) {
458     return true;
459   }
460 
461   for (const HUseListNode<HInstruction*>& use : input->GetUses()) {
462     HInstruction* user = use.GetUser();
463     if (user->IsNullCheck() && user->StrictlyDominates(at)) {
464       return true;
465     }
466   }
467 
468   return false;
469 }
470 
471 // Returns whether doing a type test between the class of `object` against `klass` has
472 // a statically known outcome. The result of the test is stored in `outcome`.
TypeCheckHasKnownOutcome(HLoadClass * klass,HInstruction * object,bool * outcome)473 static bool TypeCheckHasKnownOutcome(HLoadClass* klass, HInstruction* object, bool* outcome) {
474   DCHECK(!object->IsNullConstant()) << "Null constants should be special cased";
475   ReferenceTypeInfo obj_rti = object->GetReferenceTypeInfo();
476   ScopedObjectAccess soa(Thread::Current());
477   if (!obj_rti.IsValid()) {
478     // We run the simplifier before the reference type propagation so type info might not be
479     // available.
480     return false;
481   }
482 
483   ReferenceTypeInfo class_rti = klass->GetLoadedClassRTI();
484   if (!class_rti.IsValid()) {
485     // Happens when the loaded class is unresolved.
486     return false;
487   }
488   DCHECK(class_rti.IsExact());
489   if (class_rti.IsSupertypeOf(obj_rti)) {
490     *outcome = true;
491     return true;
492   } else if (obj_rti.IsExact()) {
493     // The test failed at compile time so will also fail at runtime.
494     *outcome = false;
495     return true;
496   } else if (!class_rti.IsInterface()
497              && !obj_rti.IsInterface()
498              && !obj_rti.IsSupertypeOf(class_rti)) {
499     // Different type hierarchy. The test will fail.
500     *outcome = false;
501     return true;
502   }
503   return false;
504 }
505 
VisitCheckCast(HCheckCast * check_cast)506 void InstructionSimplifierVisitor::VisitCheckCast(HCheckCast* check_cast) {
507   HInstruction* object = check_cast->InputAt(0);
508   HLoadClass* load_class = check_cast->InputAt(1)->AsLoadClass();
509   if (load_class->NeedsAccessCheck()) {
510     // If we need to perform an access check we cannot remove the instruction.
511     return;
512   }
513 
514   if (CanEnsureNotNullAt(object, check_cast)) {
515     check_cast->ClearMustDoNullCheck();
516   }
517 
518   if (object->IsNullConstant()) {
519     check_cast->GetBlock()->RemoveInstruction(check_cast);
520     MaybeRecordStat(MethodCompilationStat::kRemovedCheckedCast);
521     return;
522   }
523 
524   // Note: The `outcome` is initialized to please valgrind - the compiler can reorder
525   // the return value check with the `outcome` check, b/27651442 .
526   bool outcome = false;
527   if (TypeCheckHasKnownOutcome(load_class, object, &outcome)) {
528     if (outcome) {
529       check_cast->GetBlock()->RemoveInstruction(check_cast);
530       MaybeRecordStat(MethodCompilationStat::kRemovedCheckedCast);
531       if (!load_class->HasUses()) {
532         // We cannot rely on DCE to remove the class because the `HLoadClass` thinks it can throw.
533         // However, here we know that it cannot because the checkcast was successfull, hence
534         // the class was already loaded.
535         load_class->GetBlock()->RemoveInstruction(load_class);
536       }
537     } else {
538       // Don't do anything for exceptional cases for now. Ideally we should remove
539       // all instructions and blocks this instruction dominates.
540     }
541   }
542 }
543 
VisitInstanceOf(HInstanceOf * instruction)544 void InstructionSimplifierVisitor::VisitInstanceOf(HInstanceOf* instruction) {
545   HInstruction* object = instruction->InputAt(0);
546   HLoadClass* load_class = instruction->InputAt(1)->AsLoadClass();
547   if (load_class->NeedsAccessCheck()) {
548     // If we need to perform an access check we cannot remove the instruction.
549     return;
550   }
551 
552   bool can_be_null = true;
553   if (CanEnsureNotNullAt(object, instruction)) {
554     can_be_null = false;
555     instruction->ClearMustDoNullCheck();
556   }
557 
558   HGraph* graph = GetGraph();
559   if (object->IsNullConstant()) {
560     MaybeRecordStat(kRemovedInstanceOf);
561     instruction->ReplaceWith(graph->GetIntConstant(0));
562     instruction->GetBlock()->RemoveInstruction(instruction);
563     RecordSimplification();
564     return;
565   }
566 
567   // Note: The `outcome` is initialized to please valgrind - the compiler can reorder
568   // the return value check with the `outcome` check, b/27651442 .
569   bool outcome = false;
570   if (TypeCheckHasKnownOutcome(load_class, object, &outcome)) {
571     MaybeRecordStat(kRemovedInstanceOf);
572     if (outcome && can_be_null) {
573       // Type test will succeed, we just need a null test.
574       HNotEqual* test = new (graph->GetArena()) HNotEqual(graph->GetNullConstant(), object);
575       instruction->GetBlock()->InsertInstructionBefore(test, instruction);
576       instruction->ReplaceWith(test);
577     } else {
578       // We've statically determined the result of the instanceof.
579       instruction->ReplaceWith(graph->GetIntConstant(outcome));
580     }
581     RecordSimplification();
582     instruction->GetBlock()->RemoveInstruction(instruction);
583     if (outcome && !load_class->HasUses()) {
584       // We cannot rely on DCE to remove the class because the `HLoadClass` thinks it can throw.
585       // However, here we know that it cannot because the instanceof check was successfull, hence
586       // the class was already loaded.
587       load_class->GetBlock()->RemoveInstruction(load_class);
588     }
589   }
590 }
591 
VisitInstanceFieldSet(HInstanceFieldSet * instruction)592 void InstructionSimplifierVisitor::VisitInstanceFieldSet(HInstanceFieldSet* instruction) {
593   if ((instruction->GetValue()->GetType() == Primitive::kPrimNot)
594       && CanEnsureNotNullAt(instruction->GetValue(), instruction)) {
595     instruction->ClearValueCanBeNull();
596   }
597 }
598 
VisitStaticFieldSet(HStaticFieldSet * instruction)599 void InstructionSimplifierVisitor::VisitStaticFieldSet(HStaticFieldSet* instruction) {
600   if ((instruction->GetValue()->GetType() == Primitive::kPrimNot)
601       && CanEnsureNotNullAt(instruction->GetValue(), instruction)) {
602     instruction->ClearValueCanBeNull();
603   }
604 }
605 
GetOppositeConditionSwapOps(ArenaAllocator * arena,HInstruction * cond)606 static HCondition* GetOppositeConditionSwapOps(ArenaAllocator* arena, HInstruction* cond) {
607   HInstruction *lhs = cond->InputAt(0);
608   HInstruction *rhs = cond->InputAt(1);
609   switch (cond->GetKind()) {
610     case HInstruction::kEqual:
611       return new (arena) HEqual(rhs, lhs);
612     case HInstruction::kNotEqual:
613       return new (arena) HNotEqual(rhs, lhs);
614     case HInstruction::kLessThan:
615       return new (arena) HGreaterThan(rhs, lhs);
616     case HInstruction::kLessThanOrEqual:
617       return new (arena) HGreaterThanOrEqual(rhs, lhs);
618     case HInstruction::kGreaterThan:
619       return new (arena) HLessThan(rhs, lhs);
620     case HInstruction::kGreaterThanOrEqual:
621       return new (arena) HLessThanOrEqual(rhs, lhs);
622     case HInstruction::kBelow:
623       return new (arena) HAbove(rhs, lhs);
624     case HInstruction::kBelowOrEqual:
625       return new (arena) HAboveOrEqual(rhs, lhs);
626     case HInstruction::kAbove:
627       return new (arena) HBelow(rhs, lhs);
628     case HInstruction::kAboveOrEqual:
629       return new (arena) HBelowOrEqual(rhs, lhs);
630     default:
631       LOG(FATAL) << "Unknown ConditionType " << cond->GetKind();
632   }
633   return nullptr;
634 }
635 
CmpHasBoolType(HInstruction * input,HInstruction * cmp)636 static bool CmpHasBoolType(HInstruction* input, HInstruction* cmp) {
637   if (input->GetType() == Primitive::kPrimBoolean) {
638     return true;  // input has direct boolean type
639   } else if (cmp->GetUses().HasExactlyOneElement()) {
640     // Comparison also has boolean type if both its input and the instruction
641     // itself feed into the same phi node.
642     HInstruction* user = cmp->GetUses().front().GetUser();
643     return user->IsPhi() && user->HasInput(input) && user->HasInput(cmp);
644   }
645   return false;
646 }
647 
VisitEqual(HEqual * equal)648 void InstructionSimplifierVisitor::VisitEqual(HEqual* equal) {
649   HInstruction* input_const = equal->GetConstantRight();
650   if (input_const != nullptr) {
651     HInstruction* input_value = equal->GetLeastConstantLeft();
652     if (CmpHasBoolType(input_value, equal) && input_const->IsIntConstant()) {
653       HBasicBlock* block = equal->GetBlock();
654       // We are comparing the boolean to a constant which is of type int and can
655       // be any constant.
656       if (input_const->AsIntConstant()->IsTrue()) {
657         // Replace (bool_value == true) with bool_value
658         equal->ReplaceWith(input_value);
659         block->RemoveInstruction(equal);
660         RecordSimplification();
661       } else if (input_const->AsIntConstant()->IsFalse()) {
662         // Replace (bool_value == false) with !bool_value
663         equal->ReplaceWith(GetGraph()->InsertOppositeCondition(input_value, equal));
664         block->RemoveInstruction(equal);
665         RecordSimplification();
666       } else {
667         // Replace (bool_value == integer_not_zero_nor_one_constant) with false
668         equal->ReplaceWith(GetGraph()->GetIntConstant(0));
669         block->RemoveInstruction(equal);
670         RecordSimplification();
671       }
672     } else {
673       VisitCondition(equal);
674     }
675   } else {
676     VisitCondition(equal);
677   }
678 }
679 
VisitNotEqual(HNotEqual * not_equal)680 void InstructionSimplifierVisitor::VisitNotEqual(HNotEqual* not_equal) {
681   HInstruction* input_const = not_equal->GetConstantRight();
682   if (input_const != nullptr) {
683     HInstruction* input_value = not_equal->GetLeastConstantLeft();
684     if (CmpHasBoolType(input_value, not_equal) && input_const->IsIntConstant()) {
685       HBasicBlock* block = not_equal->GetBlock();
686       // We are comparing the boolean to a constant which is of type int and can
687       // be any constant.
688       if (input_const->AsIntConstant()->IsTrue()) {
689         // Replace (bool_value != true) with !bool_value
690         not_equal->ReplaceWith(GetGraph()->InsertOppositeCondition(input_value, not_equal));
691         block->RemoveInstruction(not_equal);
692         RecordSimplification();
693       } else if (input_const->AsIntConstant()->IsFalse()) {
694         // Replace (bool_value != false) with bool_value
695         not_equal->ReplaceWith(input_value);
696         block->RemoveInstruction(not_equal);
697         RecordSimplification();
698       } else {
699         // Replace (bool_value != integer_not_zero_nor_one_constant) with true
700         not_equal->ReplaceWith(GetGraph()->GetIntConstant(1));
701         block->RemoveInstruction(not_equal);
702         RecordSimplification();
703       }
704     } else {
705       VisitCondition(not_equal);
706     }
707   } else {
708     VisitCondition(not_equal);
709   }
710 }
711 
VisitBooleanNot(HBooleanNot * bool_not)712 void InstructionSimplifierVisitor::VisitBooleanNot(HBooleanNot* bool_not) {
713   HInstruction* input = bool_not->InputAt(0);
714   HInstruction* replace_with = nullptr;
715 
716   if (input->IsIntConstant()) {
717     // Replace !(true/false) with false/true.
718     if (input->AsIntConstant()->IsTrue()) {
719       replace_with = GetGraph()->GetIntConstant(0);
720     } else {
721       DCHECK(input->AsIntConstant()->IsFalse()) << input->AsIntConstant()->GetValue();
722       replace_with = GetGraph()->GetIntConstant(1);
723     }
724   } else if (input->IsBooleanNot()) {
725     // Replace (!(!bool_value)) with bool_value.
726     replace_with = input->InputAt(0);
727   } else if (input->IsCondition() &&
728              // Don't change FP compares. The definition of compares involving
729              // NaNs forces the compares to be done as written by the user.
730              !Primitive::IsFloatingPointType(input->InputAt(0)->GetType())) {
731     // Replace condition with its opposite.
732     replace_with = GetGraph()->InsertOppositeCondition(input->AsCondition(), bool_not);
733   }
734 
735   if (replace_with != nullptr) {
736     bool_not->ReplaceWith(replace_with);
737     bool_not->GetBlock()->RemoveInstruction(bool_not);
738     RecordSimplification();
739   }
740 }
741 
VisitSelect(HSelect * select)742 void InstructionSimplifierVisitor::VisitSelect(HSelect* select) {
743   HInstruction* replace_with = nullptr;
744   HInstruction* condition = select->GetCondition();
745   HInstruction* true_value = select->GetTrueValue();
746   HInstruction* false_value = select->GetFalseValue();
747 
748   if (condition->IsBooleanNot()) {
749     // Change ((!cond) ? x : y) to (cond ? y : x).
750     condition = condition->InputAt(0);
751     std::swap(true_value, false_value);
752     select->ReplaceInput(false_value, 0);
753     select->ReplaceInput(true_value, 1);
754     select->ReplaceInput(condition, 2);
755     RecordSimplification();
756   }
757 
758   if (true_value == false_value) {
759     // Replace (cond ? x : x) with (x).
760     replace_with = true_value;
761   } else if (condition->IsIntConstant()) {
762     if (condition->AsIntConstant()->IsTrue()) {
763       // Replace (true ? x : y) with (x).
764       replace_with = true_value;
765     } else {
766       // Replace (false ? x : y) with (y).
767       DCHECK(condition->AsIntConstant()->IsFalse()) << condition->AsIntConstant()->GetValue();
768       replace_with = false_value;
769     }
770   } else if (true_value->IsIntConstant() && false_value->IsIntConstant()) {
771     if (true_value->AsIntConstant()->IsTrue() && false_value->AsIntConstant()->IsFalse()) {
772       // Replace (cond ? true : false) with (cond).
773       replace_with = condition;
774     } else if (true_value->AsIntConstant()->IsFalse() && false_value->AsIntConstant()->IsTrue()) {
775       // Replace (cond ? false : true) with (!cond).
776       replace_with = GetGraph()->InsertOppositeCondition(condition, select);
777     }
778   }
779 
780   if (replace_with != nullptr) {
781     select->ReplaceWith(replace_with);
782     select->GetBlock()->RemoveInstruction(select);
783     RecordSimplification();
784   }
785 }
786 
VisitIf(HIf * instruction)787 void InstructionSimplifierVisitor::VisitIf(HIf* instruction) {
788   HInstruction* condition = instruction->InputAt(0);
789   if (condition->IsBooleanNot()) {
790     // Swap successors if input is negated.
791     instruction->ReplaceInput(condition->InputAt(0), 0);
792     instruction->GetBlock()->SwapSuccessors();
793     RecordSimplification();
794   }
795 }
796 
VisitArrayLength(HArrayLength * instruction)797 void InstructionSimplifierVisitor::VisitArrayLength(HArrayLength* instruction) {
798   HInstruction* input = instruction->InputAt(0);
799   // If the array is a NewArray with constant size, replace the array length
800   // with the constant instruction. This helps the bounds check elimination phase.
801   if (input->IsNewArray()) {
802     input = input->AsNewArray()->GetLength();
803     if (input->IsIntConstant()) {
804       instruction->ReplaceWith(input);
805     }
806   }
807 }
808 
VisitArraySet(HArraySet * instruction)809 void InstructionSimplifierVisitor::VisitArraySet(HArraySet* instruction) {
810   HInstruction* value = instruction->GetValue();
811   if (value->GetType() != Primitive::kPrimNot) return;
812 
813   if (CanEnsureNotNullAt(value, instruction)) {
814     instruction->ClearValueCanBeNull();
815   }
816 
817   if (value->IsArrayGet()) {
818     if (value->AsArrayGet()->GetArray() == instruction->GetArray()) {
819       // If the code is just swapping elements in the array, no need for a type check.
820       instruction->ClearNeedsTypeCheck();
821       return;
822     }
823   }
824 
825   if (value->IsNullConstant()) {
826     instruction->ClearNeedsTypeCheck();
827     return;
828   }
829 
830   ScopedObjectAccess soa(Thread::Current());
831   ReferenceTypeInfo array_rti = instruction->GetArray()->GetReferenceTypeInfo();
832   ReferenceTypeInfo value_rti = value->GetReferenceTypeInfo();
833   if (!array_rti.IsValid()) {
834     return;
835   }
836 
837   if (value_rti.IsValid() && array_rti.CanArrayHold(value_rti)) {
838     instruction->ClearNeedsTypeCheck();
839     return;
840   }
841 
842   if (array_rti.IsObjectArray()) {
843     if (array_rti.IsExact()) {
844       instruction->ClearNeedsTypeCheck();
845       return;
846     }
847     instruction->SetStaticTypeOfArrayIsObjectArray();
848   }
849 }
850 
IsTypeConversionImplicit(Primitive::Type input_type,Primitive::Type result_type)851 static bool IsTypeConversionImplicit(Primitive::Type input_type, Primitive::Type result_type) {
852   // Invariant: We should never generate a conversion to a Boolean value.
853   DCHECK_NE(Primitive::kPrimBoolean, result_type);
854 
855   // Besides conversion to the same type, widening integral conversions are implicit,
856   // excluding conversions to long and the byte->char conversion where we need to
857   // clear the high 16 bits of the 32-bit sign-extended representation of byte.
858   return result_type == input_type ||
859       (result_type == Primitive::kPrimInt && (input_type == Primitive::kPrimBoolean ||
860                                               input_type == Primitive::kPrimByte ||
861                                               input_type == Primitive::kPrimShort ||
862                                               input_type == Primitive::kPrimChar)) ||
863       (result_type == Primitive::kPrimChar && input_type == Primitive::kPrimBoolean) ||
864       (result_type == Primitive::kPrimShort && (input_type == Primitive::kPrimBoolean ||
865                                                 input_type == Primitive::kPrimByte)) ||
866       (result_type == Primitive::kPrimByte && input_type == Primitive::kPrimBoolean);
867 }
868 
IsTypeConversionLossless(Primitive::Type input_type,Primitive::Type result_type)869 static bool IsTypeConversionLossless(Primitive::Type input_type, Primitive::Type result_type) {
870   // The conversion to a larger type is loss-less with the exception of two cases,
871   //   - conversion to char, the only unsigned type, where we may lose some bits, and
872   //   - conversion from float to long, the only FP to integral conversion with smaller FP type.
873   // For integral to FP conversions this holds because the FP mantissa is large enough.
874   DCHECK_NE(input_type, result_type);
875   return Primitive::ComponentSize(result_type) > Primitive::ComponentSize(input_type) &&
876       result_type != Primitive::kPrimChar &&
877       !(result_type == Primitive::kPrimLong && input_type == Primitive::kPrimFloat);
878 }
879 
VisitTypeConversion(HTypeConversion * instruction)880 void InstructionSimplifierVisitor::VisitTypeConversion(HTypeConversion* instruction) {
881   HInstruction* input = instruction->GetInput();
882   Primitive::Type input_type = input->GetType();
883   Primitive::Type result_type = instruction->GetResultType();
884   if (IsTypeConversionImplicit(input_type, result_type)) {
885     // Remove the implicit conversion; this includes conversion to the same type.
886     instruction->ReplaceWith(input);
887     instruction->GetBlock()->RemoveInstruction(instruction);
888     RecordSimplification();
889     return;
890   }
891 
892   if (input->IsTypeConversion()) {
893     HTypeConversion* input_conversion = input->AsTypeConversion();
894     HInstruction* original_input = input_conversion->GetInput();
895     Primitive::Type original_type = original_input->GetType();
896 
897     // When the first conversion is lossless, a direct conversion from the original type
898     // to the final type yields the same result, even for a lossy second conversion, for
899     // example float->double->int or int->double->float.
900     bool is_first_conversion_lossless = IsTypeConversionLossless(original_type, input_type);
901 
902     // For integral conversions, see if the first conversion loses only bits that the second
903     // doesn't need, i.e. the final type is no wider than the intermediate. If so, direct
904     // conversion yields the same result, for example long->int->short or int->char->short.
905     bool integral_conversions_with_non_widening_second =
906         Primitive::IsIntegralType(input_type) &&
907         Primitive::IsIntegralType(original_type) &&
908         Primitive::IsIntegralType(result_type) &&
909         Primitive::ComponentSize(result_type) <= Primitive::ComponentSize(input_type);
910 
911     if (is_first_conversion_lossless || integral_conversions_with_non_widening_second) {
912       // If the merged conversion is implicit, do the simplification unconditionally.
913       if (IsTypeConversionImplicit(original_type, result_type)) {
914         instruction->ReplaceWith(original_input);
915         instruction->GetBlock()->RemoveInstruction(instruction);
916         if (!input_conversion->HasUses()) {
917           // Don't wait for DCE.
918           input_conversion->GetBlock()->RemoveInstruction(input_conversion);
919         }
920         RecordSimplification();
921         return;
922       }
923       // Otherwise simplify only if the first conversion has no other use.
924       if (input_conversion->HasOnlyOneNonEnvironmentUse()) {
925         input_conversion->ReplaceWith(original_input);
926         input_conversion->GetBlock()->RemoveInstruction(input_conversion);
927         RecordSimplification();
928         return;
929       }
930     }
931   } else if (input->IsAnd() && Primitive::IsIntegralType(result_type)) {
932     DCHECK(Primitive::IsIntegralType(input_type));
933     HAnd* input_and = input->AsAnd();
934     HConstant* constant = input_and->GetConstantRight();
935     if (constant != nullptr) {
936       int64_t value = Int64FromConstant(constant);
937       DCHECK_NE(value, -1);  // "& -1" would have been optimized away in VisitAnd().
938       size_t trailing_ones = CTZ(~static_cast<uint64_t>(value));
939       if (trailing_ones >= kBitsPerByte * Primitive::ComponentSize(result_type)) {
940         // The `HAnd` is useless, for example in `(byte) (x & 0xff)`, get rid of it.
941         HInstruction* original_input = input_and->GetLeastConstantLeft();
942         if (IsTypeConversionImplicit(original_input->GetType(), result_type)) {
943           instruction->ReplaceWith(original_input);
944           instruction->GetBlock()->RemoveInstruction(instruction);
945           RecordSimplification();
946           return;
947         } else if (input->HasOnlyOneNonEnvironmentUse()) {
948           input_and->ReplaceWith(original_input);
949           input_and->GetBlock()->RemoveInstruction(input_and);
950           RecordSimplification();
951           return;
952         }
953       }
954     }
955   }
956 }
957 
VisitAdd(HAdd * instruction)958 void InstructionSimplifierVisitor::VisitAdd(HAdd* instruction) {
959   HConstant* input_cst = instruction->GetConstantRight();
960   HInstruction* input_other = instruction->GetLeastConstantLeft();
961   bool integral_type = Primitive::IsIntegralType(instruction->GetType());
962   if ((input_cst != nullptr) && input_cst->IsArithmeticZero()) {
963     // Replace code looking like
964     //    ADD dst, src, 0
965     // with
966     //    src
967     // Note that we cannot optimize `x + 0.0` to `x` for floating-point. When
968     // `x` is `-0.0`, the former expression yields `0.0`, while the later
969     // yields `-0.0`.
970     if (integral_type) {
971       instruction->ReplaceWith(input_other);
972       instruction->GetBlock()->RemoveInstruction(instruction);
973       RecordSimplification();
974       return;
975     }
976   }
977 
978   HInstruction* left = instruction->GetLeft();
979   HInstruction* right = instruction->GetRight();
980   bool left_is_neg = left->IsNeg();
981   bool right_is_neg = right->IsNeg();
982 
983   if (left_is_neg && right_is_neg) {
984     if (TryMoveNegOnInputsAfterBinop(instruction)) {
985       return;
986     }
987   }
988 
989   HNeg* neg = left_is_neg ? left->AsNeg() : right->AsNeg();
990   if ((left_is_neg ^ right_is_neg) && neg->HasOnlyOneNonEnvironmentUse()) {
991     // Replace code looking like
992     //    NEG tmp, b
993     //    ADD dst, a, tmp
994     // with
995     //    SUB dst, a, b
996     // We do not perform the optimization if the input negation has environment
997     // uses or multiple non-environment uses as it could lead to worse code. In
998     // particular, we do not want the live range of `b` to be extended if we are
999     // not sure the initial 'NEG' instruction can be removed.
1000     HInstruction* other = left_is_neg ? right : left;
1001     HSub* sub = new(GetGraph()->GetArena()) HSub(instruction->GetType(), other, neg->GetInput());
1002     instruction->GetBlock()->ReplaceAndRemoveInstructionWith(instruction, sub);
1003     RecordSimplification();
1004     neg->GetBlock()->RemoveInstruction(neg);
1005     return;
1006   }
1007 
1008   if (TryReplaceWithRotate(instruction)) {
1009     return;
1010   }
1011 
1012   // TryHandleAssociativeAndCommutativeOperation() does not remove its input,
1013   // so no need to return.
1014   TryHandleAssociativeAndCommutativeOperation(instruction);
1015 
1016   if ((left->IsSub() || right->IsSub()) &&
1017       TrySubtractionChainSimplification(instruction)) {
1018     return;
1019   }
1020 
1021   if (integral_type) {
1022     // Replace code patterns looking like
1023     //    SUB dst1, x, y        SUB dst1, x, y
1024     //    ADD dst2, dst1, y     ADD dst2, y, dst1
1025     // with
1026     //    SUB dst1, x, y
1027     // ADD instruction is not needed in this case, we may use
1028     // one of inputs of SUB instead.
1029     if (left->IsSub() && left->InputAt(1) == right) {
1030       instruction->ReplaceWith(left->InputAt(0));
1031       RecordSimplification();
1032       instruction->GetBlock()->RemoveInstruction(instruction);
1033       return;
1034     } else if (right->IsSub() && right->InputAt(1) == left) {
1035       instruction->ReplaceWith(right->InputAt(0));
1036       RecordSimplification();
1037       instruction->GetBlock()->RemoveInstruction(instruction);
1038       return;
1039     }
1040   }
1041 }
1042 
VisitAnd(HAnd * instruction)1043 void InstructionSimplifierVisitor::VisitAnd(HAnd* instruction) {
1044   HConstant* input_cst = instruction->GetConstantRight();
1045   HInstruction* input_other = instruction->GetLeastConstantLeft();
1046 
1047   if (input_cst != nullptr) {
1048     int64_t value = Int64FromConstant(input_cst);
1049     if (value == -1) {
1050       // Replace code looking like
1051       //    AND dst, src, 0xFFF...FF
1052       // with
1053       //    src
1054       instruction->ReplaceWith(input_other);
1055       instruction->GetBlock()->RemoveInstruction(instruction);
1056       RecordSimplification();
1057       return;
1058     }
1059     // Eliminate And from UShr+And if the And-mask contains all the bits that
1060     // can be non-zero after UShr. Transform Shr+And to UShr if the And-mask
1061     // precisely clears the shifted-in sign bits.
1062     if ((input_other->IsUShr() || input_other->IsShr()) && input_other->InputAt(1)->IsConstant()) {
1063       size_t reg_bits = (instruction->GetResultType() == Primitive::kPrimLong) ? 64 : 32;
1064       size_t shift = Int64FromConstant(input_other->InputAt(1)->AsConstant()) & (reg_bits - 1);
1065       size_t num_tail_bits_set = CTZ(value + 1);
1066       if ((num_tail_bits_set >= reg_bits - shift) && input_other->IsUShr()) {
1067         // This AND clears only bits known to be clear, for example "(x >>> 24) & 0xff".
1068         instruction->ReplaceWith(input_other);
1069         instruction->GetBlock()->RemoveInstruction(instruction);
1070         RecordSimplification();
1071         return;
1072       }  else if ((num_tail_bits_set == reg_bits - shift) && IsPowerOfTwo(value + 1) &&
1073           input_other->HasOnlyOneNonEnvironmentUse()) {
1074         DCHECK(input_other->IsShr());  // For UShr, we would have taken the branch above.
1075         // Replace SHR+AND with USHR, for example "(x >> 24) & 0xff" -> "x >>> 24".
1076         HUShr* ushr = new (GetGraph()->GetArena()) HUShr(instruction->GetType(),
1077                                                          input_other->InputAt(0),
1078                                                          input_other->InputAt(1),
1079                                                          input_other->GetDexPc());
1080         instruction->GetBlock()->ReplaceAndRemoveInstructionWith(instruction, ushr);
1081         input_other->GetBlock()->RemoveInstruction(input_other);
1082         RecordSimplification();
1083         return;
1084       }
1085     }
1086   }
1087 
1088   // We assume that GVN has run before, so we only perform a pointer comparison.
1089   // If for some reason the values are equal but the pointers are different, we
1090   // are still correct and only miss an optimization opportunity.
1091   if (instruction->GetLeft() == instruction->GetRight()) {
1092     // Replace code looking like
1093     //    AND dst, src, src
1094     // with
1095     //    src
1096     instruction->ReplaceWith(instruction->GetLeft());
1097     instruction->GetBlock()->RemoveInstruction(instruction);
1098     RecordSimplification();
1099     return;
1100   }
1101 
1102   if (TryDeMorganNegationFactoring(instruction)) {
1103     return;
1104   }
1105 
1106   // TryHandleAssociativeAndCommutativeOperation() does not remove its input,
1107   // so no need to return.
1108   TryHandleAssociativeAndCommutativeOperation(instruction);
1109 }
1110 
VisitGreaterThan(HGreaterThan * condition)1111 void InstructionSimplifierVisitor::VisitGreaterThan(HGreaterThan* condition) {
1112   VisitCondition(condition);
1113 }
1114 
VisitGreaterThanOrEqual(HGreaterThanOrEqual * condition)1115 void InstructionSimplifierVisitor::VisitGreaterThanOrEqual(HGreaterThanOrEqual* condition) {
1116   VisitCondition(condition);
1117 }
1118 
VisitLessThan(HLessThan * condition)1119 void InstructionSimplifierVisitor::VisitLessThan(HLessThan* condition) {
1120   VisitCondition(condition);
1121 }
1122 
VisitLessThanOrEqual(HLessThanOrEqual * condition)1123 void InstructionSimplifierVisitor::VisitLessThanOrEqual(HLessThanOrEqual* condition) {
1124   VisitCondition(condition);
1125 }
1126 
VisitBelow(HBelow * condition)1127 void InstructionSimplifierVisitor::VisitBelow(HBelow* condition) {
1128   VisitCondition(condition);
1129 }
1130 
VisitBelowOrEqual(HBelowOrEqual * condition)1131 void InstructionSimplifierVisitor::VisitBelowOrEqual(HBelowOrEqual* condition) {
1132   VisitCondition(condition);
1133 }
1134 
VisitAbove(HAbove * condition)1135 void InstructionSimplifierVisitor::VisitAbove(HAbove* condition) {
1136   VisitCondition(condition);
1137 }
1138 
VisitAboveOrEqual(HAboveOrEqual * condition)1139 void InstructionSimplifierVisitor::VisitAboveOrEqual(HAboveOrEqual* condition) {
1140   VisitCondition(condition);
1141 }
1142 
1143 // Recognize the following pattern:
1144 // obj.getClass() ==/!= Foo.class
1145 // And replace it with a constant value if the type of `obj` is statically known.
RecognizeAndSimplifyClassCheck(HCondition * condition)1146 static bool RecognizeAndSimplifyClassCheck(HCondition* condition) {
1147   HInstruction* input_one = condition->InputAt(0);
1148   HInstruction* input_two = condition->InputAt(1);
1149   HLoadClass* load_class = input_one->IsLoadClass()
1150       ? input_one->AsLoadClass()
1151       : input_two->AsLoadClass();
1152   if (load_class == nullptr) {
1153     return false;
1154   }
1155 
1156   ReferenceTypeInfo class_rti = load_class->GetLoadedClassRTI();
1157   if (!class_rti.IsValid()) {
1158     // Unresolved class.
1159     return false;
1160   }
1161 
1162   HInstanceFieldGet* field_get = (load_class == input_one)
1163       ? input_two->AsInstanceFieldGet()
1164       : input_one->AsInstanceFieldGet();
1165   if (field_get == nullptr) {
1166     return false;
1167   }
1168 
1169   HInstruction* receiver = field_get->InputAt(0);
1170   ReferenceTypeInfo receiver_type = receiver->GetReferenceTypeInfo();
1171   if (!receiver_type.IsExact()) {
1172     return false;
1173   }
1174 
1175   {
1176     ScopedObjectAccess soa(Thread::Current());
1177     ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
1178     ArtField* field = class_linker->GetClassRoot(ClassLinker::kJavaLangObject)->GetInstanceField(0);
1179     DCHECK_EQ(std::string(field->GetName()), "shadow$_klass_");
1180     if (field_get->GetFieldInfo().GetField() != field) {
1181       return false;
1182     }
1183 
1184     // We can replace the compare.
1185     int value = 0;
1186     if (receiver_type.IsEqual(class_rti)) {
1187       value = condition->IsEqual() ? 1 : 0;
1188     } else {
1189       value = condition->IsNotEqual() ? 1 : 0;
1190     }
1191     condition->ReplaceWith(condition->GetBlock()->GetGraph()->GetIntConstant(value));
1192     return true;
1193   }
1194 }
1195 
VisitCondition(HCondition * condition)1196 void InstructionSimplifierVisitor::VisitCondition(HCondition* condition) {
1197   if (condition->IsEqual() || condition->IsNotEqual()) {
1198     if (RecognizeAndSimplifyClassCheck(condition)) {
1199       return;
1200     }
1201   }
1202 
1203   // Reverse condition if left is constant. Our code generators prefer constant
1204   // on the right hand side.
1205   if (condition->GetLeft()->IsConstant() && !condition->GetRight()->IsConstant()) {
1206     HBasicBlock* block = condition->GetBlock();
1207     HCondition* replacement = GetOppositeConditionSwapOps(block->GetGraph()->GetArena(), condition);
1208     // If it is a fp we must set the opposite bias.
1209     if (replacement != nullptr) {
1210       if (condition->IsLtBias()) {
1211         replacement->SetBias(ComparisonBias::kGtBias);
1212       } else if (condition->IsGtBias()) {
1213         replacement->SetBias(ComparisonBias::kLtBias);
1214       }
1215       block->ReplaceAndRemoveInstructionWith(condition, replacement);
1216       RecordSimplification();
1217 
1218       condition = replacement;
1219     }
1220   }
1221 
1222   HInstruction* left = condition->GetLeft();
1223   HInstruction* right = condition->GetRight();
1224 
1225   // Try to fold an HCompare into this HCondition.
1226 
1227   // We can only replace an HCondition which compares a Compare to 0.
1228   // Both 'dx' and 'jack' generate a compare to 0 when compiling a
1229   // condition with a long, float or double comparison as input.
1230   if (!left->IsCompare() || !right->IsConstant() || right->AsIntConstant()->GetValue() != 0) {
1231     // Conversion is not possible.
1232     return;
1233   }
1234 
1235   // Is the Compare only used for this purpose?
1236   if (!left->GetUses().HasExactlyOneElement()) {
1237     // Someone else also wants the result of the compare.
1238     return;
1239   }
1240 
1241   if (!left->GetEnvUses().empty()) {
1242     // There is a reference to the compare result in an environment. Do we really need it?
1243     if (GetGraph()->IsDebuggable()) {
1244       return;
1245     }
1246 
1247     // We have to ensure that there are no deopt points in the sequence.
1248     if (left->HasAnyEnvironmentUseBefore(condition)) {
1249       return;
1250     }
1251   }
1252 
1253   // Clean up any environment uses from the HCompare, if any.
1254   left->RemoveEnvironmentUsers();
1255 
1256   // We have decided to fold the HCompare into the HCondition. Transfer the information.
1257   condition->SetBias(left->AsCompare()->GetBias());
1258 
1259   // Replace the operands of the HCondition.
1260   condition->ReplaceInput(left->InputAt(0), 0);
1261   condition->ReplaceInput(left->InputAt(1), 1);
1262 
1263   // Remove the HCompare.
1264   left->GetBlock()->RemoveInstruction(left);
1265 
1266   RecordSimplification();
1267 }
1268 
1269 // Return whether x / divisor == x * (1.0f / divisor), for every float x.
CanDivideByReciprocalMultiplyFloat(int32_t divisor)1270 static constexpr bool CanDivideByReciprocalMultiplyFloat(int32_t divisor) {
1271   // True, if the most significant bits of divisor are 0.
1272   return ((divisor & 0x7fffff) == 0);
1273 }
1274 
1275 // Return whether x / divisor == x * (1.0 / divisor), for every double x.
CanDivideByReciprocalMultiplyDouble(int64_t divisor)1276 static constexpr bool CanDivideByReciprocalMultiplyDouble(int64_t divisor) {
1277   // True, if the most significant bits of divisor are 0.
1278   return ((divisor & ((UINT64_C(1) << 52) - 1)) == 0);
1279 }
1280 
VisitDiv(HDiv * instruction)1281 void InstructionSimplifierVisitor::VisitDiv(HDiv* instruction) {
1282   HConstant* input_cst = instruction->GetConstantRight();
1283   HInstruction* input_other = instruction->GetLeastConstantLeft();
1284   Primitive::Type type = instruction->GetType();
1285 
1286   if ((input_cst != nullptr) && input_cst->IsOne()) {
1287     // Replace code looking like
1288     //    DIV dst, src, 1
1289     // with
1290     //    src
1291     instruction->ReplaceWith(input_other);
1292     instruction->GetBlock()->RemoveInstruction(instruction);
1293     RecordSimplification();
1294     return;
1295   }
1296 
1297   if ((input_cst != nullptr) && input_cst->IsMinusOne()) {
1298     // Replace code looking like
1299     //    DIV dst, src, -1
1300     // with
1301     //    NEG dst, src
1302     instruction->GetBlock()->ReplaceAndRemoveInstructionWith(
1303         instruction, new (GetGraph()->GetArena()) HNeg(type, input_other));
1304     RecordSimplification();
1305     return;
1306   }
1307 
1308   if ((input_cst != nullptr) && Primitive::IsFloatingPointType(type)) {
1309     // Try replacing code looking like
1310     //    DIV dst, src, constant
1311     // with
1312     //    MUL dst, src, 1 / constant
1313     HConstant* reciprocal = nullptr;
1314     if (type == Primitive::Primitive::kPrimDouble) {
1315       double value = input_cst->AsDoubleConstant()->GetValue();
1316       if (CanDivideByReciprocalMultiplyDouble(bit_cast<int64_t, double>(value))) {
1317         reciprocal = GetGraph()->GetDoubleConstant(1.0 / value);
1318       }
1319     } else {
1320       DCHECK_EQ(type, Primitive::kPrimFloat);
1321       float value = input_cst->AsFloatConstant()->GetValue();
1322       if (CanDivideByReciprocalMultiplyFloat(bit_cast<int32_t, float>(value))) {
1323         reciprocal = GetGraph()->GetFloatConstant(1.0f / value);
1324       }
1325     }
1326 
1327     if (reciprocal != nullptr) {
1328       instruction->GetBlock()->ReplaceAndRemoveInstructionWith(
1329           instruction, new (GetGraph()->GetArena()) HMul(type, input_other, reciprocal));
1330       RecordSimplification();
1331       return;
1332     }
1333   }
1334 }
1335 
VisitMul(HMul * instruction)1336 void InstructionSimplifierVisitor::VisitMul(HMul* instruction) {
1337   HConstant* input_cst = instruction->GetConstantRight();
1338   HInstruction* input_other = instruction->GetLeastConstantLeft();
1339   Primitive::Type type = instruction->GetType();
1340   HBasicBlock* block = instruction->GetBlock();
1341   ArenaAllocator* allocator = GetGraph()->GetArena();
1342 
1343   if (input_cst == nullptr) {
1344     return;
1345   }
1346 
1347   if (input_cst->IsOne()) {
1348     // Replace code looking like
1349     //    MUL dst, src, 1
1350     // with
1351     //    src
1352     instruction->ReplaceWith(input_other);
1353     instruction->GetBlock()->RemoveInstruction(instruction);
1354     RecordSimplification();
1355     return;
1356   }
1357 
1358   if (input_cst->IsMinusOne() &&
1359       (Primitive::IsFloatingPointType(type) || Primitive::IsIntOrLongType(type))) {
1360     // Replace code looking like
1361     //    MUL dst, src, -1
1362     // with
1363     //    NEG dst, src
1364     HNeg* neg = new (allocator) HNeg(type, input_other);
1365     block->ReplaceAndRemoveInstructionWith(instruction, neg);
1366     RecordSimplification();
1367     return;
1368   }
1369 
1370   if (Primitive::IsFloatingPointType(type) &&
1371       ((input_cst->IsFloatConstant() && input_cst->AsFloatConstant()->GetValue() == 2.0f) ||
1372        (input_cst->IsDoubleConstant() && input_cst->AsDoubleConstant()->GetValue() == 2.0))) {
1373     // Replace code looking like
1374     //    FP_MUL dst, src, 2.0
1375     // with
1376     //    FP_ADD dst, src, src
1377     // The 'int' and 'long' cases are handled below.
1378     block->ReplaceAndRemoveInstructionWith(instruction,
1379                                            new (allocator) HAdd(type, input_other, input_other));
1380     RecordSimplification();
1381     return;
1382   }
1383 
1384   if (Primitive::IsIntOrLongType(type)) {
1385     int64_t factor = Int64FromConstant(input_cst);
1386     // Even though constant propagation also takes care of the zero case, other
1387     // optimizations can lead to having a zero multiplication.
1388     if (factor == 0) {
1389       // Replace code looking like
1390       //    MUL dst, src, 0
1391       // with
1392       //    0
1393       instruction->ReplaceWith(input_cst);
1394       instruction->GetBlock()->RemoveInstruction(instruction);
1395       RecordSimplification();
1396       return;
1397     } else if (IsPowerOfTwo(factor)) {
1398       // Replace code looking like
1399       //    MUL dst, src, pow_of_2
1400       // with
1401       //    SHL dst, src, log2(pow_of_2)
1402       HIntConstant* shift = GetGraph()->GetIntConstant(WhichPowerOf2(factor));
1403       HShl* shl = new (allocator) HShl(type, input_other, shift);
1404       block->ReplaceAndRemoveInstructionWith(instruction, shl);
1405       RecordSimplification();
1406       return;
1407     } else if (IsPowerOfTwo(factor - 1)) {
1408       // Transform code looking like
1409       //    MUL dst, src, (2^n + 1)
1410       // into
1411       //    SHL tmp, src, n
1412       //    ADD dst, src, tmp
1413       HShl* shl = new (allocator) HShl(type,
1414                                        input_other,
1415                                        GetGraph()->GetIntConstant(WhichPowerOf2(factor - 1)));
1416       HAdd* add = new (allocator) HAdd(type, input_other, shl);
1417 
1418       block->InsertInstructionBefore(shl, instruction);
1419       block->ReplaceAndRemoveInstructionWith(instruction, add);
1420       RecordSimplification();
1421       return;
1422     } else if (IsPowerOfTwo(factor + 1)) {
1423       // Transform code looking like
1424       //    MUL dst, src, (2^n - 1)
1425       // into
1426       //    SHL tmp, src, n
1427       //    SUB dst, tmp, src
1428       HShl* shl = new (allocator) HShl(type,
1429                                        input_other,
1430                                        GetGraph()->GetIntConstant(WhichPowerOf2(factor + 1)));
1431       HSub* sub = new (allocator) HSub(type, shl, input_other);
1432 
1433       block->InsertInstructionBefore(shl, instruction);
1434       block->ReplaceAndRemoveInstructionWith(instruction, sub);
1435       RecordSimplification();
1436       return;
1437     }
1438   }
1439 
1440   // TryHandleAssociativeAndCommutativeOperation() does not remove its input,
1441   // so no need to return.
1442   TryHandleAssociativeAndCommutativeOperation(instruction);
1443 }
1444 
VisitNeg(HNeg * instruction)1445 void InstructionSimplifierVisitor::VisitNeg(HNeg* instruction) {
1446   HInstruction* input = instruction->GetInput();
1447   if (input->IsNeg()) {
1448     // Replace code looking like
1449     //    NEG tmp, src
1450     //    NEG dst, tmp
1451     // with
1452     //    src
1453     HNeg* previous_neg = input->AsNeg();
1454     instruction->ReplaceWith(previous_neg->GetInput());
1455     instruction->GetBlock()->RemoveInstruction(instruction);
1456     // We perform the optimization even if the input negation has environment
1457     // uses since it allows removing the current instruction. But we only delete
1458     // the input negation only if it is does not have any uses left.
1459     if (!previous_neg->HasUses()) {
1460       previous_neg->GetBlock()->RemoveInstruction(previous_neg);
1461     }
1462     RecordSimplification();
1463     return;
1464   }
1465 
1466   if (input->IsSub() && input->HasOnlyOneNonEnvironmentUse() &&
1467       !Primitive::IsFloatingPointType(input->GetType())) {
1468     // Replace code looking like
1469     //    SUB tmp, a, b
1470     //    NEG dst, tmp
1471     // with
1472     //    SUB dst, b, a
1473     // We do not perform the optimization if the input subtraction has
1474     // environment uses or multiple non-environment uses as it could lead to
1475     // worse code. In particular, we do not want the live ranges of `a` and `b`
1476     // to be extended if we are not sure the initial 'SUB' instruction can be
1477     // removed.
1478     // We do not perform optimization for fp because we could lose the sign of zero.
1479     HSub* sub = input->AsSub();
1480     HSub* new_sub =
1481         new (GetGraph()->GetArena()) HSub(instruction->GetType(), sub->GetRight(), sub->GetLeft());
1482     instruction->GetBlock()->ReplaceAndRemoveInstructionWith(instruction, new_sub);
1483     if (!sub->HasUses()) {
1484       sub->GetBlock()->RemoveInstruction(sub);
1485     }
1486     RecordSimplification();
1487   }
1488 }
1489 
VisitNot(HNot * instruction)1490 void InstructionSimplifierVisitor::VisitNot(HNot* instruction) {
1491   HInstruction* input = instruction->GetInput();
1492   if (input->IsNot()) {
1493     // Replace code looking like
1494     //    NOT tmp, src
1495     //    NOT dst, tmp
1496     // with
1497     //    src
1498     // We perform the optimization even if the input negation has environment
1499     // uses since it allows removing the current instruction. But we only delete
1500     // the input negation only if it is does not have any uses left.
1501     HNot* previous_not = input->AsNot();
1502     instruction->ReplaceWith(previous_not->GetInput());
1503     instruction->GetBlock()->RemoveInstruction(instruction);
1504     if (!previous_not->HasUses()) {
1505       previous_not->GetBlock()->RemoveInstruction(previous_not);
1506     }
1507     RecordSimplification();
1508   }
1509 }
1510 
VisitOr(HOr * instruction)1511 void InstructionSimplifierVisitor::VisitOr(HOr* instruction) {
1512   HConstant* input_cst = instruction->GetConstantRight();
1513   HInstruction* input_other = instruction->GetLeastConstantLeft();
1514 
1515   if ((input_cst != nullptr) && input_cst->IsZeroBitPattern()) {
1516     // Replace code looking like
1517     //    OR dst, src, 0
1518     // with
1519     //    src
1520     instruction->ReplaceWith(input_other);
1521     instruction->GetBlock()->RemoveInstruction(instruction);
1522     RecordSimplification();
1523     return;
1524   }
1525 
1526   // We assume that GVN has run before, so we only perform a pointer comparison.
1527   // If for some reason the values are equal but the pointers are different, we
1528   // are still correct and only miss an optimization opportunity.
1529   if (instruction->GetLeft() == instruction->GetRight()) {
1530     // Replace code looking like
1531     //    OR dst, src, src
1532     // with
1533     //    src
1534     instruction->ReplaceWith(instruction->GetLeft());
1535     instruction->GetBlock()->RemoveInstruction(instruction);
1536     RecordSimplification();
1537     return;
1538   }
1539 
1540   if (TryDeMorganNegationFactoring(instruction)) return;
1541 
1542   if (TryReplaceWithRotate(instruction)) {
1543     return;
1544   }
1545 
1546   // TryHandleAssociativeAndCommutativeOperation() does not remove its input,
1547   // so no need to return.
1548   TryHandleAssociativeAndCommutativeOperation(instruction);
1549 }
1550 
VisitShl(HShl * instruction)1551 void InstructionSimplifierVisitor::VisitShl(HShl* instruction) {
1552   VisitShift(instruction);
1553 }
1554 
VisitShr(HShr * instruction)1555 void InstructionSimplifierVisitor::VisitShr(HShr* instruction) {
1556   VisitShift(instruction);
1557 }
1558 
VisitSub(HSub * instruction)1559 void InstructionSimplifierVisitor::VisitSub(HSub* instruction) {
1560   HConstant* input_cst = instruction->GetConstantRight();
1561   HInstruction* input_other = instruction->GetLeastConstantLeft();
1562 
1563   Primitive::Type type = instruction->GetType();
1564   if (Primitive::IsFloatingPointType(type)) {
1565     return;
1566   }
1567 
1568   if ((input_cst != nullptr) && input_cst->IsArithmeticZero()) {
1569     // Replace code looking like
1570     //    SUB dst, src, 0
1571     // with
1572     //    src
1573     // Note that we cannot optimize `x - 0.0` to `x` for floating-point. When
1574     // `x` is `-0.0`, the former expression yields `0.0`, while the later
1575     // yields `-0.0`.
1576     instruction->ReplaceWith(input_other);
1577     instruction->GetBlock()->RemoveInstruction(instruction);
1578     RecordSimplification();
1579     return;
1580   }
1581 
1582   HBasicBlock* block = instruction->GetBlock();
1583   ArenaAllocator* allocator = GetGraph()->GetArena();
1584 
1585   HInstruction* left = instruction->GetLeft();
1586   HInstruction* right = instruction->GetRight();
1587   if (left->IsConstant()) {
1588     if (Int64FromConstant(left->AsConstant()) == 0) {
1589       // Replace code looking like
1590       //    SUB dst, 0, src
1591       // with
1592       //    NEG dst, src
1593       // Note that we cannot optimize `0.0 - x` to `-x` for floating-point. When
1594       // `x` is `0.0`, the former expression yields `0.0`, while the later
1595       // yields `-0.0`.
1596       HNeg* neg = new (allocator) HNeg(type, right);
1597       block->ReplaceAndRemoveInstructionWith(instruction, neg);
1598       RecordSimplification();
1599       return;
1600     }
1601   }
1602 
1603   if (left->IsNeg() && right->IsNeg()) {
1604     if (TryMoveNegOnInputsAfterBinop(instruction)) {
1605       return;
1606     }
1607   }
1608 
1609   if (right->IsNeg() && right->HasOnlyOneNonEnvironmentUse()) {
1610     // Replace code looking like
1611     //    NEG tmp, b
1612     //    SUB dst, a, tmp
1613     // with
1614     //    ADD dst, a, b
1615     HAdd* add = new(GetGraph()->GetArena()) HAdd(type, left, right->AsNeg()->GetInput());
1616     instruction->GetBlock()->ReplaceAndRemoveInstructionWith(instruction, add);
1617     RecordSimplification();
1618     right->GetBlock()->RemoveInstruction(right);
1619     return;
1620   }
1621 
1622   if (left->IsNeg() && left->HasOnlyOneNonEnvironmentUse()) {
1623     // Replace code looking like
1624     //    NEG tmp, a
1625     //    SUB dst, tmp, b
1626     // with
1627     //    ADD tmp, a, b
1628     //    NEG dst, tmp
1629     // The second version is not intrinsically better, but enables more
1630     // transformations.
1631     HAdd* add = new(GetGraph()->GetArena()) HAdd(type, left->AsNeg()->GetInput(), right);
1632     instruction->GetBlock()->InsertInstructionBefore(add, instruction);
1633     HNeg* neg = new (GetGraph()->GetArena()) HNeg(instruction->GetType(), add);
1634     instruction->GetBlock()->InsertInstructionBefore(neg, instruction);
1635     instruction->ReplaceWith(neg);
1636     instruction->GetBlock()->RemoveInstruction(instruction);
1637     RecordSimplification();
1638     left->GetBlock()->RemoveInstruction(left);
1639     return;
1640   }
1641 
1642   if (TrySubtractionChainSimplification(instruction)) {
1643     return;
1644   }
1645 
1646   if (left->IsAdd()) {
1647     // Replace code patterns looking like
1648     //    ADD dst1, x, y        ADD dst1, x, y
1649     //    SUB dst2, dst1, y     SUB dst2, dst1, x
1650     // with
1651     //    ADD dst1, x, y
1652     // SUB instruction is not needed in this case, we may use
1653     // one of inputs of ADD instead.
1654     // It is applicable to integral types only.
1655     DCHECK(Primitive::IsIntegralType(type));
1656     if (left->InputAt(1) == right) {
1657       instruction->ReplaceWith(left->InputAt(0));
1658       RecordSimplification();
1659       instruction->GetBlock()->RemoveInstruction(instruction);
1660       return;
1661     } else if (left->InputAt(0) == right) {
1662       instruction->ReplaceWith(left->InputAt(1));
1663       RecordSimplification();
1664       instruction->GetBlock()->RemoveInstruction(instruction);
1665       return;
1666     }
1667   }
1668 }
1669 
VisitUShr(HUShr * instruction)1670 void InstructionSimplifierVisitor::VisitUShr(HUShr* instruction) {
1671   VisitShift(instruction);
1672 }
1673 
VisitXor(HXor * instruction)1674 void InstructionSimplifierVisitor::VisitXor(HXor* instruction) {
1675   HConstant* input_cst = instruction->GetConstantRight();
1676   HInstruction* input_other = instruction->GetLeastConstantLeft();
1677 
1678   if ((input_cst != nullptr) && input_cst->IsZeroBitPattern()) {
1679     // Replace code looking like
1680     //    XOR dst, src, 0
1681     // with
1682     //    src
1683     instruction->ReplaceWith(input_other);
1684     instruction->GetBlock()->RemoveInstruction(instruction);
1685     RecordSimplification();
1686     return;
1687   }
1688 
1689   if ((input_cst != nullptr) && input_cst->IsOne()
1690       && input_other->GetType() == Primitive::kPrimBoolean) {
1691     // Replace code looking like
1692     //    XOR dst, src, 1
1693     // with
1694     //    BOOLEAN_NOT dst, src
1695     HBooleanNot* boolean_not = new (GetGraph()->GetArena()) HBooleanNot(input_other);
1696     instruction->GetBlock()->ReplaceAndRemoveInstructionWith(instruction, boolean_not);
1697     RecordSimplification();
1698     return;
1699   }
1700 
1701   if ((input_cst != nullptr) && AreAllBitsSet(input_cst)) {
1702     // Replace code looking like
1703     //    XOR dst, src, 0xFFF...FF
1704     // with
1705     //    NOT dst, src
1706     HNot* bitwise_not = new (GetGraph()->GetArena()) HNot(instruction->GetType(), input_other);
1707     instruction->GetBlock()->ReplaceAndRemoveInstructionWith(instruction, bitwise_not);
1708     RecordSimplification();
1709     return;
1710   }
1711 
1712   HInstruction* left = instruction->GetLeft();
1713   HInstruction* right = instruction->GetRight();
1714   if (((left->IsNot() && right->IsNot()) ||
1715        (left->IsBooleanNot() && right->IsBooleanNot())) &&
1716       left->HasOnlyOneNonEnvironmentUse() &&
1717       right->HasOnlyOneNonEnvironmentUse()) {
1718     // Replace code looking like
1719     //    NOT nota, a
1720     //    NOT notb, b
1721     //    XOR dst, nota, notb
1722     // with
1723     //    XOR dst, a, b
1724     instruction->ReplaceInput(left->InputAt(0), 0);
1725     instruction->ReplaceInput(right->InputAt(0), 1);
1726     left->GetBlock()->RemoveInstruction(left);
1727     right->GetBlock()->RemoveInstruction(right);
1728     RecordSimplification();
1729     return;
1730   }
1731 
1732   if (TryReplaceWithRotate(instruction)) {
1733     return;
1734   }
1735 
1736   // TryHandleAssociativeAndCommutativeOperation() does not remove its input,
1737   // so no need to return.
1738   TryHandleAssociativeAndCommutativeOperation(instruction);
1739 }
1740 
SimplifyStringEquals(HInvoke * instruction)1741 void InstructionSimplifierVisitor::SimplifyStringEquals(HInvoke* instruction) {
1742   HInstruction* argument = instruction->InputAt(1);
1743   HInstruction* receiver = instruction->InputAt(0);
1744   if (receiver == argument) {
1745     // Because String.equals is an instance call, the receiver is
1746     // a null check if we don't know it's null. The argument however, will
1747     // be the actual object. So we cannot end up in a situation where both
1748     // are equal but could be null.
1749     DCHECK(CanEnsureNotNullAt(argument, instruction));
1750     instruction->ReplaceWith(GetGraph()->GetIntConstant(1));
1751     instruction->GetBlock()->RemoveInstruction(instruction);
1752   } else {
1753     StringEqualsOptimizations optimizations(instruction);
1754     if (CanEnsureNotNullAt(argument, instruction)) {
1755       optimizations.SetArgumentNotNull();
1756     }
1757     ScopedObjectAccess soa(Thread::Current());
1758     ReferenceTypeInfo argument_rti = argument->GetReferenceTypeInfo();
1759     if (argument_rti.IsValid() && argument_rti.IsStringClass()) {
1760       optimizations.SetArgumentIsString();
1761     }
1762   }
1763 }
1764 
SimplifyRotate(HInvoke * invoke,bool is_left,Primitive::Type type)1765 void InstructionSimplifierVisitor::SimplifyRotate(HInvoke* invoke,
1766                                                   bool is_left,
1767                                                   Primitive::Type type) {
1768   DCHECK(invoke->IsInvokeStaticOrDirect());
1769   DCHECK_EQ(invoke->GetInvokeType(), InvokeType::kStatic);
1770   HInstruction* value = invoke->InputAt(0);
1771   HInstruction* distance = invoke->InputAt(1);
1772   // Replace the invoke with an HRor.
1773   if (is_left) {
1774     // Unconditionally set the type of the negated distance to `int`,
1775     // as shift and rotate operations expect a 32-bit (or narrower)
1776     // value for their distance input.
1777     distance = new (GetGraph()->GetArena()) HNeg(Primitive::kPrimInt, distance);
1778     invoke->GetBlock()->InsertInstructionBefore(distance, invoke);
1779   }
1780   HRor* ror = new (GetGraph()->GetArena()) HRor(type, value, distance);
1781   invoke->GetBlock()->ReplaceAndRemoveInstructionWith(invoke, ror);
1782   // Remove ClinitCheck and LoadClass, if possible.
1783   HInstruction* clinit = invoke->GetInputs().back();
1784   if (clinit->IsClinitCheck() && !clinit->HasUses()) {
1785     clinit->GetBlock()->RemoveInstruction(clinit);
1786     HInstruction* ldclass = clinit->InputAt(0);
1787     if (ldclass->IsLoadClass() && !ldclass->HasUses()) {
1788       ldclass->GetBlock()->RemoveInstruction(ldclass);
1789     }
1790   }
1791 }
1792 
IsArrayLengthOf(HInstruction * potential_length,HInstruction * potential_array)1793 static bool IsArrayLengthOf(HInstruction* potential_length, HInstruction* potential_array) {
1794   if (potential_length->IsArrayLength()) {
1795     return potential_length->InputAt(0) == potential_array;
1796   }
1797 
1798   if (potential_array->IsNewArray()) {
1799     return potential_array->AsNewArray()->GetLength() == potential_length;
1800   }
1801 
1802   return false;
1803 }
1804 
SimplifySystemArrayCopy(HInvoke * instruction)1805 void InstructionSimplifierVisitor::SimplifySystemArrayCopy(HInvoke* instruction) {
1806   HInstruction* source = instruction->InputAt(0);
1807   HInstruction* destination = instruction->InputAt(2);
1808   HInstruction* count = instruction->InputAt(4);
1809   SystemArrayCopyOptimizations optimizations(instruction);
1810   if (CanEnsureNotNullAt(source, instruction)) {
1811     optimizations.SetSourceIsNotNull();
1812   }
1813   if (CanEnsureNotNullAt(destination, instruction)) {
1814     optimizations.SetDestinationIsNotNull();
1815   }
1816   if (destination == source) {
1817     optimizations.SetDestinationIsSource();
1818   }
1819 
1820   if (IsArrayLengthOf(count, source)) {
1821     optimizations.SetCountIsSourceLength();
1822   }
1823 
1824   if (IsArrayLengthOf(count, destination)) {
1825     optimizations.SetCountIsDestinationLength();
1826   }
1827 
1828   {
1829     ScopedObjectAccess soa(Thread::Current());
1830     Primitive::Type source_component_type = Primitive::kPrimVoid;
1831     Primitive::Type destination_component_type = Primitive::kPrimVoid;
1832     ReferenceTypeInfo destination_rti = destination->GetReferenceTypeInfo();
1833     if (destination_rti.IsValid()) {
1834       if (destination_rti.IsObjectArray()) {
1835         if (destination_rti.IsExact()) {
1836           optimizations.SetDoesNotNeedTypeCheck();
1837         }
1838         optimizations.SetDestinationIsTypedObjectArray();
1839       }
1840       if (destination_rti.IsPrimitiveArrayClass()) {
1841         destination_component_type =
1842             destination_rti.GetTypeHandle()->GetComponentType()->GetPrimitiveType();
1843         optimizations.SetDestinationIsPrimitiveArray();
1844       } else if (destination_rti.IsNonPrimitiveArrayClass()) {
1845         optimizations.SetDestinationIsNonPrimitiveArray();
1846       }
1847     }
1848     ReferenceTypeInfo source_rti = source->GetReferenceTypeInfo();
1849     if (source_rti.IsValid()) {
1850       if (destination_rti.IsValid() && destination_rti.CanArrayHoldValuesOf(source_rti)) {
1851         optimizations.SetDoesNotNeedTypeCheck();
1852       }
1853       if (source_rti.IsPrimitiveArrayClass()) {
1854         optimizations.SetSourceIsPrimitiveArray();
1855         source_component_type = source_rti.GetTypeHandle()->GetComponentType()->GetPrimitiveType();
1856       } else if (source_rti.IsNonPrimitiveArrayClass()) {
1857         optimizations.SetSourceIsNonPrimitiveArray();
1858       }
1859     }
1860     // For primitive arrays, use their optimized ArtMethod implementations.
1861     if ((source_component_type != Primitive::kPrimVoid) &&
1862         (source_component_type == destination_component_type)) {
1863       ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
1864       PointerSize image_size = class_linker->GetImagePointerSize();
1865       HInvokeStaticOrDirect* invoke = instruction->AsInvokeStaticOrDirect();
1866       mirror::Class* system = invoke->GetResolvedMethod()->GetDeclaringClass();
1867       ArtMethod* method = nullptr;
1868       switch (source_component_type) {
1869         case Primitive::kPrimBoolean:
1870           method = system->FindClassMethod("arraycopy", "([ZI[ZII)V", image_size);
1871           break;
1872         case Primitive::kPrimByte:
1873           method = system->FindClassMethod("arraycopy", "([BI[BII)V", image_size);
1874           break;
1875         case Primitive::kPrimChar:
1876           method = system->FindClassMethod("arraycopy", "([CI[CII)V", image_size);
1877           break;
1878         case Primitive::kPrimShort:
1879           method = system->FindClassMethod("arraycopy", "([SI[SII)V", image_size);
1880           break;
1881         case Primitive::kPrimInt:
1882           method = system->FindClassMethod("arraycopy", "([II[III)V", image_size);
1883           break;
1884         case Primitive::kPrimFloat:
1885           method = system->FindClassMethod("arraycopy", "([FI[FII)V", image_size);
1886           break;
1887         case Primitive::kPrimLong:
1888           method = system->FindClassMethod("arraycopy", "([JI[JII)V", image_size);
1889           break;
1890         case Primitive::kPrimDouble:
1891           method = system->FindClassMethod("arraycopy", "([DI[DII)V", image_size);
1892           break;
1893         default:
1894           LOG(FATAL) << "Unreachable";
1895       }
1896       DCHECK(method != nullptr);
1897       DCHECK(method->IsStatic());
1898       DCHECK(method->GetDeclaringClass() == system);
1899       invoke->SetResolvedMethod(method);
1900       // Sharpen the new invoke. Note that we do not update the dex method index of
1901       // the invoke, as we would need to look it up in the current dex file, and it
1902       // is unlikely that it exists. The most usual situation for such typed
1903       // arraycopy methods is a direct pointer to the boot image.
1904       HSharpening::SharpenInvokeStaticOrDirect(invoke, codegen_, compiler_driver_);
1905     }
1906   }
1907 }
1908 
SimplifyCompare(HInvoke * invoke,bool is_signum,Primitive::Type type)1909 void InstructionSimplifierVisitor::SimplifyCompare(HInvoke* invoke,
1910                                                    bool is_signum,
1911                                                    Primitive::Type type) {
1912   DCHECK(invoke->IsInvokeStaticOrDirect());
1913   uint32_t dex_pc = invoke->GetDexPc();
1914   HInstruction* left = invoke->InputAt(0);
1915   HInstruction* right;
1916   if (!is_signum) {
1917     right = invoke->InputAt(1);
1918   } else if (type == Primitive::kPrimLong) {
1919     right = GetGraph()->GetLongConstant(0);
1920   } else {
1921     right = GetGraph()->GetIntConstant(0);
1922   }
1923   HCompare* compare = new (GetGraph()->GetArena())
1924       HCompare(type, left, right, ComparisonBias::kNoBias, dex_pc);
1925   invoke->GetBlock()->ReplaceAndRemoveInstructionWith(invoke, compare);
1926 }
1927 
SimplifyIsNaN(HInvoke * invoke)1928 void InstructionSimplifierVisitor::SimplifyIsNaN(HInvoke* invoke) {
1929   DCHECK(invoke->IsInvokeStaticOrDirect());
1930   uint32_t dex_pc = invoke->GetDexPc();
1931   // IsNaN(x) is the same as x != x.
1932   HInstruction* x = invoke->InputAt(0);
1933   HCondition* condition = new (GetGraph()->GetArena()) HNotEqual(x, x, dex_pc);
1934   condition->SetBias(ComparisonBias::kLtBias);
1935   invoke->GetBlock()->ReplaceAndRemoveInstructionWith(invoke, condition);
1936 }
1937 
SimplifyFP2Int(HInvoke * invoke)1938 void InstructionSimplifierVisitor::SimplifyFP2Int(HInvoke* invoke) {
1939   DCHECK(invoke->IsInvokeStaticOrDirect());
1940   uint32_t dex_pc = invoke->GetDexPc();
1941   HInstruction* x = invoke->InputAt(0);
1942   Primitive::Type type = x->GetType();
1943   // Set proper bit pattern for NaN and replace intrinsic with raw version.
1944   HInstruction* nan;
1945   if (type == Primitive::kPrimDouble) {
1946     nan = GetGraph()->GetLongConstant(0x7ff8000000000000L);
1947     invoke->SetIntrinsic(Intrinsics::kDoubleDoubleToRawLongBits,
1948                          kNeedsEnvironmentOrCache,
1949                          kNoSideEffects,
1950                          kNoThrow);
1951   } else {
1952     DCHECK_EQ(type, Primitive::kPrimFloat);
1953     nan = GetGraph()->GetIntConstant(0x7fc00000);
1954     invoke->SetIntrinsic(Intrinsics::kFloatFloatToRawIntBits,
1955                          kNeedsEnvironmentOrCache,
1956                          kNoSideEffects,
1957                          kNoThrow);
1958   }
1959   // Test IsNaN(x), which is the same as x != x.
1960   HCondition* condition = new (GetGraph()->GetArena()) HNotEqual(x, x, dex_pc);
1961   condition->SetBias(ComparisonBias::kLtBias);
1962   invoke->GetBlock()->InsertInstructionBefore(condition, invoke->GetNext());
1963   // Select between the two.
1964   HInstruction* select = new (GetGraph()->GetArena()) HSelect(condition, nan, invoke, dex_pc);
1965   invoke->GetBlock()->InsertInstructionBefore(select, condition->GetNext());
1966   invoke->ReplaceWithExceptInReplacementAtIndex(select, 0);  // false at index 0
1967 }
1968 
SimplifyStringCharAt(HInvoke * invoke)1969 void InstructionSimplifierVisitor::SimplifyStringCharAt(HInvoke* invoke) {
1970   HInstruction* str = invoke->InputAt(0);
1971   HInstruction* index = invoke->InputAt(1);
1972   uint32_t dex_pc = invoke->GetDexPc();
1973   ArenaAllocator* arena = GetGraph()->GetArena();
1974   // We treat String as an array to allow DCE and BCE to seamlessly work on strings,
1975   // so create the HArrayLength, HBoundsCheck and HArrayGet.
1976   HArrayLength* length = new (arena) HArrayLength(str, dex_pc, /* is_string_length */ true);
1977   invoke->GetBlock()->InsertInstructionBefore(length, invoke);
1978   HBoundsCheck* bounds_check = new (arena) HBoundsCheck(
1979       index, length, dex_pc, invoke->GetDexMethodIndex());
1980   invoke->GetBlock()->InsertInstructionBefore(bounds_check, invoke);
1981   HArrayGet* array_get = new (arena) HArrayGet(
1982       str, bounds_check, Primitive::kPrimChar, dex_pc, /* is_string_char_at */ true);
1983   invoke->GetBlock()->ReplaceAndRemoveInstructionWith(invoke, array_get);
1984   bounds_check->CopyEnvironmentFrom(invoke->GetEnvironment());
1985   GetGraph()->SetHasBoundsChecks(true);
1986 }
1987 
SimplifyStringIsEmptyOrLength(HInvoke * invoke)1988 void InstructionSimplifierVisitor::SimplifyStringIsEmptyOrLength(HInvoke* invoke) {
1989   HInstruction* str = invoke->InputAt(0);
1990   uint32_t dex_pc = invoke->GetDexPc();
1991   // We treat String as an array to allow DCE and BCE to seamlessly work on strings,
1992   // so create the HArrayLength.
1993   HArrayLength* length =
1994       new (GetGraph()->GetArena()) HArrayLength(str, dex_pc, /* is_string_length */ true);
1995   HInstruction* replacement;
1996   if (invoke->GetIntrinsic() == Intrinsics::kStringIsEmpty) {
1997     // For String.isEmpty(), create the `HEqual` representing the `length == 0`.
1998     invoke->GetBlock()->InsertInstructionBefore(length, invoke);
1999     HIntConstant* zero = GetGraph()->GetIntConstant(0);
2000     HEqual* equal = new (GetGraph()->GetArena()) HEqual(length, zero, dex_pc);
2001     replacement = equal;
2002   } else {
2003     DCHECK_EQ(invoke->GetIntrinsic(), Intrinsics::kStringLength);
2004     replacement = length;
2005   }
2006   invoke->GetBlock()->ReplaceAndRemoveInstructionWith(invoke, replacement);
2007 }
2008 
2009 // This method should only be used on intrinsics whose sole way of throwing an
2010 // exception is raising a NPE when the nth argument is null. If that argument
2011 // is provably non-null, we can clear the flag.
SimplifyNPEOnArgN(HInvoke * invoke,size_t n)2012 void InstructionSimplifierVisitor::SimplifyNPEOnArgN(HInvoke* invoke, size_t n) {
2013   HInstruction* arg = invoke->InputAt(n);
2014   if (invoke->CanThrow() && !arg->CanBeNull()) {
2015     invoke->SetCanThrow(false);
2016   }
2017 }
2018 
2019 // Methods that return "this" can replace the returned value with the receiver.
SimplifyReturnThis(HInvoke * invoke)2020 void InstructionSimplifierVisitor::SimplifyReturnThis(HInvoke* invoke) {
2021   if (invoke->HasUses()) {
2022     HInstruction* receiver = invoke->InputAt(0);
2023     invoke->ReplaceWith(receiver);
2024     RecordSimplification();
2025   }
2026 }
2027 
2028 // Helper method for StringBuffer escape analysis.
NoEscapeForStringBufferReference(HInstruction * reference,HInstruction * user)2029 static bool NoEscapeForStringBufferReference(HInstruction* reference, HInstruction* user) {
2030   if (user->IsInvokeStaticOrDirect()) {
2031     // Any constructor on StringBuffer is okay.
2032     return user->AsInvokeStaticOrDirect()->GetResolvedMethod() != nullptr &&
2033            user->AsInvokeStaticOrDirect()->GetResolvedMethod()->IsConstructor() &&
2034            user->InputAt(0) == reference;
2035   } else if (user->IsInvokeVirtual()) {
2036     switch (user->AsInvokeVirtual()->GetIntrinsic()) {
2037       case Intrinsics::kStringBufferLength:
2038       case Intrinsics::kStringBufferToString:
2039         DCHECK_EQ(user->InputAt(0), reference);
2040         return true;
2041       case Intrinsics::kStringBufferAppend:
2042         // Returns "this", so only okay if no further uses.
2043         DCHECK_EQ(user->InputAt(0), reference);
2044         DCHECK_NE(user->InputAt(1), reference);
2045         return !user->HasUses();
2046       default:
2047         break;
2048     }
2049   }
2050   return false;
2051 }
2052 
2053 // Certain allocation intrinsics are not removed by dead code elimination
2054 // because of potentially throwing an OOM exception or other side effects.
2055 // This method removes such intrinsics when special circumstances allow.
SimplifyAllocationIntrinsic(HInvoke * invoke)2056 void InstructionSimplifierVisitor::SimplifyAllocationIntrinsic(HInvoke* invoke) {
2057   if (!invoke->HasUses()) {
2058     // Instruction has no uses. If unsynchronized, we can remove right away, safely ignoring
2059     // the potential OOM of course. Otherwise, we must ensure the receiver object of this
2060     // call does not escape since only thread-local synchronization may be removed.
2061     bool is_synchronized = invoke->GetIntrinsic() == Intrinsics::kStringBufferToString;
2062     HInstruction* receiver = invoke->InputAt(0);
2063     if (!is_synchronized || DoesNotEscape(receiver, NoEscapeForStringBufferReference)) {
2064       invoke->GetBlock()->RemoveInstruction(invoke);
2065       RecordSimplification();
2066     }
2067   }
2068 }
2069 
SimplifyMemBarrier(HInvoke * invoke,MemBarrierKind barrier_kind)2070 void InstructionSimplifierVisitor::SimplifyMemBarrier(HInvoke* invoke, MemBarrierKind barrier_kind) {
2071   uint32_t dex_pc = invoke->GetDexPc();
2072   HMemoryBarrier* mem_barrier = new (GetGraph()->GetArena()) HMemoryBarrier(barrier_kind, dex_pc);
2073   invoke->GetBlock()->ReplaceAndRemoveInstructionWith(invoke, mem_barrier);
2074 }
2075 
VisitInvoke(HInvoke * instruction)2076 void InstructionSimplifierVisitor::VisitInvoke(HInvoke* instruction) {
2077   switch (instruction->GetIntrinsic()) {
2078     case Intrinsics::kStringEquals:
2079       SimplifyStringEquals(instruction);
2080       break;
2081     case Intrinsics::kSystemArrayCopy:
2082       SimplifySystemArrayCopy(instruction);
2083       break;
2084     case Intrinsics::kIntegerRotateRight:
2085       SimplifyRotate(instruction, /* is_left */ false, Primitive::kPrimInt);
2086       break;
2087     case Intrinsics::kLongRotateRight:
2088       SimplifyRotate(instruction, /* is_left */ false, Primitive::kPrimLong);
2089       break;
2090     case Intrinsics::kIntegerRotateLeft:
2091       SimplifyRotate(instruction, /* is_left */ true, Primitive::kPrimInt);
2092       break;
2093     case Intrinsics::kLongRotateLeft:
2094       SimplifyRotate(instruction, /* is_left */ true, Primitive::kPrimLong);
2095       break;
2096     case Intrinsics::kIntegerCompare:
2097       SimplifyCompare(instruction, /* is_signum */ false, Primitive::kPrimInt);
2098       break;
2099     case Intrinsics::kLongCompare:
2100       SimplifyCompare(instruction, /* is_signum */ false, Primitive::kPrimLong);
2101       break;
2102     case Intrinsics::kIntegerSignum:
2103       SimplifyCompare(instruction, /* is_signum */ true, Primitive::kPrimInt);
2104       break;
2105     case Intrinsics::kLongSignum:
2106       SimplifyCompare(instruction, /* is_signum */ true, Primitive::kPrimLong);
2107       break;
2108     case Intrinsics::kFloatIsNaN:
2109     case Intrinsics::kDoubleIsNaN:
2110       SimplifyIsNaN(instruction);
2111       break;
2112     case Intrinsics::kFloatFloatToIntBits:
2113     case Intrinsics::kDoubleDoubleToLongBits:
2114       SimplifyFP2Int(instruction);
2115       break;
2116     case Intrinsics::kStringCharAt:
2117       SimplifyStringCharAt(instruction);
2118       break;
2119     case Intrinsics::kStringIsEmpty:
2120     case Intrinsics::kStringLength:
2121       SimplifyStringIsEmptyOrLength(instruction);
2122       break;
2123     case Intrinsics::kStringStringIndexOf:
2124     case Intrinsics::kStringStringIndexOfAfter:
2125       SimplifyNPEOnArgN(instruction, 1);  // 0th has own NullCheck
2126       break;
2127     case Intrinsics::kStringBufferAppend:
2128     case Intrinsics::kStringBuilderAppend:
2129       SimplifyReturnThis(instruction);
2130       break;
2131     case Intrinsics::kStringBufferToString:
2132     case Intrinsics::kStringBuilderToString:
2133       SimplifyAllocationIntrinsic(instruction);
2134       break;
2135     case Intrinsics::kUnsafeLoadFence:
2136       SimplifyMemBarrier(instruction, MemBarrierKind::kLoadAny);
2137       break;
2138     case Intrinsics::kUnsafeStoreFence:
2139       SimplifyMemBarrier(instruction, MemBarrierKind::kAnyStore);
2140       break;
2141     case Intrinsics::kUnsafeFullFence:
2142       SimplifyMemBarrier(instruction, MemBarrierKind::kAnyAny);
2143       break;
2144     default:
2145       break;
2146   }
2147 }
2148 
VisitDeoptimize(HDeoptimize * deoptimize)2149 void InstructionSimplifierVisitor::VisitDeoptimize(HDeoptimize* deoptimize) {
2150   HInstruction* cond = deoptimize->InputAt(0);
2151   if (cond->IsConstant()) {
2152     if (cond->AsIntConstant()->IsFalse()) {
2153       // Never deopt: instruction can be removed.
2154       if (deoptimize->GuardsAnInput()) {
2155         deoptimize->ReplaceWith(deoptimize->GuardedInput());
2156       }
2157       deoptimize->GetBlock()->RemoveInstruction(deoptimize);
2158     } else {
2159       // Always deopt.
2160     }
2161   }
2162 }
2163 
2164 // Replace code looking like
2165 //    OP y, x, const1
2166 //    OP z, y, const2
2167 // with
2168 //    OP z, x, const3
2169 // where OP is both an associative and a commutative operation.
TryHandleAssociativeAndCommutativeOperation(HBinaryOperation * instruction)2170 bool InstructionSimplifierVisitor::TryHandleAssociativeAndCommutativeOperation(
2171     HBinaryOperation* instruction) {
2172   DCHECK(instruction->IsCommutative());
2173 
2174   if (!Primitive::IsIntegralType(instruction->GetType())) {
2175     return false;
2176   }
2177 
2178   HInstruction* left = instruction->GetLeft();
2179   HInstruction* right = instruction->GetRight();
2180   // Variable names as described above.
2181   HConstant* const2;
2182   HBinaryOperation* y;
2183 
2184   if (instruction->InstructionTypeEquals(left) && right->IsConstant()) {
2185     const2 = right->AsConstant();
2186     y = left->AsBinaryOperation();
2187   } else if (left->IsConstant() && instruction->InstructionTypeEquals(right)) {
2188     const2 = left->AsConstant();
2189     y = right->AsBinaryOperation();
2190   } else {
2191     // The node does not match the pattern.
2192     return false;
2193   }
2194 
2195   // If `y` has more than one use, we do not perform the optimization
2196   // because it might increase code size (e.g. if the new constant is
2197   // no longer encodable as an immediate operand in the target ISA).
2198   if (!y->HasOnlyOneNonEnvironmentUse()) {
2199     return false;
2200   }
2201 
2202   // GetConstantRight() can return both left and right constants
2203   // for commutative operations.
2204   HConstant* const1 = y->GetConstantRight();
2205   if (const1 == nullptr) {
2206     return false;
2207   }
2208 
2209   instruction->ReplaceInput(const1, 0);
2210   instruction->ReplaceInput(const2, 1);
2211   HConstant* const3 = instruction->TryStaticEvaluation();
2212   DCHECK(const3 != nullptr);
2213   instruction->ReplaceInput(y->GetLeastConstantLeft(), 0);
2214   instruction->ReplaceInput(const3, 1);
2215   RecordSimplification();
2216   return true;
2217 }
2218 
AsAddOrSub(HInstruction * binop)2219 static HBinaryOperation* AsAddOrSub(HInstruction* binop) {
2220   return (binop->IsAdd() || binop->IsSub()) ? binop->AsBinaryOperation() : nullptr;
2221 }
2222 
2223 // Helper function that performs addition statically, considering the result type.
ComputeAddition(Primitive::Type type,int64_t x,int64_t y)2224 static int64_t ComputeAddition(Primitive::Type type, int64_t x, int64_t y) {
2225   // Use the Compute() method for consistency with TryStaticEvaluation().
2226   if (type == Primitive::kPrimInt) {
2227     return HAdd::Compute<int32_t>(x, y);
2228   } else {
2229     DCHECK_EQ(type, Primitive::kPrimLong);
2230     return HAdd::Compute<int64_t>(x, y);
2231   }
2232 }
2233 
2234 // Helper function that handles the child classes of HConstant
2235 // and returns an integer with the appropriate sign.
GetValue(HConstant * constant,bool is_negated)2236 static int64_t GetValue(HConstant* constant, bool is_negated) {
2237   int64_t ret = Int64FromConstant(constant);
2238   return is_negated ? -ret : ret;
2239 }
2240 
2241 // Replace code looking like
2242 //    OP1 y, x, const1
2243 //    OP2 z, y, const2
2244 // with
2245 //    OP3 z, x, const3
2246 // where OPx is either ADD or SUB, and at least one of OP{1,2} is SUB.
TrySubtractionChainSimplification(HBinaryOperation * instruction)2247 bool InstructionSimplifierVisitor::TrySubtractionChainSimplification(
2248     HBinaryOperation* instruction) {
2249   DCHECK(instruction->IsAdd() || instruction->IsSub()) << instruction->DebugName();
2250 
2251   Primitive::Type type = instruction->GetType();
2252   if (!Primitive::IsIntegralType(type)) {
2253     return false;
2254   }
2255 
2256   HInstruction* left = instruction->GetLeft();
2257   HInstruction* right = instruction->GetRight();
2258   // Variable names as described above.
2259   HConstant* const2 = right->IsConstant() ? right->AsConstant() : left->AsConstant();
2260   if (const2 == nullptr) {
2261     return false;
2262   }
2263 
2264   HBinaryOperation* y = (AsAddOrSub(left) != nullptr)
2265       ? left->AsBinaryOperation()
2266       : AsAddOrSub(right);
2267   // If y has more than one use, we do not perform the optimization because
2268   // it might increase code size (e.g. if the new constant is no longer
2269   // encodable as an immediate operand in the target ISA).
2270   if ((y == nullptr) || !y->HasOnlyOneNonEnvironmentUse()) {
2271     return false;
2272   }
2273 
2274   left = y->GetLeft();
2275   HConstant* const1 = left->IsConstant() ? left->AsConstant() : y->GetRight()->AsConstant();
2276   if (const1 == nullptr) {
2277     return false;
2278   }
2279 
2280   HInstruction* x = (const1 == left) ? y->GetRight() : left;
2281   // If both inputs are constants, let the constant folding pass deal with it.
2282   if (x->IsConstant()) {
2283     return false;
2284   }
2285 
2286   bool is_const2_negated = (const2 == right) && instruction->IsSub();
2287   int64_t const2_val = GetValue(const2, is_const2_negated);
2288   bool is_y_negated = (y == right) && instruction->IsSub();
2289   right = y->GetRight();
2290   bool is_const1_negated = is_y_negated ^ ((const1 == right) && y->IsSub());
2291   int64_t const1_val = GetValue(const1, is_const1_negated);
2292   bool is_x_negated = is_y_negated ^ ((x == right) && y->IsSub());
2293   int64_t const3_val = ComputeAddition(type, const1_val, const2_val);
2294   HBasicBlock* block = instruction->GetBlock();
2295   HConstant* const3 = block->GetGraph()->GetConstant(type, const3_val);
2296   ArenaAllocator* arena = instruction->GetArena();
2297   HInstruction* z;
2298 
2299   if (is_x_negated) {
2300     z = new (arena) HSub(type, const3, x, instruction->GetDexPc());
2301   } else {
2302     z = new (arena) HAdd(type, x, const3, instruction->GetDexPc());
2303   }
2304 
2305   block->ReplaceAndRemoveInstructionWith(instruction, z);
2306   RecordSimplification();
2307   return true;
2308 }
2309 
2310 }  // namespace art
2311