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 "class_root.h"
22 #include "data_type-inl.h"
23 #include "escape.h"
24 #include "intrinsics.h"
25 #include "mirror/class-inl.h"
26 #include "scoped_thread_state_change-inl.h"
27 #include "sharpening.h"
28 #include "string_builder_append.h"
29 
30 namespace art {
31 
32 // Whether to run an exhaustive test of individual HInstructions cloning when each instruction
33 // is replaced with its copy if it is clonable.
34 static constexpr bool kTestInstructionClonerExhaustively = false;
35 
36 class InstructionSimplifierVisitor : public HGraphDelegateVisitor {
37  public:
InstructionSimplifierVisitor(HGraph * graph,CodeGenerator * codegen,OptimizingCompilerStats * stats)38   InstructionSimplifierVisitor(HGraph* graph,
39                                CodeGenerator* codegen,
40                                OptimizingCompilerStats* stats)
41       : HGraphDelegateVisitor(graph),
42         codegen_(codegen),
43         stats_(stats) {}
44 
45   bool Run();
46 
47  private:
RecordSimplification()48   void RecordSimplification() {
49     simplification_occurred_ = true;
50     simplifications_at_current_position_++;
51     MaybeRecordStat(stats_, MethodCompilationStat::kInstructionSimplifications);
52   }
53 
54   bool ReplaceRotateWithRor(HBinaryOperation* op, HUShr* ushr, HShl* shl);
55   bool TryReplaceWithRotate(HBinaryOperation* instruction);
56   bool TryReplaceWithRotateConstantPattern(HBinaryOperation* op, HUShr* ushr, HShl* shl);
57   bool TryReplaceWithRotateRegisterNegPattern(HBinaryOperation* op, HUShr* ushr, HShl* shl);
58   bool TryReplaceWithRotateRegisterSubPattern(HBinaryOperation* op, HUShr* ushr, HShl* shl);
59 
60   bool TryMoveNegOnInputsAfterBinop(HBinaryOperation* binop);
61   // `op` should be either HOr or HAnd.
62   // De Morgan's laws:
63   // ~a & ~b = ~(a | b)  and  ~a | ~b = ~(a & b)
64   bool TryDeMorganNegationFactoring(HBinaryOperation* op);
65   bool TryHandleAssociativeAndCommutativeOperation(HBinaryOperation* instruction);
66   bool TrySubtractionChainSimplification(HBinaryOperation* instruction);
67   bool TryCombineVecMultiplyAccumulate(HVecMul* mul);
68 
69   void VisitShift(HBinaryOperation* shift);
70   void VisitEqual(HEqual* equal) override;
71   void VisitNotEqual(HNotEqual* equal) override;
72   void VisitBooleanNot(HBooleanNot* bool_not) override;
73   void VisitInstanceFieldSet(HInstanceFieldSet* equal) override;
74   void VisitStaticFieldSet(HStaticFieldSet* equal) override;
75   void VisitArraySet(HArraySet* equal) override;
76   void VisitTypeConversion(HTypeConversion* instruction) override;
77   void VisitNullCheck(HNullCheck* instruction) override;
78   void VisitArrayLength(HArrayLength* instruction) override;
79   void VisitCheckCast(HCheckCast* instruction) override;
80   void VisitAbs(HAbs* 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   void VisitVecMul(HVecMul* instruction) override;
108 
109   bool CanEnsureNotNullAt(HInstruction* instr, HInstruction* at) const;
110 
111   void SimplifyRotate(HInvoke* invoke, bool is_left, DataType::Type type);
112   void SimplifySystemArrayCopy(HInvoke* invoke);
113   void SimplifyStringEquals(HInvoke* invoke);
114   void SimplifyCompare(HInvoke* invoke, bool is_signum, DataType::Type type);
115   void SimplifyIsNaN(HInvoke* invoke);
116   void SimplifyFP2Int(HInvoke* invoke);
117   void SimplifyStringCharAt(HInvoke* invoke);
118   void SimplifyStringIsEmptyOrLength(HInvoke* invoke);
119   void SimplifyStringIndexOf(HInvoke* invoke);
120   void SimplifyNPEOnArgN(HInvoke* invoke, size_t);
121   void SimplifyReturnThis(HInvoke* invoke);
122   void SimplifyAllocationIntrinsic(HInvoke* invoke);
123   void SimplifyMemBarrier(HInvoke* invoke, MemBarrierKind barrier_kind);
124   void SimplifyMin(HInvoke* invoke, DataType::Type type);
125   void SimplifyMax(HInvoke* invoke, DataType::Type type);
126   void SimplifyAbs(HInvoke* invoke, DataType::Type type);
127 
128   CodeGenerator* codegen_;
129   OptimizingCompilerStats* stats_;
130   bool simplification_occurred_ = false;
131   int simplifications_at_current_position_ = 0;
132   // We ensure we do not loop infinitely. The value should not be too high, since that
133   // would allow looping around the same basic block too many times. The value should
134   // not be too low either, however, since we want to allow revisiting a basic block
135   // with many statements and simplifications at least once.
136   static constexpr int kMaxSamePositionSimplifications = 50;
137 };
138 
Run()139 bool InstructionSimplifier::Run() {
140   if (kTestInstructionClonerExhaustively) {
141     CloneAndReplaceInstructionVisitor visitor(graph_);
142     visitor.VisitReversePostOrder();
143   }
144 
145   InstructionSimplifierVisitor visitor(graph_, codegen_, stats_);
146   return visitor.Run();
147 }
148 
Run()149 bool InstructionSimplifierVisitor::Run() {
150   bool didSimplify = false;
151   // Iterate in reverse post order to open up more simplifications to users
152   // of instructions that got simplified.
153   for (HBasicBlock* block : GetGraph()->GetReversePostOrder()) {
154     // The simplification of an instruction to another instruction may yield
155     // possibilities for other simplifications. So although we perform a reverse
156     // post order visit, we sometimes need to revisit an instruction index.
157     do {
158       simplification_occurred_ = false;
159       VisitBasicBlock(block);
160       if (simplification_occurred_) {
161         didSimplify = true;
162       }
163     } while (simplification_occurred_ &&
164              (simplifications_at_current_position_ < kMaxSamePositionSimplifications));
165     simplifications_at_current_position_ = 0;
166   }
167   return didSimplify;
168 }
169 
170 namespace {
171 
AreAllBitsSet(HConstant * constant)172 bool AreAllBitsSet(HConstant* constant) {
173   return Int64FromConstant(constant) == -1;
174 }
175 
176 }  // namespace
177 
178 // Returns true if the code was simplified to use only one negation operation
179 // after the binary operation instead of one on each of the inputs.
TryMoveNegOnInputsAfterBinop(HBinaryOperation * binop)180 bool InstructionSimplifierVisitor::TryMoveNegOnInputsAfterBinop(HBinaryOperation* binop) {
181   DCHECK(binop->IsAdd() || binop->IsSub());
182   DCHECK(binop->GetLeft()->IsNeg() && binop->GetRight()->IsNeg());
183   HNeg* left_neg = binop->GetLeft()->AsNeg();
184   HNeg* right_neg = binop->GetRight()->AsNeg();
185   if (!left_neg->HasOnlyOneNonEnvironmentUse() ||
186       !right_neg->HasOnlyOneNonEnvironmentUse()) {
187     return false;
188   }
189   // Replace code looking like
190   //    NEG tmp1, a
191   //    NEG tmp2, b
192   //    ADD dst, tmp1, tmp2
193   // with
194   //    ADD tmp, a, b
195   //    NEG dst, tmp
196   // Note that we cannot optimize `(-a) + (-b)` to `-(a + b)` for floating-point.
197   // When `a` is `-0.0` and `b` is `0.0`, the former expression yields `0.0`,
198   // while the later yields `-0.0`.
199   if (!DataType::IsIntegralType(binop->GetType())) {
200     return false;
201   }
202   binop->ReplaceInput(left_neg->GetInput(), 0);
203   binop->ReplaceInput(right_neg->GetInput(), 1);
204   left_neg->GetBlock()->RemoveInstruction(left_neg);
205   right_neg->GetBlock()->RemoveInstruction(right_neg);
206   HNeg* neg = new (GetGraph()->GetAllocator()) HNeg(binop->GetType(), binop);
207   binop->GetBlock()->InsertInstructionBefore(neg, binop->GetNext());
208   binop->ReplaceWithExceptInReplacementAtIndex(neg, 0);
209   RecordSimplification();
210   return true;
211 }
212 
TryDeMorganNegationFactoring(HBinaryOperation * op)213 bool InstructionSimplifierVisitor::TryDeMorganNegationFactoring(HBinaryOperation* op) {
214   DCHECK(op->IsAnd() || op->IsOr()) << op->DebugName();
215   DataType::Type type = op->GetType();
216   HInstruction* left = op->GetLeft();
217   HInstruction* right = op->GetRight();
218 
219   // We can apply De Morgan's laws if both inputs are Not's and are only used
220   // by `op`.
221   if (((left->IsNot() && right->IsNot()) ||
222        (left->IsBooleanNot() && right->IsBooleanNot())) &&
223       left->HasOnlyOneNonEnvironmentUse() &&
224       right->HasOnlyOneNonEnvironmentUse()) {
225     // Replace code looking like
226     //    NOT nota, a
227     //    NOT notb, b
228     //    AND dst, nota, notb (respectively OR)
229     // with
230     //    OR or, a, b         (respectively AND)
231     //    NOT dest, or
232     HInstruction* src_left = left->InputAt(0);
233     HInstruction* src_right = right->InputAt(0);
234     uint32_t dex_pc = op->GetDexPc();
235 
236     // Remove the negations on the inputs.
237     left->ReplaceWith(src_left);
238     right->ReplaceWith(src_right);
239     left->GetBlock()->RemoveInstruction(left);
240     right->GetBlock()->RemoveInstruction(right);
241 
242     // Replace the `HAnd` or `HOr`.
243     HBinaryOperation* hbin;
244     if (op->IsAnd()) {
245       hbin = new (GetGraph()->GetAllocator()) HOr(type, src_left, src_right, dex_pc);
246     } else {
247       hbin = new (GetGraph()->GetAllocator()) HAnd(type, src_left, src_right, dex_pc);
248     }
249     HInstruction* hnot;
250     if (left->IsBooleanNot()) {
251       hnot = new (GetGraph()->GetAllocator()) HBooleanNot(hbin, dex_pc);
252     } else {
253       hnot = new (GetGraph()->GetAllocator()) HNot(type, hbin, dex_pc);
254     }
255 
256     op->GetBlock()->InsertInstructionBefore(hbin, op);
257     op->GetBlock()->ReplaceAndRemoveInstructionWith(op, hnot);
258 
259     RecordSimplification();
260     return true;
261   }
262 
263   return false;
264 }
265 
TryCombineVecMultiplyAccumulate(HVecMul * mul)266 bool InstructionSimplifierVisitor::TryCombineVecMultiplyAccumulate(HVecMul* mul) {
267   DataType::Type type = mul->GetPackedType();
268   InstructionSet isa = codegen_->GetInstructionSet();
269   switch (isa) {
270     case InstructionSet::kArm64:
271       if (!(type == DataType::Type::kUint8 ||
272             type == DataType::Type::kInt8 ||
273             type == DataType::Type::kUint16 ||
274             type == DataType::Type::kInt16 ||
275             type == DataType::Type::kInt32)) {
276         return false;
277       }
278       break;
279     default:
280       return false;
281   }
282 
283   ArenaAllocator* allocator = mul->GetBlock()->GetGraph()->GetAllocator();
284 
285   if (mul->HasOnlyOneNonEnvironmentUse()) {
286     HInstruction* use = mul->GetUses().front().GetUser();
287     if (use->IsVecAdd() || use->IsVecSub()) {
288       // Replace code looking like
289       //    VECMUL tmp, x, y
290       //    VECADD/SUB dst, acc, tmp
291       // with
292       //    VECMULACC dst, acc, x, y
293       // Note that we do not want to (unconditionally) perform the merge when the
294       // multiplication has multiple uses and it can be merged in all of them.
295       // Multiple uses could happen on the same control-flow path, and we would
296       // then increase the amount of work. In the future we could try to evaluate
297       // whether all uses are on different control-flow paths (using dominance and
298       // reverse-dominance information) and only perform the merge when they are.
299       HInstruction* accumulator = nullptr;
300       HVecBinaryOperation* binop = use->AsVecBinaryOperation();
301       HInstruction* binop_left = binop->GetLeft();
302       HInstruction* binop_right = binop->GetRight();
303       // This is always true since the `HVecMul` has only one use (which is checked above).
304       DCHECK_NE(binop_left, binop_right);
305       if (binop_right == mul) {
306         accumulator = binop_left;
307       } else if (use->IsVecAdd()) {
308         DCHECK_EQ(binop_left, mul);
309         accumulator = binop_right;
310       }
311 
312       HInstruction::InstructionKind kind =
313           use->IsVecAdd() ? HInstruction::kAdd : HInstruction::kSub;
314       if (accumulator != nullptr) {
315         HVecMultiplyAccumulate* mulacc =
316             new (allocator) HVecMultiplyAccumulate(allocator,
317                                                    kind,
318                                                    accumulator,
319                                                    mul->GetLeft(),
320                                                    mul->GetRight(),
321                                                    binop->GetPackedType(),
322                                                    binop->GetVectorLength(),
323                                                    binop->GetDexPc());
324 
325         binop->GetBlock()->ReplaceAndRemoveInstructionWith(binop, mulacc);
326         DCHECK(!mul->HasUses());
327         mul->GetBlock()->RemoveInstruction(mul);
328         return true;
329       }
330     }
331   }
332 
333   return false;
334 }
335 
VisitShift(HBinaryOperation * instruction)336 void InstructionSimplifierVisitor::VisitShift(HBinaryOperation* instruction) {
337   DCHECK(instruction->IsShl() || instruction->IsShr() || instruction->IsUShr());
338   HInstruction* shift_amount = instruction->GetRight();
339   HInstruction* value = instruction->GetLeft();
340 
341   int64_t implicit_mask = (value->GetType() == DataType::Type::kInt64)
342       ? kMaxLongShiftDistance
343       : kMaxIntShiftDistance;
344 
345   if (shift_amount->IsConstant()) {
346     int64_t cst = Int64FromConstant(shift_amount->AsConstant());
347     int64_t masked_cst = cst & implicit_mask;
348     if (masked_cst == 0) {
349       // Replace code looking like
350       //    SHL dst, value, 0
351       // with
352       //    value
353       instruction->ReplaceWith(value);
354       instruction->GetBlock()->RemoveInstruction(instruction);
355       RecordSimplification();
356       return;
357     } else if (masked_cst != cst) {
358       // Replace code looking like
359       //    SHL dst, value, cst
360       // where cst exceeds maximum distance with the equivalent
361       //    SHL dst, value, cst & implicit_mask
362       // (as defined by shift semantics). This ensures other
363       // optimizations do not need to special case for such situations.
364       DCHECK_EQ(shift_amount->GetType(), DataType::Type::kInt32);
365       instruction->ReplaceInput(GetGraph()->GetIntConstant(masked_cst), /* index= */ 1);
366       RecordSimplification();
367       return;
368     }
369   }
370 
371   // Shift operations implicitly mask the shift amount according to the type width. Get rid of
372   // unnecessary And/Or/Xor/Add/Sub/TypeConversion operations on the shift amount that do not
373   // affect the relevant bits.
374   // Replace code looking like
375   //    AND adjusted_shift, shift, <superset of implicit mask>
376   //    [OR/XOR/ADD/SUB adjusted_shift, shift, <value not overlapping with implicit mask>]
377   //    [<conversion-from-integral-non-64-bit-type> adjusted_shift, shift]
378   //    SHL dst, value, adjusted_shift
379   // with
380   //    SHL dst, value, shift
381   if (shift_amount->IsAnd() ||
382       shift_amount->IsOr() ||
383       shift_amount->IsXor() ||
384       shift_amount->IsAdd() ||
385       shift_amount->IsSub()) {
386     int64_t required_result = shift_amount->IsAnd() ? implicit_mask : 0;
387     HBinaryOperation* bin_op = shift_amount->AsBinaryOperation();
388     HConstant* mask = bin_op->GetConstantRight();
389     if (mask != nullptr && (Int64FromConstant(mask) & implicit_mask) == required_result) {
390       instruction->ReplaceInput(bin_op->GetLeastConstantLeft(), 1);
391       RecordSimplification();
392       return;
393     }
394   } else if (shift_amount->IsTypeConversion()) {
395     DCHECK_NE(shift_amount->GetType(), DataType::Type::kBool);  // We never convert to bool.
396     DataType::Type source_type = shift_amount->InputAt(0)->GetType();
397     // Non-integral and 64-bit source types require an explicit type conversion.
398     if (DataType::IsIntegralType(source_type) && !DataType::Is64BitType(source_type)) {
399       instruction->ReplaceInput(shift_amount->AsTypeConversion()->GetInput(), 1);
400       RecordSimplification();
401       return;
402     }
403   }
404 }
405 
IsSubRegBitsMinusOther(HSub * sub,size_t reg_bits,HInstruction * other)406 static bool IsSubRegBitsMinusOther(HSub* sub, size_t reg_bits, HInstruction* other) {
407   return (sub->GetRight() == other &&
408           sub->GetLeft()->IsConstant() &&
409           (Int64FromConstant(sub->GetLeft()->AsConstant()) & (reg_bits - 1)) == 0);
410 }
411 
ReplaceRotateWithRor(HBinaryOperation * op,HUShr * ushr,HShl * shl)412 bool InstructionSimplifierVisitor::ReplaceRotateWithRor(HBinaryOperation* op,
413                                                         HUShr* ushr,
414                                                         HShl* shl) {
415   DCHECK(op->IsAdd() || op->IsXor() || op->IsOr()) << op->DebugName();
416   HRor* ror =
417       new (GetGraph()->GetAllocator()) HRor(ushr->GetType(), ushr->GetLeft(), ushr->GetRight());
418   op->GetBlock()->ReplaceAndRemoveInstructionWith(op, ror);
419   if (!ushr->HasUses()) {
420     ushr->GetBlock()->RemoveInstruction(ushr);
421   }
422   if (!ushr->GetRight()->HasUses()) {
423     ushr->GetRight()->GetBlock()->RemoveInstruction(ushr->GetRight());
424   }
425   if (!shl->HasUses()) {
426     shl->GetBlock()->RemoveInstruction(shl);
427   }
428   if (!shl->GetRight()->HasUses()) {
429     shl->GetRight()->GetBlock()->RemoveInstruction(shl->GetRight());
430   }
431   RecordSimplification();
432   return true;
433 }
434 
435 // Try to replace a binary operation flanked by one UShr and one Shl with a bitfield rotation.
TryReplaceWithRotate(HBinaryOperation * op)436 bool InstructionSimplifierVisitor::TryReplaceWithRotate(HBinaryOperation* op) {
437   DCHECK(op->IsAdd() || op->IsXor() || op->IsOr());
438   HInstruction* left = op->GetLeft();
439   HInstruction* right = op->GetRight();
440   // If we have an UShr and a Shl (in either order).
441   if ((left->IsUShr() && right->IsShl()) || (left->IsShl() && right->IsUShr())) {
442     HUShr* ushr = left->IsUShr() ? left->AsUShr() : right->AsUShr();
443     HShl* shl = left->IsShl() ? left->AsShl() : right->AsShl();
444     DCHECK(DataType::IsIntOrLongType(ushr->GetType()));
445     if (ushr->GetType() == shl->GetType() &&
446         ushr->GetLeft() == shl->GetLeft()) {
447       if (ushr->GetRight()->IsConstant() && shl->GetRight()->IsConstant()) {
448         // Shift distances are both constant, try replacing with Ror if they
449         // add up to the register size.
450         return TryReplaceWithRotateConstantPattern(op, ushr, shl);
451       } else if (ushr->GetRight()->IsSub() || shl->GetRight()->IsSub()) {
452         // Shift distances are potentially of the form x and (reg_size - x).
453         return TryReplaceWithRotateRegisterSubPattern(op, ushr, shl);
454       } else if (ushr->GetRight()->IsNeg() || shl->GetRight()->IsNeg()) {
455         // Shift distances are potentially of the form d and -d.
456         return TryReplaceWithRotateRegisterNegPattern(op, ushr, shl);
457       }
458     }
459   }
460   return false;
461 }
462 
463 // Try replacing code looking like (x >>> #rdist OP x << #ldist):
464 //    UShr dst, x,   #rdist
465 //    Shl  tmp, x,   #ldist
466 //    OP   dst, dst, tmp
467 // or like (x >>> #rdist OP x << #-ldist):
468 //    UShr dst, x,   #rdist
469 //    Shl  tmp, x,   #-ldist
470 //    OP   dst, dst, tmp
471 // with
472 //    Ror  dst, x,   #rdist
TryReplaceWithRotateConstantPattern(HBinaryOperation * op,HUShr * ushr,HShl * shl)473 bool InstructionSimplifierVisitor::TryReplaceWithRotateConstantPattern(HBinaryOperation* op,
474                                                                        HUShr* ushr,
475                                                                        HShl* shl) {
476   DCHECK(op->IsAdd() || op->IsXor() || op->IsOr());
477   size_t reg_bits = DataType::Size(ushr->GetType()) * kBitsPerByte;
478   size_t rdist = Int64FromConstant(ushr->GetRight()->AsConstant());
479   size_t ldist = Int64FromConstant(shl->GetRight()->AsConstant());
480   if (((ldist + rdist) & (reg_bits - 1)) == 0) {
481     ReplaceRotateWithRor(op, ushr, shl);
482     return true;
483   }
484   return false;
485 }
486 
487 // Replace code looking like (x >>> -d OP x << d):
488 //    Neg  neg, d
489 //    UShr dst, x,   neg
490 //    Shl  tmp, x,   d
491 //    OP   dst, dst, tmp
492 // with
493 //    Neg  neg, d
494 //    Ror  dst, x,   neg
495 // *** OR ***
496 // Replace code looking like (x >>> d OP x << -d):
497 //    UShr dst, x,   d
498 //    Neg  neg, d
499 //    Shl  tmp, x,   neg
500 //    OP   dst, dst, tmp
501 // with
502 //    Ror  dst, x,   d
TryReplaceWithRotateRegisterNegPattern(HBinaryOperation * op,HUShr * ushr,HShl * shl)503 bool InstructionSimplifierVisitor::TryReplaceWithRotateRegisterNegPattern(HBinaryOperation* op,
504                                                                           HUShr* ushr,
505                                                                           HShl* shl) {
506   DCHECK(op->IsAdd() || op->IsXor() || op->IsOr());
507   DCHECK(ushr->GetRight()->IsNeg() || shl->GetRight()->IsNeg());
508   bool neg_is_left = shl->GetRight()->IsNeg();
509   HNeg* neg = neg_is_left ? shl->GetRight()->AsNeg() : ushr->GetRight()->AsNeg();
510   // And the shift distance being negated is the distance being shifted the other way.
511   if (neg->InputAt(0) == (neg_is_left ? ushr->GetRight() : shl->GetRight())) {
512     ReplaceRotateWithRor(op, ushr, shl);
513   }
514   return false;
515 }
516 
517 // Try replacing code looking like (x >>> d OP x << (#bits - d)):
518 //    UShr dst, x,     d
519 //    Sub  ld,  #bits, d
520 //    Shl  tmp, x,     ld
521 //    OP   dst, dst,   tmp
522 // with
523 //    Ror  dst, x,     d
524 // *** OR ***
525 // Replace code looking like (x >>> (#bits - d) OP x << d):
526 //    Sub  rd,  #bits, d
527 //    UShr dst, x,     rd
528 //    Shl  tmp, x,     d
529 //    OP   dst, dst,   tmp
530 // with
531 //    Neg  neg, d
532 //    Ror  dst, x,     neg
TryReplaceWithRotateRegisterSubPattern(HBinaryOperation * op,HUShr * ushr,HShl * shl)533 bool InstructionSimplifierVisitor::TryReplaceWithRotateRegisterSubPattern(HBinaryOperation* op,
534                                                                           HUShr* ushr,
535                                                                           HShl* shl) {
536   DCHECK(op->IsAdd() || op->IsXor() || op->IsOr());
537   DCHECK(ushr->GetRight()->IsSub() || shl->GetRight()->IsSub());
538   size_t reg_bits = DataType::Size(ushr->GetType()) * kBitsPerByte;
539   HInstruction* shl_shift = shl->GetRight();
540   HInstruction* ushr_shift = ushr->GetRight();
541   if ((shl_shift->IsSub() && IsSubRegBitsMinusOther(shl_shift->AsSub(), reg_bits, ushr_shift)) ||
542       (ushr_shift->IsSub() && IsSubRegBitsMinusOther(ushr_shift->AsSub(), reg_bits, shl_shift))) {
543     return ReplaceRotateWithRor(op, ushr, shl);
544   }
545   return false;
546 }
547 
VisitNullCheck(HNullCheck * null_check)548 void InstructionSimplifierVisitor::VisitNullCheck(HNullCheck* null_check) {
549   HInstruction* obj = null_check->InputAt(0);
550   if (!obj->CanBeNull()) {
551     null_check->ReplaceWith(obj);
552     null_check->GetBlock()->RemoveInstruction(null_check);
553     if (stats_ != nullptr) {
554       stats_->RecordStat(MethodCompilationStat::kRemovedNullCheck);
555     }
556   }
557 }
558 
CanEnsureNotNullAt(HInstruction * input,HInstruction * at) const559 bool InstructionSimplifierVisitor::CanEnsureNotNullAt(HInstruction* input, HInstruction* at) const {
560   if (!input->CanBeNull()) {
561     return true;
562   }
563 
564   for (const HUseListNode<HInstruction*>& use : input->GetUses()) {
565     HInstruction* user = use.GetUser();
566     if (user->IsNullCheck() && user->StrictlyDominates(at)) {
567       return true;
568     }
569   }
570 
571   return false;
572 }
573 
574 // Returns whether doing a type test between the class of `object` against `klass` has
575 // a statically known outcome. The result of the test is stored in `outcome`.
TypeCheckHasKnownOutcome(ReferenceTypeInfo class_rti,HInstruction * object,bool * outcome)576 static bool TypeCheckHasKnownOutcome(ReferenceTypeInfo class_rti,
577                                      HInstruction* object,
578                                      /*out*/bool* outcome) {
579   DCHECK(!object->IsNullConstant()) << "Null constants should be special cased";
580   ReferenceTypeInfo obj_rti = object->GetReferenceTypeInfo();
581   ScopedObjectAccess soa(Thread::Current());
582   if (!obj_rti.IsValid()) {
583     // We run the simplifier before the reference type propagation so type info might not be
584     // available.
585     return false;
586   }
587 
588   if (!class_rti.IsValid()) {
589     // Happens when the loaded class is unresolved.
590     return false;
591   }
592   DCHECK(class_rti.IsExact());
593   if (class_rti.IsSupertypeOf(obj_rti)) {
594     *outcome = true;
595     return true;
596   } else if (obj_rti.IsExact()) {
597     // The test failed at compile time so will also fail at runtime.
598     *outcome = false;
599     return true;
600   } else if (!class_rti.IsInterface()
601              && !obj_rti.IsInterface()
602              && !obj_rti.IsSupertypeOf(class_rti)) {
603     // Different type hierarchy. The test will fail.
604     *outcome = false;
605     return true;
606   }
607   return false;
608 }
609 
VisitCheckCast(HCheckCast * check_cast)610 void InstructionSimplifierVisitor::VisitCheckCast(HCheckCast* check_cast) {
611   HInstruction* object = check_cast->InputAt(0);
612   if (check_cast->GetTypeCheckKind() != TypeCheckKind::kBitstringCheck &&
613       check_cast->GetTargetClass()->NeedsAccessCheck()) {
614     // If we need to perform an access check we cannot remove the instruction.
615     return;
616   }
617 
618   if (CanEnsureNotNullAt(object, check_cast)) {
619     check_cast->ClearMustDoNullCheck();
620   }
621 
622   if (object->IsNullConstant()) {
623     check_cast->GetBlock()->RemoveInstruction(check_cast);
624     MaybeRecordStat(stats_, MethodCompilationStat::kRemovedCheckedCast);
625     return;
626   }
627 
628   // Historical note: The `outcome` was initialized to please Valgrind - the compiler can reorder
629   // the return value check with the `outcome` check, b/27651442.
630   bool outcome = false;
631   if (TypeCheckHasKnownOutcome(check_cast->GetTargetClassRTI(), object, &outcome)) {
632     if (outcome) {
633       check_cast->GetBlock()->RemoveInstruction(check_cast);
634       MaybeRecordStat(stats_, MethodCompilationStat::kRemovedCheckedCast);
635       if (check_cast->GetTypeCheckKind() != TypeCheckKind::kBitstringCheck) {
636         HLoadClass* load_class = check_cast->GetTargetClass();
637         if (!load_class->HasUses()) {
638           // We cannot rely on DCE to remove the class because the `HLoadClass` thinks it can throw.
639           // However, here we know that it cannot because the checkcast was successfull, hence
640           // the class was already loaded.
641           load_class->GetBlock()->RemoveInstruction(load_class);
642         }
643       }
644     } else {
645       // Don't do anything for exceptional cases for now. Ideally we should remove
646       // all instructions and blocks this instruction dominates.
647     }
648   }
649 }
650 
VisitInstanceOf(HInstanceOf * instruction)651 void InstructionSimplifierVisitor::VisitInstanceOf(HInstanceOf* instruction) {
652   HInstruction* object = instruction->InputAt(0);
653   if (instruction->GetTypeCheckKind() != TypeCheckKind::kBitstringCheck &&
654       instruction->GetTargetClass()->NeedsAccessCheck()) {
655     // If we need to perform an access check we cannot remove the instruction.
656     return;
657   }
658 
659   bool can_be_null = true;
660   if (CanEnsureNotNullAt(object, instruction)) {
661     can_be_null = false;
662     instruction->ClearMustDoNullCheck();
663   }
664 
665   HGraph* graph = GetGraph();
666   if (object->IsNullConstant()) {
667     MaybeRecordStat(stats_, MethodCompilationStat::kRemovedInstanceOf);
668     instruction->ReplaceWith(graph->GetIntConstant(0));
669     instruction->GetBlock()->RemoveInstruction(instruction);
670     RecordSimplification();
671     return;
672   }
673 
674   // Historical note: The `outcome` was initialized to please Valgrind - the compiler can reorder
675   // the return value check with the `outcome` check, b/27651442.
676   bool outcome = false;
677   if (TypeCheckHasKnownOutcome(instruction->GetTargetClassRTI(), object, &outcome)) {
678     MaybeRecordStat(stats_, MethodCompilationStat::kRemovedInstanceOf);
679     if (outcome && can_be_null) {
680       // Type test will succeed, we just need a null test.
681       HNotEqual* test = new (graph->GetAllocator()) HNotEqual(graph->GetNullConstant(), object);
682       instruction->GetBlock()->InsertInstructionBefore(test, instruction);
683       instruction->ReplaceWith(test);
684     } else {
685       // We've statically determined the result of the instanceof.
686       instruction->ReplaceWith(graph->GetIntConstant(outcome));
687     }
688     RecordSimplification();
689     instruction->GetBlock()->RemoveInstruction(instruction);
690     if (outcome && instruction->GetTypeCheckKind() != TypeCheckKind::kBitstringCheck) {
691       HLoadClass* load_class = instruction->GetTargetClass();
692       if (!load_class->HasUses()) {
693         // We cannot rely on DCE to remove the class because the `HLoadClass` thinks it can throw.
694         // However, here we know that it cannot because the instanceof check was successfull, hence
695         // the class was already loaded.
696         load_class->GetBlock()->RemoveInstruction(load_class);
697       }
698     }
699   }
700 }
701 
VisitInstanceFieldSet(HInstanceFieldSet * instruction)702 void InstructionSimplifierVisitor::VisitInstanceFieldSet(HInstanceFieldSet* instruction) {
703   if ((instruction->GetValue()->GetType() == DataType::Type::kReference)
704       && CanEnsureNotNullAt(instruction->GetValue(), instruction)) {
705     instruction->ClearValueCanBeNull();
706   }
707 }
708 
VisitStaticFieldSet(HStaticFieldSet * instruction)709 void InstructionSimplifierVisitor::VisitStaticFieldSet(HStaticFieldSet* instruction) {
710   if ((instruction->GetValue()->GetType() == DataType::Type::kReference)
711       && CanEnsureNotNullAt(instruction->GetValue(), instruction)) {
712     instruction->ClearValueCanBeNull();
713   }
714 }
715 
GetOppositeConditionSwapOps(ArenaAllocator * allocator,HInstruction * cond)716 static HCondition* GetOppositeConditionSwapOps(ArenaAllocator* allocator, HInstruction* cond) {
717   HInstruction *lhs = cond->InputAt(0);
718   HInstruction *rhs = cond->InputAt(1);
719   switch (cond->GetKind()) {
720     case HInstruction::kEqual:
721       return new (allocator) HEqual(rhs, lhs);
722     case HInstruction::kNotEqual:
723       return new (allocator) HNotEqual(rhs, lhs);
724     case HInstruction::kLessThan:
725       return new (allocator) HGreaterThan(rhs, lhs);
726     case HInstruction::kLessThanOrEqual:
727       return new (allocator) HGreaterThanOrEqual(rhs, lhs);
728     case HInstruction::kGreaterThan:
729       return new (allocator) HLessThan(rhs, lhs);
730     case HInstruction::kGreaterThanOrEqual:
731       return new (allocator) HLessThanOrEqual(rhs, lhs);
732     case HInstruction::kBelow:
733       return new (allocator) HAbove(rhs, lhs);
734     case HInstruction::kBelowOrEqual:
735       return new (allocator) HAboveOrEqual(rhs, lhs);
736     case HInstruction::kAbove:
737       return new (allocator) HBelow(rhs, lhs);
738     case HInstruction::kAboveOrEqual:
739       return new (allocator) HBelowOrEqual(rhs, lhs);
740     default:
741       LOG(FATAL) << "Unknown ConditionType " << cond->GetKind();
742       UNREACHABLE();
743   }
744 }
745 
VisitEqual(HEqual * equal)746 void InstructionSimplifierVisitor::VisitEqual(HEqual* equal) {
747   HInstruction* input_const = equal->GetConstantRight();
748   if (input_const != nullptr) {
749     HInstruction* input_value = equal->GetLeastConstantLeft();
750     if ((input_value->GetType() == DataType::Type::kBool) && input_const->IsIntConstant()) {
751       HBasicBlock* block = equal->GetBlock();
752       // We are comparing the boolean to a constant which is of type int and can
753       // be any constant.
754       if (input_const->AsIntConstant()->IsTrue()) {
755         // Replace (bool_value == true) with bool_value
756         equal->ReplaceWith(input_value);
757         block->RemoveInstruction(equal);
758         RecordSimplification();
759       } else if (input_const->AsIntConstant()->IsFalse()) {
760         // Replace (bool_value == false) with !bool_value
761         equal->ReplaceWith(GetGraph()->InsertOppositeCondition(input_value, equal));
762         block->RemoveInstruction(equal);
763         RecordSimplification();
764       } else {
765         // Replace (bool_value == integer_not_zero_nor_one_constant) with false
766         equal->ReplaceWith(GetGraph()->GetIntConstant(0));
767         block->RemoveInstruction(equal);
768         RecordSimplification();
769       }
770     } else {
771       VisitCondition(equal);
772     }
773   } else {
774     VisitCondition(equal);
775   }
776 }
777 
VisitNotEqual(HNotEqual * not_equal)778 void InstructionSimplifierVisitor::VisitNotEqual(HNotEqual* not_equal) {
779   HInstruction* input_const = not_equal->GetConstantRight();
780   if (input_const != nullptr) {
781     HInstruction* input_value = not_equal->GetLeastConstantLeft();
782     if ((input_value->GetType() == DataType::Type::kBool) && input_const->IsIntConstant()) {
783       HBasicBlock* block = not_equal->GetBlock();
784       // We are comparing the boolean to a constant which is of type int and can
785       // be any constant.
786       if (input_const->AsIntConstant()->IsTrue()) {
787         // Replace (bool_value != true) with !bool_value
788         not_equal->ReplaceWith(GetGraph()->InsertOppositeCondition(input_value, not_equal));
789         block->RemoveInstruction(not_equal);
790         RecordSimplification();
791       } else if (input_const->AsIntConstant()->IsFalse()) {
792         // Replace (bool_value != false) with bool_value
793         not_equal->ReplaceWith(input_value);
794         block->RemoveInstruction(not_equal);
795         RecordSimplification();
796       } else {
797         // Replace (bool_value != integer_not_zero_nor_one_constant) with true
798         not_equal->ReplaceWith(GetGraph()->GetIntConstant(1));
799         block->RemoveInstruction(not_equal);
800         RecordSimplification();
801       }
802     } else {
803       VisitCondition(not_equal);
804     }
805   } else {
806     VisitCondition(not_equal);
807   }
808 }
809 
VisitBooleanNot(HBooleanNot * bool_not)810 void InstructionSimplifierVisitor::VisitBooleanNot(HBooleanNot* bool_not) {
811   HInstruction* input = bool_not->InputAt(0);
812   HInstruction* replace_with = nullptr;
813 
814   if (input->IsIntConstant()) {
815     // Replace !(true/false) with false/true.
816     if (input->AsIntConstant()->IsTrue()) {
817       replace_with = GetGraph()->GetIntConstant(0);
818     } else {
819       DCHECK(input->AsIntConstant()->IsFalse()) << input->AsIntConstant()->GetValue();
820       replace_with = GetGraph()->GetIntConstant(1);
821     }
822   } else if (input->IsBooleanNot()) {
823     // Replace (!(!bool_value)) with bool_value.
824     replace_with = input->InputAt(0);
825   } else if (input->IsCondition() &&
826              // Don't change FP compares. The definition of compares involving
827              // NaNs forces the compares to be done as written by the user.
828              !DataType::IsFloatingPointType(input->InputAt(0)->GetType())) {
829     // Replace condition with its opposite.
830     replace_with = GetGraph()->InsertOppositeCondition(input->AsCondition(), bool_not);
831   }
832 
833   if (replace_with != nullptr) {
834     bool_not->ReplaceWith(replace_with);
835     bool_not->GetBlock()->RemoveInstruction(bool_not);
836     RecordSimplification();
837   }
838 }
839 
840 // Constructs a new ABS(x) node in the HIR.
NewIntegralAbs(ArenaAllocator * allocator,HInstruction * x,HInstruction * cursor)841 static HInstruction* NewIntegralAbs(ArenaAllocator* allocator,
842                                     HInstruction* x,
843                                     HInstruction* cursor) {
844   DataType::Type type = DataType::Kind(x->GetType());
845   DCHECK(type == DataType::Type::kInt32 || type == DataType::Type::kInt64);
846   HAbs* abs = new (allocator) HAbs(type, x, cursor->GetDexPc());
847   cursor->GetBlock()->InsertInstructionBefore(abs, cursor);
848   return abs;
849 }
850 
851 // Constructs a new MIN/MAX(x, y) node in the HIR.
NewIntegralMinMax(ArenaAllocator * allocator,HInstruction * x,HInstruction * y,HInstruction * cursor,bool is_min)852 static HInstruction* NewIntegralMinMax(ArenaAllocator* allocator,
853                                        HInstruction* x,
854                                        HInstruction* y,
855                                        HInstruction* cursor,
856                                        bool is_min) {
857   DataType::Type type = DataType::Kind(x->GetType());
858   DCHECK(type == DataType::Type::kInt32 || type == DataType::Type::kInt64);
859   HBinaryOperation* minmax = nullptr;
860   if (is_min) {
861     minmax = new (allocator) HMin(type, x, y, cursor->GetDexPc());
862   } else {
863     minmax = new (allocator) HMax(type, x, y, cursor->GetDexPc());
864   }
865   cursor->GetBlock()->InsertInstructionBefore(minmax, cursor);
866   return minmax;
867 }
868 
869 // Returns true if operands a and b consists of widening type conversions
870 // (either explicit or implicit) to the given to_type.
AreLowerPrecisionArgs(DataType::Type to_type,HInstruction * a,HInstruction * b)871 static bool AreLowerPrecisionArgs(DataType::Type to_type, HInstruction* a, HInstruction* b) {
872   if (a->IsTypeConversion() && a->GetType() == to_type) {
873     a = a->InputAt(0);
874   }
875   if (b->IsTypeConversion() && b->GetType() == to_type) {
876     b = b->InputAt(0);
877   }
878   DataType::Type type1 = a->GetType();
879   DataType::Type type2 = b->GetType();
880   return (type1 == DataType::Type::kUint8  && type2 == DataType::Type::kUint8) ||
881          (type1 == DataType::Type::kInt8   && type2 == DataType::Type::kInt8) ||
882          (type1 == DataType::Type::kInt16  && type2 == DataType::Type::kInt16) ||
883          (type1 == DataType::Type::kUint16 && type2 == DataType::Type::kUint16) ||
884          (type1 == DataType::Type::kInt32  && type2 == DataType::Type::kInt32 &&
885           to_type == DataType::Type::kInt64);
886 }
887 
888 // Returns an acceptable substitution for "a" on the select
889 // construct "a <cmp> b ? c : .."  during MIN/MAX recognition.
AllowInMinMax(IfCondition cmp,HInstruction * a,HInstruction * b,HInstruction * c)890 static HInstruction* AllowInMinMax(IfCondition cmp,
891                                    HInstruction* a,
892                                    HInstruction* b,
893                                    HInstruction* c) {
894   int64_t value = 0;
895   if (IsInt64AndGet(b, /*out*/ &value) &&
896       (((cmp == kCondLT || cmp == kCondLE) && c->IsMax()) ||
897        ((cmp == kCondGT || cmp == kCondGE) && c->IsMin()))) {
898     HConstant* other = c->AsBinaryOperation()->GetConstantRight();
899     if (other != nullptr && a == c->AsBinaryOperation()->GetLeastConstantLeft()) {
900       int64_t other_value = Int64FromConstant(other);
901       bool is_max = (cmp == kCondLT || cmp == kCondLE);
902       // Allow the max for a <  100 ? max(a, -100) : ..
903       //    or the min for a > -100 ? min(a,  100) : ..
904       if (is_max ? (value >= other_value) : (value <= other_value)) {
905         return c;
906       }
907     }
908   }
909   return nullptr;
910 }
911 
VisitSelect(HSelect * select)912 void InstructionSimplifierVisitor::VisitSelect(HSelect* select) {
913   HInstruction* replace_with = nullptr;
914   HInstruction* condition = select->GetCondition();
915   HInstruction* true_value = select->GetTrueValue();
916   HInstruction* false_value = select->GetFalseValue();
917 
918   if (condition->IsBooleanNot()) {
919     // Change ((!cond) ? x : y) to (cond ? y : x).
920     condition = condition->InputAt(0);
921     std::swap(true_value, false_value);
922     select->ReplaceInput(false_value, 0);
923     select->ReplaceInput(true_value, 1);
924     select->ReplaceInput(condition, 2);
925     RecordSimplification();
926   }
927 
928   if (true_value == false_value) {
929     // Replace (cond ? x : x) with (x).
930     replace_with = true_value;
931   } else if (condition->IsIntConstant()) {
932     if (condition->AsIntConstant()->IsTrue()) {
933       // Replace (true ? x : y) with (x).
934       replace_with = true_value;
935     } else {
936       // Replace (false ? x : y) with (y).
937       DCHECK(condition->AsIntConstant()->IsFalse()) << condition->AsIntConstant()->GetValue();
938       replace_with = false_value;
939     }
940   } else if (true_value->IsIntConstant() && false_value->IsIntConstant()) {
941     if (true_value->AsIntConstant()->IsTrue() && false_value->AsIntConstant()->IsFalse()) {
942       // Replace (cond ? true : false) with (cond).
943       replace_with = condition;
944     } else if (true_value->AsIntConstant()->IsFalse() && false_value->AsIntConstant()->IsTrue()) {
945       // Replace (cond ? false : true) with (!cond).
946       replace_with = GetGraph()->InsertOppositeCondition(condition, select);
947     }
948   } else if (condition->IsCondition()) {
949     IfCondition cmp = condition->AsCondition()->GetCondition();
950     HInstruction* a = condition->InputAt(0);
951     HInstruction* b = condition->InputAt(1);
952     DataType::Type t_type = true_value->GetType();
953     DataType::Type f_type = false_value->GetType();
954     // Here we have a <cmp> b ? true_value : false_value.
955     // Test if both values are compatible integral types (resulting MIN/MAX/ABS
956     // type will be int or long, like the condition). Replacements are general,
957     // but assume conditions prefer constants on the right.
958     if (DataType::IsIntegralType(t_type) && DataType::Kind(t_type) == DataType::Kind(f_type)) {
959       // Allow a <  100 ? max(a, -100) : ..
960       //    or a > -100 ? min(a,  100) : ..
961       // to use min/max instead of a to detect nested min/max expressions.
962       HInstruction* new_a = AllowInMinMax(cmp, a, b, true_value);
963       if (new_a != nullptr) {
964         a = new_a;
965       }
966       // Try to replace typical integral MIN/MAX/ABS constructs.
967       if ((cmp == kCondLT || cmp == kCondLE || cmp == kCondGT || cmp == kCondGE) &&
968           ((a == true_value && b == false_value) ||
969            (b == true_value && a == false_value))) {
970         // Found a < b ? a : b (MIN) or a < b ? b : a (MAX)
971         //    or a > b ? a : b (MAX) or a > b ? b : a (MIN).
972         bool is_min = (cmp == kCondLT || cmp == kCondLE) == (a == true_value);
973         replace_with = NewIntegralMinMax(GetGraph()->GetAllocator(), a, b, select, is_min);
974       } else if (((cmp == kCondLT || cmp == kCondLE) && true_value->IsNeg()) ||
975                  ((cmp == kCondGT || cmp == kCondGE) && false_value->IsNeg())) {
976         bool negLeft = (cmp == kCondLT || cmp == kCondLE);
977         HInstruction* the_negated = negLeft ? true_value->InputAt(0) : false_value->InputAt(0);
978         HInstruction* not_negated = negLeft ? false_value : true_value;
979         if (a == the_negated && a == not_negated && IsInt64Value(b, 0)) {
980           // Found a < 0 ? -a :  a
981           //    or a > 0 ?  a : -a
982           // which can be replaced by ABS(a).
983           replace_with = NewIntegralAbs(GetGraph()->GetAllocator(), a, select);
984         }
985       } else if (true_value->IsSub() && false_value->IsSub()) {
986         HInstruction* true_sub1 = true_value->InputAt(0);
987         HInstruction* true_sub2 = true_value->InputAt(1);
988         HInstruction* false_sub1 = false_value->InputAt(0);
989         HInstruction* false_sub2 = false_value->InputAt(1);
990         if ((((cmp == kCondGT || cmp == kCondGE) &&
991               (a == true_sub1 && b == true_sub2 && a == false_sub2 && b == false_sub1)) ||
992              ((cmp == kCondLT || cmp == kCondLE) &&
993               (a == true_sub2 && b == true_sub1 && a == false_sub1 && b == false_sub2))) &&
994             AreLowerPrecisionArgs(t_type, a, b)) {
995           // Found a > b ? a - b  : b - a
996           //    or a < b ? b - a  : a - b
997           // which can be replaced by ABS(a - b) for lower precision operands a, b.
998           replace_with = NewIntegralAbs(GetGraph()->GetAllocator(), true_value, select);
999         }
1000       }
1001     }
1002   }
1003 
1004   if (replace_with != nullptr) {
1005     select->ReplaceWith(replace_with);
1006     select->GetBlock()->RemoveInstruction(select);
1007     RecordSimplification();
1008   }
1009 }
1010 
VisitIf(HIf * instruction)1011 void InstructionSimplifierVisitor::VisitIf(HIf* instruction) {
1012   HInstruction* condition = instruction->InputAt(0);
1013   if (condition->IsBooleanNot()) {
1014     // Swap successors if input is negated.
1015     instruction->ReplaceInput(condition->InputAt(0), 0);
1016     instruction->GetBlock()->SwapSuccessors();
1017     RecordSimplification();
1018   }
1019 }
1020 
VisitArrayLength(HArrayLength * instruction)1021 void InstructionSimplifierVisitor::VisitArrayLength(HArrayLength* instruction) {
1022   HInstruction* input = instruction->InputAt(0);
1023   // If the array is a NewArray with constant size, replace the array length
1024   // with the constant instruction. This helps the bounds check elimination phase.
1025   if (input->IsNewArray()) {
1026     input = input->AsNewArray()->GetLength();
1027     if (input->IsIntConstant()) {
1028       instruction->ReplaceWith(input);
1029     }
1030   }
1031 }
1032 
VisitArraySet(HArraySet * instruction)1033 void InstructionSimplifierVisitor::VisitArraySet(HArraySet* instruction) {
1034   HInstruction* value = instruction->GetValue();
1035   if (value->GetType() != DataType::Type::kReference) {
1036     return;
1037   }
1038 
1039   if (CanEnsureNotNullAt(value, instruction)) {
1040     instruction->ClearValueCanBeNull();
1041   }
1042 
1043   if (value->IsArrayGet()) {
1044     if (value->AsArrayGet()->GetArray() == instruction->GetArray()) {
1045       // If the code is just swapping elements in the array, no need for a type check.
1046       instruction->ClearNeedsTypeCheck();
1047       return;
1048     }
1049   }
1050 
1051   if (value->IsNullConstant()) {
1052     instruction->ClearNeedsTypeCheck();
1053     return;
1054   }
1055 
1056   ScopedObjectAccess soa(Thread::Current());
1057   ReferenceTypeInfo array_rti = instruction->GetArray()->GetReferenceTypeInfo();
1058   ReferenceTypeInfo value_rti = value->GetReferenceTypeInfo();
1059   if (!array_rti.IsValid()) {
1060     return;
1061   }
1062 
1063   if (value_rti.IsValid() && array_rti.CanArrayHold(value_rti)) {
1064     instruction->ClearNeedsTypeCheck();
1065     return;
1066   }
1067 
1068   if (array_rti.IsObjectArray()) {
1069     if (array_rti.IsExact()) {
1070       instruction->ClearNeedsTypeCheck();
1071       return;
1072     }
1073     instruction->SetStaticTypeOfArrayIsObjectArray();
1074   }
1075 }
1076 
IsTypeConversionLossless(DataType::Type input_type,DataType::Type result_type)1077 static bool IsTypeConversionLossless(DataType::Type input_type, DataType::Type result_type) {
1078   // Make sure all implicit conversions have been simplified and no new ones have been introduced.
1079   DCHECK(!DataType::IsTypeConversionImplicit(input_type, result_type))
1080       << input_type << "," << result_type;
1081   // The conversion to a larger type is loss-less with the exception of two cases,
1082   //   - conversion to the unsigned type Uint16, where we may lose some bits, and
1083   //   - conversion from float to long, the only FP to integral conversion with smaller FP type.
1084   // For integral to FP conversions this holds because the FP mantissa is large enough.
1085   // Note: The size check excludes Uint8 as the result type.
1086   return DataType::Size(result_type) > DataType::Size(input_type) &&
1087       result_type != DataType::Type::kUint16 &&
1088       !(result_type == DataType::Type::kInt64 && input_type == DataType::Type::kFloat32);
1089 }
1090 
TryReplaceFieldOrArrayGetType(HInstruction * maybe_get,DataType::Type new_type)1091 static inline bool TryReplaceFieldOrArrayGetType(HInstruction* maybe_get, DataType::Type new_type) {
1092   if (maybe_get->IsInstanceFieldGet()) {
1093     maybe_get->AsInstanceFieldGet()->SetType(new_type);
1094     return true;
1095   } else if (maybe_get->IsStaticFieldGet()) {
1096     maybe_get->AsStaticFieldGet()->SetType(new_type);
1097     return true;
1098   } else if (maybe_get->IsArrayGet() && !maybe_get->AsArrayGet()->IsStringCharAt()) {
1099     maybe_get->AsArrayGet()->SetType(new_type);
1100     return true;
1101   } else {
1102     return false;
1103   }
1104 }
1105 
1106 // The type conversion is only used for storing into a field/element of the
1107 // same/narrower size.
IsTypeConversionForStoringIntoNoWiderFieldOnly(HTypeConversion * type_conversion)1108 static bool IsTypeConversionForStoringIntoNoWiderFieldOnly(HTypeConversion* type_conversion) {
1109   if (type_conversion->HasEnvironmentUses()) {
1110     return false;
1111   }
1112   DataType::Type input_type = type_conversion->GetInputType();
1113   DataType::Type result_type = type_conversion->GetResultType();
1114   if (!DataType::IsIntegralType(input_type) ||
1115       !DataType::IsIntegralType(result_type) ||
1116       input_type == DataType::Type::kInt64 ||
1117       result_type == DataType::Type::kInt64) {
1118     // Type conversion is needed if non-integer types are involved, or 64-bit
1119     // types are involved, which may use different number of registers.
1120     return false;
1121   }
1122   if (DataType::Size(input_type) >= DataType::Size(result_type)) {
1123     // Type conversion is not necessary when storing to a field/element of the
1124     // same/smaller size.
1125   } else {
1126     // We do not handle this case here.
1127     return false;
1128   }
1129 
1130   // Check if the converted value is only used for storing into heap.
1131   for (const HUseListNode<HInstruction*>& use : type_conversion->GetUses()) {
1132     HInstruction* instruction = use.GetUser();
1133     if (instruction->IsInstanceFieldSet() &&
1134         instruction->AsInstanceFieldSet()->GetFieldType() == result_type) {
1135       DCHECK_EQ(instruction->AsInstanceFieldSet()->GetValue(), type_conversion);
1136       continue;
1137     }
1138     if (instruction->IsStaticFieldSet() &&
1139         instruction->AsStaticFieldSet()->GetFieldType() == result_type) {
1140       DCHECK_EQ(instruction->AsStaticFieldSet()->GetValue(), type_conversion);
1141       continue;
1142     }
1143     if (instruction->IsArraySet() &&
1144         instruction->AsArraySet()->GetComponentType() == result_type &&
1145         // not index use.
1146         instruction->AsArraySet()->GetIndex() != type_conversion) {
1147       DCHECK_EQ(instruction->AsArraySet()->GetValue(), type_conversion);
1148       continue;
1149     }
1150     // The use is not as a store value, or the field/element type is not the
1151     // same as the result_type, keep the type conversion.
1152     return false;
1153   }
1154   // Codegen automatically handles the type conversion during the store.
1155   return true;
1156 }
1157 
VisitTypeConversion(HTypeConversion * instruction)1158 void InstructionSimplifierVisitor::VisitTypeConversion(HTypeConversion* instruction) {
1159   HInstruction* input = instruction->GetInput();
1160   DataType::Type input_type = input->GetType();
1161   DataType::Type result_type = instruction->GetResultType();
1162   if (instruction->IsImplicitConversion()) {
1163     instruction->ReplaceWith(input);
1164     instruction->GetBlock()->RemoveInstruction(instruction);
1165     RecordSimplification();
1166     return;
1167   }
1168 
1169   if (input->IsTypeConversion()) {
1170     HTypeConversion* input_conversion = input->AsTypeConversion();
1171     HInstruction* original_input = input_conversion->GetInput();
1172     DataType::Type original_type = original_input->GetType();
1173 
1174     // When the first conversion is lossless, a direct conversion from the original type
1175     // to the final type yields the same result, even for a lossy second conversion, for
1176     // example float->double->int or int->double->float.
1177     bool is_first_conversion_lossless = IsTypeConversionLossless(original_type, input_type);
1178 
1179     // For integral conversions, see if the first conversion loses only bits that the second
1180     // doesn't need, i.e. the final type is no wider than the intermediate. If so, direct
1181     // conversion yields the same result, for example long->int->short or int->char->short.
1182     bool integral_conversions_with_non_widening_second =
1183         DataType::IsIntegralType(input_type) &&
1184         DataType::IsIntegralType(original_type) &&
1185         DataType::IsIntegralType(result_type) &&
1186         DataType::Size(result_type) <= DataType::Size(input_type);
1187 
1188     if (is_first_conversion_lossless || integral_conversions_with_non_widening_second) {
1189       // If the merged conversion is implicit, do the simplification unconditionally.
1190       if (DataType::IsTypeConversionImplicit(original_type, result_type)) {
1191         instruction->ReplaceWith(original_input);
1192         instruction->GetBlock()->RemoveInstruction(instruction);
1193         if (!input_conversion->HasUses()) {
1194           // Don't wait for DCE.
1195           input_conversion->GetBlock()->RemoveInstruction(input_conversion);
1196         }
1197         RecordSimplification();
1198         return;
1199       }
1200       // Otherwise simplify only if the first conversion has no other use.
1201       if (input_conversion->HasOnlyOneNonEnvironmentUse()) {
1202         input_conversion->ReplaceWith(original_input);
1203         input_conversion->GetBlock()->RemoveInstruction(input_conversion);
1204         RecordSimplification();
1205         return;
1206       }
1207     }
1208   } else if (input->IsAnd() && DataType::IsIntegralType(result_type)) {
1209     DCHECK(DataType::IsIntegralType(input_type));
1210     HAnd* input_and = input->AsAnd();
1211     HConstant* constant = input_and->GetConstantRight();
1212     if (constant != nullptr) {
1213       int64_t value = Int64FromConstant(constant);
1214       DCHECK_NE(value, -1);  // "& -1" would have been optimized away in VisitAnd().
1215       size_t trailing_ones = CTZ(~static_cast<uint64_t>(value));
1216       if (trailing_ones >= kBitsPerByte * DataType::Size(result_type)) {
1217         // The `HAnd` is useless, for example in `(byte) (x & 0xff)`, get rid of it.
1218         HInstruction* original_input = input_and->GetLeastConstantLeft();
1219         if (DataType::IsTypeConversionImplicit(original_input->GetType(), result_type)) {
1220           instruction->ReplaceWith(original_input);
1221           instruction->GetBlock()->RemoveInstruction(instruction);
1222           RecordSimplification();
1223           return;
1224         } else if (input->HasOnlyOneNonEnvironmentUse()) {
1225           input_and->ReplaceWith(original_input);
1226           input_and->GetBlock()->RemoveInstruction(input_and);
1227           RecordSimplification();
1228           return;
1229         }
1230       }
1231     }
1232   } else if (input->HasOnlyOneNonEnvironmentUse() &&
1233              ((input_type == DataType::Type::kInt8 && result_type == DataType::Type::kUint8) ||
1234               (input_type == DataType::Type::kUint8 && result_type == DataType::Type::kInt8) ||
1235               (input_type == DataType::Type::kInt16 && result_type == DataType::Type::kUint16) ||
1236               (input_type == DataType::Type::kUint16 && result_type == DataType::Type::kInt16))) {
1237     // Try to modify the type of the load to `result_type` and remove the explicit type conversion.
1238     if (TryReplaceFieldOrArrayGetType(input, result_type)) {
1239       instruction->ReplaceWith(input);
1240       instruction->GetBlock()->RemoveInstruction(instruction);
1241       RecordSimplification();
1242       return;
1243     }
1244   }
1245 
1246   if (IsTypeConversionForStoringIntoNoWiderFieldOnly(instruction)) {
1247     instruction->ReplaceWith(input);
1248     instruction->GetBlock()->RemoveInstruction(instruction);
1249     RecordSimplification();
1250     return;
1251   }
1252 }
1253 
VisitAbs(HAbs * instruction)1254 void InstructionSimplifierVisitor::VisitAbs(HAbs* instruction) {
1255   HInstruction* input = instruction->GetInput();
1256   if (DataType::IsZeroExtension(input->GetType(), instruction->GetResultType())) {
1257     // Zero extension from narrow to wide can never set sign bit in the wider
1258     // operand, making the subsequent Abs redundant (e.g., abs(b & 0xff) for byte b).
1259     instruction->ReplaceWith(input);
1260     instruction->GetBlock()->RemoveInstruction(instruction);
1261     RecordSimplification();
1262   }
1263 }
1264 
VisitAdd(HAdd * instruction)1265 void InstructionSimplifierVisitor::VisitAdd(HAdd* instruction) {
1266   HConstant* input_cst = instruction->GetConstantRight();
1267   HInstruction* input_other = instruction->GetLeastConstantLeft();
1268   bool integral_type = DataType::IsIntegralType(instruction->GetType());
1269   if ((input_cst != nullptr) && input_cst->IsArithmeticZero()) {
1270     // Replace code looking like
1271     //    ADD dst, src, 0
1272     // with
1273     //    src
1274     // Note that we cannot optimize `x + 0.0` to `x` for floating-point. When
1275     // `x` is `-0.0`, the former expression yields `0.0`, while the later
1276     // yields `-0.0`.
1277     if (integral_type) {
1278       instruction->ReplaceWith(input_other);
1279       instruction->GetBlock()->RemoveInstruction(instruction);
1280       RecordSimplification();
1281       return;
1282     }
1283   }
1284 
1285   HInstruction* left = instruction->GetLeft();
1286   HInstruction* right = instruction->GetRight();
1287   bool left_is_neg = left->IsNeg();
1288   bool right_is_neg = right->IsNeg();
1289 
1290   if (left_is_neg && right_is_neg) {
1291     if (TryMoveNegOnInputsAfterBinop(instruction)) {
1292       return;
1293     }
1294   }
1295 
1296   HNeg* neg = left_is_neg ? left->AsNeg() : right->AsNeg();
1297   if (left_is_neg != right_is_neg && neg->HasOnlyOneNonEnvironmentUse()) {
1298     // Replace code looking like
1299     //    NEG tmp, b
1300     //    ADD dst, a, tmp
1301     // with
1302     //    SUB dst, a, b
1303     // We do not perform the optimization if the input negation has environment
1304     // uses or multiple non-environment uses as it could lead to worse code. In
1305     // particular, we do not want the live range of `b` to be extended if we are
1306     // not sure the initial 'NEG' instruction can be removed.
1307     HInstruction* other = left_is_neg ? right : left;
1308     HSub* sub =
1309         new(GetGraph()->GetAllocator()) HSub(instruction->GetType(), other, neg->GetInput());
1310     instruction->GetBlock()->ReplaceAndRemoveInstructionWith(instruction, sub);
1311     RecordSimplification();
1312     neg->GetBlock()->RemoveInstruction(neg);
1313     return;
1314   }
1315 
1316   if (TryReplaceWithRotate(instruction)) {
1317     return;
1318   }
1319 
1320   // TryHandleAssociativeAndCommutativeOperation() does not remove its input,
1321   // so no need to return.
1322   TryHandleAssociativeAndCommutativeOperation(instruction);
1323 
1324   if ((left->IsSub() || right->IsSub()) &&
1325       TrySubtractionChainSimplification(instruction)) {
1326     return;
1327   }
1328 
1329   if (integral_type) {
1330     // Replace code patterns looking like
1331     //    SUB dst1, x, y        SUB dst1, x, y
1332     //    ADD dst2, dst1, y     ADD dst2, y, dst1
1333     // with
1334     //    SUB dst1, x, y
1335     // ADD instruction is not needed in this case, we may use
1336     // one of inputs of SUB instead.
1337     if (left->IsSub() && left->InputAt(1) == right) {
1338       instruction->ReplaceWith(left->InputAt(0));
1339       RecordSimplification();
1340       instruction->GetBlock()->RemoveInstruction(instruction);
1341       return;
1342     } else if (right->IsSub() && right->InputAt(1) == left) {
1343       instruction->ReplaceWith(right->InputAt(0));
1344       RecordSimplification();
1345       instruction->GetBlock()->RemoveInstruction(instruction);
1346       return;
1347     }
1348   }
1349 }
1350 
VisitAnd(HAnd * instruction)1351 void InstructionSimplifierVisitor::VisitAnd(HAnd* instruction) {
1352   DCHECK(DataType::IsIntegralType(instruction->GetType()));
1353   HConstant* input_cst = instruction->GetConstantRight();
1354   HInstruction* input_other = instruction->GetLeastConstantLeft();
1355 
1356   if (input_cst != nullptr) {
1357     int64_t value = Int64FromConstant(input_cst);
1358     if (value == -1 ||
1359         // Similar cases under zero extension.
1360         (DataType::IsUnsignedType(input_other->GetType()) &&
1361          ((DataType::MaxValueOfIntegralType(input_other->GetType()) & ~value) == 0))) {
1362       // Replace code looking like
1363       //    AND dst, src, 0xFFF...FF
1364       // with
1365       //    src
1366       instruction->ReplaceWith(input_other);
1367       instruction->GetBlock()->RemoveInstruction(instruction);
1368       RecordSimplification();
1369       return;
1370     }
1371     if (input_other->IsTypeConversion() &&
1372         input_other->GetType() == DataType::Type::kInt64 &&
1373         DataType::IsIntegralType(input_other->InputAt(0)->GetType()) &&
1374         IsInt<32>(value) &&
1375         input_other->HasOnlyOneNonEnvironmentUse()) {
1376       // The AND can be reordered before the TypeConversion. Replace
1377       //   LongConstant cst, <32-bit-constant-sign-extended-to-64-bits>
1378       //   TypeConversion<Int64> tmp, src
1379       //   AND dst, tmp, cst
1380       // with
1381       //   IntConstant cst, <32-bit-constant>
1382       //   AND tmp, src, cst
1383       //   TypeConversion<Int64> dst, tmp
1384       // This helps 32-bit targets and does not hurt 64-bit targets.
1385       // This also simplifies detection of other patterns, such as Uint8 loads.
1386       HInstruction* new_and_input = input_other->InputAt(0);
1387       // Implicit conversion Int64->Int64 would have been removed previously.
1388       DCHECK_NE(new_and_input->GetType(), DataType::Type::kInt64);
1389       HConstant* new_const = GetGraph()->GetConstant(DataType::Type::kInt32, value);
1390       HAnd* new_and =
1391           new (GetGraph()->GetAllocator()) HAnd(DataType::Type::kInt32, new_and_input, new_const);
1392       instruction->GetBlock()->InsertInstructionBefore(new_and, instruction);
1393       HTypeConversion* new_conversion =
1394           new (GetGraph()->GetAllocator()) HTypeConversion(DataType::Type::kInt64, new_and);
1395       instruction->GetBlock()->ReplaceAndRemoveInstructionWith(instruction, new_conversion);
1396       input_other->GetBlock()->RemoveInstruction(input_other);
1397       RecordSimplification();
1398       // Try to process the new And now, do not wait for the next round of simplifications.
1399       instruction = new_and;
1400       input_other = new_and_input;
1401     }
1402     // Eliminate And from UShr+And if the And-mask contains all the bits that
1403     // can be non-zero after UShr. Transform Shr+And to UShr if the And-mask
1404     // precisely clears the shifted-in sign bits.
1405     if ((input_other->IsUShr() || input_other->IsShr()) && input_other->InputAt(1)->IsConstant()) {
1406       size_t reg_bits = (instruction->GetResultType() == DataType::Type::kInt64) ? 64 : 32;
1407       size_t shift = Int64FromConstant(input_other->InputAt(1)->AsConstant()) & (reg_bits - 1);
1408       size_t num_tail_bits_set = CTZ(value + 1);
1409       if ((num_tail_bits_set >= reg_bits - shift) && input_other->IsUShr()) {
1410         // This AND clears only bits known to be clear, for example "(x >>> 24) & 0xff".
1411         instruction->ReplaceWith(input_other);
1412         instruction->GetBlock()->RemoveInstruction(instruction);
1413         RecordSimplification();
1414         return;
1415       }  else if ((num_tail_bits_set == reg_bits - shift) && IsPowerOfTwo(value + 1) &&
1416           input_other->HasOnlyOneNonEnvironmentUse()) {
1417         DCHECK(input_other->IsShr());  // For UShr, we would have taken the branch above.
1418         // Replace SHR+AND with USHR, for example "(x >> 24) & 0xff" -> "x >>> 24".
1419         HUShr* ushr = new (GetGraph()->GetAllocator()) HUShr(instruction->GetType(),
1420                                                              input_other->InputAt(0),
1421                                                              input_other->InputAt(1),
1422                                                              input_other->GetDexPc());
1423         instruction->GetBlock()->ReplaceAndRemoveInstructionWith(instruction, ushr);
1424         input_other->GetBlock()->RemoveInstruction(input_other);
1425         RecordSimplification();
1426         return;
1427       }
1428     }
1429     if ((value == 0xff || value == 0xffff) && instruction->GetType() != DataType::Type::kInt64) {
1430       // Transform AND to a type conversion to Uint8/Uint16. If `input_other` is a field
1431       // or array Get with only a single use, short-circuit the subsequent simplification
1432       // of the Get+TypeConversion and change the Get's type to `new_type` instead.
1433       DataType::Type new_type = (value == 0xff) ? DataType::Type::kUint8 : DataType::Type::kUint16;
1434       DataType::Type find_type = (value == 0xff) ? DataType::Type::kInt8 : DataType::Type::kInt16;
1435       if (input_other->GetType() == find_type &&
1436           input_other->HasOnlyOneNonEnvironmentUse() &&
1437           TryReplaceFieldOrArrayGetType(input_other, new_type)) {
1438         instruction->ReplaceWith(input_other);
1439         instruction->GetBlock()->RemoveInstruction(instruction);
1440       } else if (DataType::IsTypeConversionImplicit(input_other->GetType(), new_type)) {
1441         instruction->ReplaceWith(input_other);
1442         instruction->GetBlock()->RemoveInstruction(instruction);
1443       } else {
1444         HTypeConversion* type_conversion = new (GetGraph()->GetAllocator()) HTypeConversion(
1445             new_type, input_other, instruction->GetDexPc());
1446         instruction->GetBlock()->ReplaceAndRemoveInstructionWith(instruction, type_conversion);
1447       }
1448       RecordSimplification();
1449       return;
1450     }
1451   }
1452 
1453   // We assume that GVN has run before, so we only perform a pointer comparison.
1454   // If for some reason the values are equal but the pointers are different, we
1455   // are still correct and only miss an optimization opportunity.
1456   if (instruction->GetLeft() == instruction->GetRight()) {
1457     // Replace code looking like
1458     //    AND dst, src, src
1459     // with
1460     //    src
1461     instruction->ReplaceWith(instruction->GetLeft());
1462     instruction->GetBlock()->RemoveInstruction(instruction);
1463     RecordSimplification();
1464     return;
1465   }
1466 
1467   if (TryDeMorganNegationFactoring(instruction)) {
1468     return;
1469   }
1470 
1471   // TryHandleAssociativeAndCommutativeOperation() does not remove its input,
1472   // so no need to return.
1473   TryHandleAssociativeAndCommutativeOperation(instruction);
1474 }
1475 
VisitGreaterThan(HGreaterThan * condition)1476 void InstructionSimplifierVisitor::VisitGreaterThan(HGreaterThan* condition) {
1477   VisitCondition(condition);
1478 }
1479 
VisitGreaterThanOrEqual(HGreaterThanOrEqual * condition)1480 void InstructionSimplifierVisitor::VisitGreaterThanOrEqual(HGreaterThanOrEqual* condition) {
1481   VisitCondition(condition);
1482 }
1483 
VisitLessThan(HLessThan * condition)1484 void InstructionSimplifierVisitor::VisitLessThan(HLessThan* condition) {
1485   VisitCondition(condition);
1486 }
1487 
VisitLessThanOrEqual(HLessThanOrEqual * condition)1488 void InstructionSimplifierVisitor::VisitLessThanOrEqual(HLessThanOrEqual* condition) {
1489   VisitCondition(condition);
1490 }
1491 
VisitBelow(HBelow * condition)1492 void InstructionSimplifierVisitor::VisitBelow(HBelow* condition) {
1493   VisitCondition(condition);
1494 }
1495 
VisitBelowOrEqual(HBelowOrEqual * condition)1496 void InstructionSimplifierVisitor::VisitBelowOrEqual(HBelowOrEqual* condition) {
1497   VisitCondition(condition);
1498 }
1499 
VisitAbove(HAbove * condition)1500 void InstructionSimplifierVisitor::VisitAbove(HAbove* condition) {
1501   VisitCondition(condition);
1502 }
1503 
VisitAboveOrEqual(HAboveOrEqual * condition)1504 void InstructionSimplifierVisitor::VisitAboveOrEqual(HAboveOrEqual* condition) {
1505   VisitCondition(condition);
1506 }
1507 
1508 // Recognize the following pattern:
1509 // obj.getClass() ==/!= Foo.class
1510 // And replace it with a constant value if the type of `obj` is statically known.
RecognizeAndSimplifyClassCheck(HCondition * condition)1511 static bool RecognizeAndSimplifyClassCheck(HCondition* condition) {
1512   HInstruction* input_one = condition->InputAt(0);
1513   HInstruction* input_two = condition->InputAt(1);
1514   HLoadClass* load_class = input_one->IsLoadClass()
1515       ? input_one->AsLoadClass()
1516       : input_two->AsLoadClass();
1517   if (load_class == nullptr) {
1518     return false;
1519   }
1520 
1521   ReferenceTypeInfo class_rti = load_class->GetLoadedClassRTI();
1522   if (!class_rti.IsValid()) {
1523     // Unresolved class.
1524     return false;
1525   }
1526 
1527   HInstanceFieldGet* field_get = (load_class == input_one)
1528       ? input_two->AsInstanceFieldGet()
1529       : input_one->AsInstanceFieldGet();
1530   if (field_get == nullptr) {
1531     return false;
1532   }
1533 
1534   HInstruction* receiver = field_get->InputAt(0);
1535   ReferenceTypeInfo receiver_type = receiver->GetReferenceTypeInfo();
1536   if (!receiver_type.IsExact()) {
1537     return false;
1538   }
1539 
1540   {
1541     ScopedObjectAccess soa(Thread::Current());
1542     ArtField* field = GetClassRoot<mirror::Object>()->GetInstanceField(0);
1543     DCHECK_EQ(std::string(field->GetName()), "shadow$_klass_");
1544     if (field_get->GetFieldInfo().GetField() != field) {
1545       return false;
1546     }
1547 
1548     // We can replace the compare.
1549     int value = 0;
1550     if (receiver_type.IsEqual(class_rti)) {
1551       value = condition->IsEqual() ? 1 : 0;
1552     } else {
1553       value = condition->IsNotEqual() ? 1 : 0;
1554     }
1555     condition->ReplaceWith(condition->GetBlock()->GetGraph()->GetIntConstant(value));
1556     return true;
1557   }
1558 }
1559 
VisitCondition(HCondition * condition)1560 void InstructionSimplifierVisitor::VisitCondition(HCondition* condition) {
1561   if (condition->IsEqual() || condition->IsNotEqual()) {
1562     if (RecognizeAndSimplifyClassCheck(condition)) {
1563       return;
1564     }
1565   }
1566 
1567   // Reverse condition if left is constant. Our code generators prefer constant
1568   // on the right hand side.
1569   if (condition->GetLeft()->IsConstant() && !condition->GetRight()->IsConstant()) {
1570     HBasicBlock* block = condition->GetBlock();
1571     HCondition* replacement =
1572         GetOppositeConditionSwapOps(block->GetGraph()->GetAllocator(), condition);
1573     // If it is a fp we must set the opposite bias.
1574     if (replacement != nullptr) {
1575       if (condition->IsLtBias()) {
1576         replacement->SetBias(ComparisonBias::kGtBias);
1577       } else if (condition->IsGtBias()) {
1578         replacement->SetBias(ComparisonBias::kLtBias);
1579       }
1580       block->ReplaceAndRemoveInstructionWith(condition, replacement);
1581       RecordSimplification();
1582 
1583       condition = replacement;
1584     }
1585   }
1586 
1587   HInstruction* left = condition->GetLeft();
1588   HInstruction* right = condition->GetRight();
1589 
1590   // Try to fold an HCompare into this HCondition.
1591 
1592   // We can only replace an HCondition which compares a Compare to 0.
1593   // Both 'dx' and 'jack' generate a compare to 0 when compiling a
1594   // condition with a long, float or double comparison as input.
1595   if (!left->IsCompare() || !right->IsConstant() || right->AsIntConstant()->GetValue() != 0) {
1596     // Conversion is not possible.
1597     return;
1598   }
1599 
1600   // Is the Compare only used for this purpose?
1601   if (!left->GetUses().HasExactlyOneElement()) {
1602     // Someone else also wants the result of the compare.
1603     return;
1604   }
1605 
1606   if (!left->GetEnvUses().empty()) {
1607     // There is a reference to the compare result in an environment. Do we really need it?
1608     if (GetGraph()->IsDebuggable()) {
1609       return;
1610     }
1611 
1612     // We have to ensure that there are no deopt points in the sequence.
1613     if (left->HasAnyEnvironmentUseBefore(condition)) {
1614       return;
1615     }
1616   }
1617 
1618   // Clean up any environment uses from the HCompare, if any.
1619   left->RemoveEnvironmentUsers();
1620 
1621   // We have decided to fold the HCompare into the HCondition. Transfer the information.
1622   condition->SetBias(left->AsCompare()->GetBias());
1623 
1624   // Replace the operands of the HCondition.
1625   condition->ReplaceInput(left->InputAt(0), 0);
1626   condition->ReplaceInput(left->InputAt(1), 1);
1627 
1628   // Remove the HCompare.
1629   left->GetBlock()->RemoveInstruction(left);
1630 
1631   RecordSimplification();
1632 }
1633 
1634 // Return whether x / divisor == x * (1.0f / divisor), for every float x.
CanDivideByReciprocalMultiplyFloat(int32_t divisor)1635 static constexpr bool CanDivideByReciprocalMultiplyFloat(int32_t divisor) {
1636   // True, if the most significant bits of divisor are 0.
1637   return ((divisor & 0x7fffff) == 0);
1638 }
1639 
1640 // Return whether x / divisor == x * (1.0 / divisor), for every double x.
CanDivideByReciprocalMultiplyDouble(int64_t divisor)1641 static constexpr bool CanDivideByReciprocalMultiplyDouble(int64_t divisor) {
1642   // True, if the most significant bits of divisor are 0.
1643   return ((divisor & ((UINT64_C(1) << 52) - 1)) == 0);
1644 }
1645 
VisitDiv(HDiv * instruction)1646 void InstructionSimplifierVisitor::VisitDiv(HDiv* instruction) {
1647   HConstant* input_cst = instruction->GetConstantRight();
1648   HInstruction* input_other = instruction->GetLeastConstantLeft();
1649   DataType::Type type = instruction->GetType();
1650 
1651   if ((input_cst != nullptr) && input_cst->IsOne()) {
1652     // Replace code looking like
1653     //    DIV dst, src, 1
1654     // with
1655     //    src
1656     instruction->ReplaceWith(input_other);
1657     instruction->GetBlock()->RemoveInstruction(instruction);
1658     RecordSimplification();
1659     return;
1660   }
1661 
1662   if ((input_cst != nullptr) && input_cst->IsMinusOne()) {
1663     // Replace code looking like
1664     //    DIV dst, src, -1
1665     // with
1666     //    NEG dst, src
1667     instruction->GetBlock()->ReplaceAndRemoveInstructionWith(
1668         instruction, new (GetGraph()->GetAllocator()) HNeg(type, input_other));
1669     RecordSimplification();
1670     return;
1671   }
1672 
1673   if ((input_cst != nullptr) && DataType::IsFloatingPointType(type)) {
1674     // Try replacing code looking like
1675     //    DIV dst, src, constant
1676     // with
1677     //    MUL dst, src, 1 / constant
1678     HConstant* reciprocal = nullptr;
1679     if (type == DataType::Type::kFloat64) {
1680       double value = input_cst->AsDoubleConstant()->GetValue();
1681       if (CanDivideByReciprocalMultiplyDouble(bit_cast<int64_t, double>(value))) {
1682         reciprocal = GetGraph()->GetDoubleConstant(1.0 / value);
1683       }
1684     } else {
1685       DCHECK_EQ(type, DataType::Type::kFloat32);
1686       float value = input_cst->AsFloatConstant()->GetValue();
1687       if (CanDivideByReciprocalMultiplyFloat(bit_cast<int32_t, float>(value))) {
1688         reciprocal = GetGraph()->GetFloatConstant(1.0f / value);
1689       }
1690     }
1691 
1692     if (reciprocal != nullptr) {
1693       instruction->GetBlock()->ReplaceAndRemoveInstructionWith(
1694           instruction, new (GetGraph()->GetAllocator()) HMul(type, input_other, reciprocal));
1695       RecordSimplification();
1696       return;
1697     }
1698   }
1699 }
1700 
VisitMul(HMul * instruction)1701 void InstructionSimplifierVisitor::VisitMul(HMul* instruction) {
1702   HConstant* input_cst = instruction->GetConstantRight();
1703   HInstruction* input_other = instruction->GetLeastConstantLeft();
1704   DataType::Type type = instruction->GetType();
1705   HBasicBlock* block = instruction->GetBlock();
1706   ArenaAllocator* allocator = GetGraph()->GetAllocator();
1707 
1708   if (input_cst == nullptr) {
1709     return;
1710   }
1711 
1712   if (input_cst->IsOne()) {
1713     // Replace code looking like
1714     //    MUL dst, src, 1
1715     // with
1716     //    src
1717     instruction->ReplaceWith(input_other);
1718     instruction->GetBlock()->RemoveInstruction(instruction);
1719     RecordSimplification();
1720     return;
1721   }
1722 
1723   if (input_cst->IsMinusOne() &&
1724       (DataType::IsFloatingPointType(type) || DataType::IsIntOrLongType(type))) {
1725     // Replace code looking like
1726     //    MUL dst, src, -1
1727     // with
1728     //    NEG dst, src
1729     HNeg* neg = new (allocator) HNeg(type, input_other);
1730     block->ReplaceAndRemoveInstructionWith(instruction, neg);
1731     RecordSimplification();
1732     return;
1733   }
1734 
1735   if (DataType::IsFloatingPointType(type) &&
1736       ((input_cst->IsFloatConstant() && input_cst->AsFloatConstant()->GetValue() == 2.0f) ||
1737        (input_cst->IsDoubleConstant() && input_cst->AsDoubleConstant()->GetValue() == 2.0))) {
1738     // Replace code looking like
1739     //    FP_MUL dst, src, 2.0
1740     // with
1741     //    FP_ADD dst, src, src
1742     // The 'int' and 'long' cases are handled below.
1743     block->ReplaceAndRemoveInstructionWith(instruction,
1744                                            new (allocator) HAdd(type, input_other, input_other));
1745     RecordSimplification();
1746     return;
1747   }
1748 
1749   if (DataType::IsIntOrLongType(type)) {
1750     int64_t factor = Int64FromConstant(input_cst);
1751     // Even though constant propagation also takes care of the zero case, other
1752     // optimizations can lead to having a zero multiplication.
1753     if (factor == 0) {
1754       // Replace code looking like
1755       //    MUL dst, src, 0
1756       // with
1757       //    0
1758       instruction->ReplaceWith(input_cst);
1759       instruction->GetBlock()->RemoveInstruction(instruction);
1760       RecordSimplification();
1761       return;
1762     } else if (IsPowerOfTwo(factor)) {
1763       // Replace code looking like
1764       //    MUL dst, src, pow_of_2
1765       // with
1766       //    SHL dst, src, log2(pow_of_2)
1767       HIntConstant* shift = GetGraph()->GetIntConstant(WhichPowerOf2(factor));
1768       HShl* shl = new (allocator) HShl(type, input_other, shift);
1769       block->ReplaceAndRemoveInstructionWith(instruction, shl);
1770       RecordSimplification();
1771       return;
1772     } else if (IsPowerOfTwo(factor - 1)) {
1773       // Transform code looking like
1774       //    MUL dst, src, (2^n + 1)
1775       // into
1776       //    SHL tmp, src, n
1777       //    ADD dst, src, tmp
1778       HShl* shl = new (allocator) HShl(type,
1779                                        input_other,
1780                                        GetGraph()->GetIntConstant(WhichPowerOf2(factor - 1)));
1781       HAdd* add = new (allocator) HAdd(type, input_other, shl);
1782 
1783       block->InsertInstructionBefore(shl, instruction);
1784       block->ReplaceAndRemoveInstructionWith(instruction, add);
1785       RecordSimplification();
1786       return;
1787     } else if (IsPowerOfTwo(factor + 1)) {
1788       // Transform code looking like
1789       //    MUL dst, src, (2^n - 1)
1790       // into
1791       //    SHL tmp, src, n
1792       //    SUB dst, tmp, src
1793       HShl* shl = new (allocator) HShl(type,
1794                                        input_other,
1795                                        GetGraph()->GetIntConstant(WhichPowerOf2(factor + 1)));
1796       HSub* sub = new (allocator) HSub(type, shl, input_other);
1797 
1798       block->InsertInstructionBefore(shl, instruction);
1799       block->ReplaceAndRemoveInstructionWith(instruction, sub);
1800       RecordSimplification();
1801       return;
1802     }
1803   }
1804 
1805   // TryHandleAssociativeAndCommutativeOperation() does not remove its input,
1806   // so no need to return.
1807   TryHandleAssociativeAndCommutativeOperation(instruction);
1808 }
1809 
VisitNeg(HNeg * instruction)1810 void InstructionSimplifierVisitor::VisitNeg(HNeg* instruction) {
1811   HInstruction* input = instruction->GetInput();
1812   if (input->IsNeg()) {
1813     // Replace code looking like
1814     //    NEG tmp, src
1815     //    NEG dst, tmp
1816     // with
1817     //    src
1818     HNeg* previous_neg = input->AsNeg();
1819     instruction->ReplaceWith(previous_neg->GetInput());
1820     instruction->GetBlock()->RemoveInstruction(instruction);
1821     // We perform the optimization even if the input negation has environment
1822     // uses since it allows removing the current instruction. But we only delete
1823     // the input negation only if it is does not have any uses left.
1824     if (!previous_neg->HasUses()) {
1825       previous_neg->GetBlock()->RemoveInstruction(previous_neg);
1826     }
1827     RecordSimplification();
1828     return;
1829   }
1830 
1831   if (input->IsSub() && input->HasOnlyOneNonEnvironmentUse() &&
1832       !DataType::IsFloatingPointType(input->GetType())) {
1833     // Replace code looking like
1834     //    SUB tmp, a, b
1835     //    NEG dst, tmp
1836     // with
1837     //    SUB dst, b, a
1838     // We do not perform the optimization if the input subtraction has
1839     // environment uses or multiple non-environment uses as it could lead to
1840     // worse code. In particular, we do not want the live ranges of `a` and `b`
1841     // to be extended if we are not sure the initial 'SUB' instruction can be
1842     // removed.
1843     // We do not perform optimization for fp because we could lose the sign of zero.
1844     HSub* sub = input->AsSub();
1845     HSub* new_sub = new (GetGraph()->GetAllocator()) HSub(
1846         instruction->GetType(), sub->GetRight(), sub->GetLeft());
1847     instruction->GetBlock()->ReplaceAndRemoveInstructionWith(instruction, new_sub);
1848     if (!sub->HasUses()) {
1849       sub->GetBlock()->RemoveInstruction(sub);
1850     }
1851     RecordSimplification();
1852   }
1853 }
1854 
VisitNot(HNot * instruction)1855 void InstructionSimplifierVisitor::VisitNot(HNot* instruction) {
1856   HInstruction* input = instruction->GetInput();
1857   if (input->IsNot()) {
1858     // Replace code looking like
1859     //    NOT tmp, src
1860     //    NOT dst, tmp
1861     // with
1862     //    src
1863     // We perform the optimization even if the input negation has environment
1864     // uses since it allows removing the current instruction. But we only delete
1865     // the input negation only if it is does not have any uses left.
1866     HNot* previous_not = input->AsNot();
1867     instruction->ReplaceWith(previous_not->GetInput());
1868     instruction->GetBlock()->RemoveInstruction(instruction);
1869     if (!previous_not->HasUses()) {
1870       previous_not->GetBlock()->RemoveInstruction(previous_not);
1871     }
1872     RecordSimplification();
1873   }
1874 }
1875 
VisitOr(HOr * instruction)1876 void InstructionSimplifierVisitor::VisitOr(HOr* instruction) {
1877   HConstant* input_cst = instruction->GetConstantRight();
1878   HInstruction* input_other = instruction->GetLeastConstantLeft();
1879 
1880   if ((input_cst != nullptr) && input_cst->IsZeroBitPattern()) {
1881     // Replace code looking like
1882     //    OR dst, src, 0
1883     // with
1884     //    src
1885     instruction->ReplaceWith(input_other);
1886     instruction->GetBlock()->RemoveInstruction(instruction);
1887     RecordSimplification();
1888     return;
1889   }
1890 
1891   // We assume that GVN has run before, so we only perform a pointer comparison.
1892   // If for some reason the values are equal but the pointers are different, we
1893   // are still correct and only miss an optimization opportunity.
1894   if (instruction->GetLeft() == instruction->GetRight()) {
1895     // Replace code looking like
1896     //    OR dst, src, src
1897     // with
1898     //    src
1899     instruction->ReplaceWith(instruction->GetLeft());
1900     instruction->GetBlock()->RemoveInstruction(instruction);
1901     RecordSimplification();
1902     return;
1903   }
1904 
1905   if (TryDeMorganNegationFactoring(instruction)) return;
1906 
1907   if (TryReplaceWithRotate(instruction)) {
1908     return;
1909   }
1910 
1911   // TryHandleAssociativeAndCommutativeOperation() does not remove its input,
1912   // so no need to return.
1913   TryHandleAssociativeAndCommutativeOperation(instruction);
1914 }
1915 
VisitShl(HShl * instruction)1916 void InstructionSimplifierVisitor::VisitShl(HShl* instruction) {
1917   VisitShift(instruction);
1918 }
1919 
VisitShr(HShr * instruction)1920 void InstructionSimplifierVisitor::VisitShr(HShr* instruction) {
1921   VisitShift(instruction);
1922 }
1923 
VisitSub(HSub * instruction)1924 void InstructionSimplifierVisitor::VisitSub(HSub* instruction) {
1925   HConstant* input_cst = instruction->GetConstantRight();
1926   HInstruction* input_other = instruction->GetLeastConstantLeft();
1927 
1928   DataType::Type type = instruction->GetType();
1929   if (DataType::IsFloatingPointType(type)) {
1930     return;
1931   }
1932 
1933   if ((input_cst != nullptr) && input_cst->IsArithmeticZero()) {
1934     // Replace code looking like
1935     //    SUB dst, src, 0
1936     // with
1937     //    src
1938     // Note that we cannot optimize `x - 0.0` to `x` for floating-point. When
1939     // `x` is `-0.0`, the former expression yields `0.0`, while the later
1940     // yields `-0.0`.
1941     instruction->ReplaceWith(input_other);
1942     instruction->GetBlock()->RemoveInstruction(instruction);
1943     RecordSimplification();
1944     return;
1945   }
1946 
1947   HBasicBlock* block = instruction->GetBlock();
1948   ArenaAllocator* allocator = GetGraph()->GetAllocator();
1949 
1950   HInstruction* left = instruction->GetLeft();
1951   HInstruction* right = instruction->GetRight();
1952   if (left->IsConstant()) {
1953     if (Int64FromConstant(left->AsConstant()) == 0) {
1954       // Replace code looking like
1955       //    SUB dst, 0, src
1956       // with
1957       //    NEG dst, src
1958       // Note that we cannot optimize `0.0 - x` to `-x` for floating-point. When
1959       // `x` is `0.0`, the former expression yields `0.0`, while the later
1960       // yields `-0.0`.
1961       HNeg* neg = new (allocator) HNeg(type, right);
1962       block->ReplaceAndRemoveInstructionWith(instruction, neg);
1963       RecordSimplification();
1964       return;
1965     }
1966   }
1967 
1968   if (left->IsNeg() && right->IsNeg()) {
1969     if (TryMoveNegOnInputsAfterBinop(instruction)) {
1970       return;
1971     }
1972   }
1973 
1974   if (right->IsNeg() && right->HasOnlyOneNonEnvironmentUse()) {
1975     // Replace code looking like
1976     //    NEG tmp, b
1977     //    SUB dst, a, tmp
1978     // with
1979     //    ADD dst, a, b
1980     HAdd* add = new(GetGraph()->GetAllocator()) HAdd(type, left, right->AsNeg()->GetInput());
1981     instruction->GetBlock()->ReplaceAndRemoveInstructionWith(instruction, add);
1982     RecordSimplification();
1983     right->GetBlock()->RemoveInstruction(right);
1984     return;
1985   }
1986 
1987   if (left->IsNeg() && left->HasOnlyOneNonEnvironmentUse()) {
1988     // Replace code looking like
1989     //    NEG tmp, a
1990     //    SUB dst, tmp, b
1991     // with
1992     //    ADD tmp, a, b
1993     //    NEG dst, tmp
1994     // The second version is not intrinsically better, but enables more
1995     // transformations.
1996     HAdd* add = new(GetGraph()->GetAllocator()) HAdd(type, left->AsNeg()->GetInput(), right);
1997     instruction->GetBlock()->InsertInstructionBefore(add, instruction);
1998     HNeg* neg = new (GetGraph()->GetAllocator()) HNeg(instruction->GetType(), add);
1999     instruction->GetBlock()->InsertInstructionBefore(neg, instruction);
2000     instruction->ReplaceWith(neg);
2001     instruction->GetBlock()->RemoveInstruction(instruction);
2002     RecordSimplification();
2003     left->GetBlock()->RemoveInstruction(left);
2004     return;
2005   }
2006 
2007   if (TrySubtractionChainSimplification(instruction)) {
2008     return;
2009   }
2010 
2011   if (left->IsAdd()) {
2012     // Replace code patterns looking like
2013     //    ADD dst1, x, y        ADD dst1, x, y
2014     //    SUB dst2, dst1, y     SUB dst2, dst1, x
2015     // with
2016     //    ADD dst1, x, y
2017     // SUB instruction is not needed in this case, we may use
2018     // one of inputs of ADD instead.
2019     // It is applicable to integral types only.
2020     DCHECK(DataType::IsIntegralType(type));
2021     if (left->InputAt(1) == right) {
2022       instruction->ReplaceWith(left->InputAt(0));
2023       RecordSimplification();
2024       instruction->GetBlock()->RemoveInstruction(instruction);
2025       return;
2026     } else if (left->InputAt(0) == right) {
2027       instruction->ReplaceWith(left->InputAt(1));
2028       RecordSimplification();
2029       instruction->GetBlock()->RemoveInstruction(instruction);
2030       return;
2031     }
2032   }
2033 }
2034 
VisitUShr(HUShr * instruction)2035 void InstructionSimplifierVisitor::VisitUShr(HUShr* instruction) {
2036   VisitShift(instruction);
2037 }
2038 
VisitXor(HXor * instruction)2039 void InstructionSimplifierVisitor::VisitXor(HXor* instruction) {
2040   HConstant* input_cst = instruction->GetConstantRight();
2041   HInstruction* input_other = instruction->GetLeastConstantLeft();
2042 
2043   if ((input_cst != nullptr) && input_cst->IsZeroBitPattern()) {
2044     // Replace code looking like
2045     //    XOR dst, src, 0
2046     // with
2047     //    src
2048     instruction->ReplaceWith(input_other);
2049     instruction->GetBlock()->RemoveInstruction(instruction);
2050     RecordSimplification();
2051     return;
2052   }
2053 
2054   if ((input_cst != nullptr) && input_cst->IsOne()
2055       && input_other->GetType() == DataType::Type::kBool) {
2056     // Replace code looking like
2057     //    XOR dst, src, 1
2058     // with
2059     //    BOOLEAN_NOT dst, src
2060     HBooleanNot* boolean_not = new (GetGraph()->GetAllocator()) HBooleanNot(input_other);
2061     instruction->GetBlock()->ReplaceAndRemoveInstructionWith(instruction, boolean_not);
2062     RecordSimplification();
2063     return;
2064   }
2065 
2066   if ((input_cst != nullptr) && AreAllBitsSet(input_cst)) {
2067     // Replace code looking like
2068     //    XOR dst, src, 0xFFF...FF
2069     // with
2070     //    NOT dst, src
2071     HNot* bitwise_not = new (GetGraph()->GetAllocator()) HNot(instruction->GetType(), input_other);
2072     instruction->GetBlock()->ReplaceAndRemoveInstructionWith(instruction, bitwise_not);
2073     RecordSimplification();
2074     return;
2075   }
2076 
2077   HInstruction* left = instruction->GetLeft();
2078   HInstruction* right = instruction->GetRight();
2079   if (((left->IsNot() && right->IsNot()) ||
2080        (left->IsBooleanNot() && right->IsBooleanNot())) &&
2081       left->HasOnlyOneNonEnvironmentUse() &&
2082       right->HasOnlyOneNonEnvironmentUse()) {
2083     // Replace code looking like
2084     //    NOT nota, a
2085     //    NOT notb, b
2086     //    XOR dst, nota, notb
2087     // with
2088     //    XOR dst, a, b
2089     instruction->ReplaceInput(left->InputAt(0), 0);
2090     instruction->ReplaceInput(right->InputAt(0), 1);
2091     left->GetBlock()->RemoveInstruction(left);
2092     right->GetBlock()->RemoveInstruction(right);
2093     RecordSimplification();
2094     return;
2095   }
2096 
2097   if (TryReplaceWithRotate(instruction)) {
2098     return;
2099   }
2100 
2101   // TryHandleAssociativeAndCommutativeOperation() does not remove its input,
2102   // so no need to return.
2103   TryHandleAssociativeAndCommutativeOperation(instruction);
2104 }
2105 
SimplifyStringEquals(HInvoke * instruction)2106 void InstructionSimplifierVisitor::SimplifyStringEquals(HInvoke* instruction) {
2107   HInstruction* argument = instruction->InputAt(1);
2108   HInstruction* receiver = instruction->InputAt(0);
2109   if (receiver == argument) {
2110     // Because String.equals is an instance call, the receiver is
2111     // a null check if we don't know it's null. The argument however, will
2112     // be the actual object. So we cannot end up in a situation where both
2113     // are equal but could be null.
2114     DCHECK(CanEnsureNotNullAt(argument, instruction));
2115     instruction->ReplaceWith(GetGraph()->GetIntConstant(1));
2116     instruction->GetBlock()->RemoveInstruction(instruction);
2117   } else {
2118     StringEqualsOptimizations optimizations(instruction);
2119     if (CanEnsureNotNullAt(argument, instruction)) {
2120       optimizations.SetArgumentNotNull();
2121     }
2122     ScopedObjectAccess soa(Thread::Current());
2123     ReferenceTypeInfo argument_rti = argument->GetReferenceTypeInfo();
2124     if (argument_rti.IsValid() && argument_rti.IsStringClass()) {
2125       optimizations.SetArgumentIsString();
2126     }
2127   }
2128 }
2129 
SimplifyRotate(HInvoke * invoke,bool is_left,DataType::Type type)2130 void InstructionSimplifierVisitor::SimplifyRotate(HInvoke* invoke,
2131                                                   bool is_left,
2132                                                   DataType::Type type) {
2133   DCHECK(invoke->IsInvokeStaticOrDirect());
2134   DCHECK_EQ(invoke->GetInvokeType(), InvokeType::kStatic);
2135   HInstruction* value = invoke->InputAt(0);
2136   HInstruction* distance = invoke->InputAt(1);
2137   // Replace the invoke with an HRor.
2138   if (is_left) {
2139     // Unconditionally set the type of the negated distance to `int`,
2140     // as shift and rotate operations expect a 32-bit (or narrower)
2141     // value for their distance input.
2142     distance = new (GetGraph()->GetAllocator()) HNeg(DataType::Type::kInt32, distance);
2143     invoke->GetBlock()->InsertInstructionBefore(distance, invoke);
2144   }
2145   HRor* ror = new (GetGraph()->GetAllocator()) HRor(type, value, distance);
2146   invoke->GetBlock()->ReplaceAndRemoveInstructionWith(invoke, ror);
2147   // Remove ClinitCheck and LoadClass, if possible.
2148   HInstruction* clinit = invoke->GetInputs().back();
2149   if (clinit->IsClinitCheck() && !clinit->HasUses()) {
2150     clinit->GetBlock()->RemoveInstruction(clinit);
2151     HInstruction* ldclass = clinit->InputAt(0);
2152     if (ldclass->IsLoadClass() && !ldclass->HasUses()) {
2153       ldclass->GetBlock()->RemoveInstruction(ldclass);
2154     }
2155   }
2156 }
2157 
IsArrayLengthOf(HInstruction * potential_length,HInstruction * potential_array)2158 static bool IsArrayLengthOf(HInstruction* potential_length, HInstruction* potential_array) {
2159   if (potential_length->IsArrayLength()) {
2160     return potential_length->InputAt(0) == potential_array;
2161   }
2162 
2163   if (potential_array->IsNewArray()) {
2164     return potential_array->AsNewArray()->GetLength() == potential_length;
2165   }
2166 
2167   return false;
2168 }
2169 
SimplifySystemArrayCopy(HInvoke * instruction)2170 void InstructionSimplifierVisitor::SimplifySystemArrayCopy(HInvoke* instruction) {
2171   HInstruction* source = instruction->InputAt(0);
2172   HInstruction* destination = instruction->InputAt(2);
2173   HInstruction* count = instruction->InputAt(4);
2174   SystemArrayCopyOptimizations optimizations(instruction);
2175   if (CanEnsureNotNullAt(source, instruction)) {
2176     optimizations.SetSourceIsNotNull();
2177   }
2178   if (CanEnsureNotNullAt(destination, instruction)) {
2179     optimizations.SetDestinationIsNotNull();
2180   }
2181   if (destination == source) {
2182     optimizations.SetDestinationIsSource();
2183   }
2184 
2185   if (IsArrayLengthOf(count, source)) {
2186     optimizations.SetCountIsSourceLength();
2187   }
2188 
2189   if (IsArrayLengthOf(count, destination)) {
2190     optimizations.SetCountIsDestinationLength();
2191   }
2192 
2193   {
2194     ScopedObjectAccess soa(Thread::Current());
2195     DataType::Type source_component_type = DataType::Type::kVoid;
2196     DataType::Type destination_component_type = DataType::Type::kVoid;
2197     ReferenceTypeInfo destination_rti = destination->GetReferenceTypeInfo();
2198     if (destination_rti.IsValid()) {
2199       if (destination_rti.IsObjectArray()) {
2200         if (destination_rti.IsExact()) {
2201           optimizations.SetDoesNotNeedTypeCheck();
2202         }
2203         optimizations.SetDestinationIsTypedObjectArray();
2204       }
2205       if (destination_rti.IsPrimitiveArrayClass()) {
2206         destination_component_type = DataTypeFromPrimitive(
2207             destination_rti.GetTypeHandle()->GetComponentType()->GetPrimitiveType());
2208         optimizations.SetDestinationIsPrimitiveArray();
2209       } else if (destination_rti.IsNonPrimitiveArrayClass()) {
2210         optimizations.SetDestinationIsNonPrimitiveArray();
2211       }
2212     }
2213     ReferenceTypeInfo source_rti = source->GetReferenceTypeInfo();
2214     if (source_rti.IsValid()) {
2215       if (destination_rti.IsValid() && destination_rti.CanArrayHoldValuesOf(source_rti)) {
2216         optimizations.SetDoesNotNeedTypeCheck();
2217       }
2218       if (source_rti.IsPrimitiveArrayClass()) {
2219         optimizations.SetSourceIsPrimitiveArray();
2220         source_component_type = DataTypeFromPrimitive(
2221             source_rti.GetTypeHandle()->GetComponentType()->GetPrimitiveType());
2222       } else if (source_rti.IsNonPrimitiveArrayClass()) {
2223         optimizations.SetSourceIsNonPrimitiveArray();
2224       }
2225     }
2226     // For primitive arrays, use their optimized ArtMethod implementations.
2227     if ((source_component_type != DataType::Type::kVoid) &&
2228         (source_component_type == destination_component_type)) {
2229       ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
2230       PointerSize image_size = class_linker->GetImagePointerSize();
2231       HInvokeStaticOrDirect* invoke = instruction->AsInvokeStaticOrDirect();
2232       ObjPtr<mirror::Class> system = invoke->GetResolvedMethod()->GetDeclaringClass();
2233       ArtMethod* method = nullptr;
2234       switch (source_component_type) {
2235         case DataType::Type::kBool:
2236           method = system->FindClassMethod("arraycopy", "([ZI[ZII)V", image_size);
2237           break;
2238         case DataType::Type::kInt8:
2239           method = system->FindClassMethod("arraycopy", "([BI[BII)V", image_size);
2240           break;
2241         case DataType::Type::kUint16:
2242           method = system->FindClassMethod("arraycopy", "([CI[CII)V", image_size);
2243           break;
2244         case DataType::Type::kInt16:
2245           method = system->FindClassMethod("arraycopy", "([SI[SII)V", image_size);
2246           break;
2247         case DataType::Type::kInt32:
2248           method = system->FindClassMethod("arraycopy", "([II[III)V", image_size);
2249           break;
2250         case DataType::Type::kFloat32:
2251           method = system->FindClassMethod("arraycopy", "([FI[FII)V", image_size);
2252           break;
2253         case DataType::Type::kInt64:
2254           method = system->FindClassMethod("arraycopy", "([JI[JII)V", image_size);
2255           break;
2256         case DataType::Type::kFloat64:
2257           method = system->FindClassMethod("arraycopy", "([DI[DII)V", image_size);
2258           break;
2259         default:
2260           LOG(FATAL) << "Unreachable";
2261       }
2262       DCHECK(method != nullptr);
2263       DCHECK(method->IsStatic());
2264       DCHECK(method->GetDeclaringClass() == system);
2265       invoke->SetResolvedMethod(method);
2266       // Sharpen the new invoke. Note that we do not update the dex method index of
2267       // the invoke, as we would need to look it up in the current dex file, and it
2268       // is unlikely that it exists. The most usual situation for such typed
2269       // arraycopy methods is a direct pointer to the boot image.
2270       invoke->SetDispatchInfo(HSharpening::SharpenInvokeStaticOrDirect(method, codegen_));
2271     }
2272   }
2273 }
2274 
SimplifyCompare(HInvoke * invoke,bool is_signum,DataType::Type type)2275 void InstructionSimplifierVisitor::SimplifyCompare(HInvoke* invoke,
2276                                                    bool is_signum,
2277                                                    DataType::Type type) {
2278   DCHECK(invoke->IsInvokeStaticOrDirect());
2279   uint32_t dex_pc = invoke->GetDexPc();
2280   HInstruction* left = invoke->InputAt(0);
2281   HInstruction* right;
2282   if (!is_signum) {
2283     right = invoke->InputAt(1);
2284   } else if (type == DataType::Type::kInt64) {
2285     right = GetGraph()->GetLongConstant(0);
2286   } else {
2287     right = GetGraph()->GetIntConstant(0);
2288   }
2289   HCompare* compare = new (GetGraph()->GetAllocator())
2290       HCompare(type, left, right, ComparisonBias::kNoBias, dex_pc);
2291   invoke->GetBlock()->ReplaceAndRemoveInstructionWith(invoke, compare);
2292 }
2293 
SimplifyIsNaN(HInvoke * invoke)2294 void InstructionSimplifierVisitor::SimplifyIsNaN(HInvoke* invoke) {
2295   DCHECK(invoke->IsInvokeStaticOrDirect());
2296   uint32_t dex_pc = invoke->GetDexPc();
2297   // IsNaN(x) is the same as x != x.
2298   HInstruction* x = invoke->InputAt(0);
2299   HCondition* condition = new (GetGraph()->GetAllocator()) HNotEqual(x, x, dex_pc);
2300   condition->SetBias(ComparisonBias::kLtBias);
2301   invoke->GetBlock()->ReplaceAndRemoveInstructionWith(invoke, condition);
2302 }
2303 
SimplifyFP2Int(HInvoke * invoke)2304 void InstructionSimplifierVisitor::SimplifyFP2Int(HInvoke* invoke) {
2305   DCHECK(invoke->IsInvokeStaticOrDirect());
2306   uint32_t dex_pc = invoke->GetDexPc();
2307   HInstruction* x = invoke->InputAt(0);
2308   DataType::Type type = x->GetType();
2309   // Set proper bit pattern for NaN and replace intrinsic with raw version.
2310   HInstruction* nan;
2311   if (type == DataType::Type::kFloat64) {
2312     nan = GetGraph()->GetLongConstant(0x7ff8000000000000L);
2313     invoke->SetIntrinsic(Intrinsics::kDoubleDoubleToRawLongBits,
2314                          kNeedsEnvironmentOrCache,
2315                          kNoSideEffects,
2316                          kNoThrow);
2317   } else {
2318     DCHECK_EQ(type, DataType::Type::kFloat32);
2319     nan = GetGraph()->GetIntConstant(0x7fc00000);
2320     invoke->SetIntrinsic(Intrinsics::kFloatFloatToRawIntBits,
2321                          kNeedsEnvironmentOrCache,
2322                          kNoSideEffects,
2323                          kNoThrow);
2324   }
2325   // Test IsNaN(x), which is the same as x != x.
2326   HCondition* condition = new (GetGraph()->GetAllocator()) HNotEqual(x, x, dex_pc);
2327   condition->SetBias(ComparisonBias::kLtBias);
2328   invoke->GetBlock()->InsertInstructionBefore(condition, invoke->GetNext());
2329   // Select between the two.
2330   HInstruction* select = new (GetGraph()->GetAllocator()) HSelect(condition, nan, invoke, dex_pc);
2331   invoke->GetBlock()->InsertInstructionBefore(select, condition->GetNext());
2332   invoke->ReplaceWithExceptInReplacementAtIndex(select, 0);  // false at index 0
2333 }
2334 
SimplifyStringCharAt(HInvoke * invoke)2335 void InstructionSimplifierVisitor::SimplifyStringCharAt(HInvoke* invoke) {
2336   HInstruction* str = invoke->InputAt(0);
2337   HInstruction* index = invoke->InputAt(1);
2338   uint32_t dex_pc = invoke->GetDexPc();
2339   ArenaAllocator* allocator = GetGraph()->GetAllocator();
2340   // We treat String as an array to allow DCE and BCE to seamlessly work on strings,
2341   // so create the HArrayLength, HBoundsCheck and HArrayGet.
2342   HArrayLength* length = new (allocator) HArrayLength(str, dex_pc, /* is_string_length= */ true);
2343   invoke->GetBlock()->InsertInstructionBefore(length, invoke);
2344   HBoundsCheck* bounds_check = new (allocator) HBoundsCheck(
2345       index, length, dex_pc, /* is_string_char_at= */ true);
2346   invoke->GetBlock()->InsertInstructionBefore(bounds_check, invoke);
2347   HArrayGet* array_get = new (allocator) HArrayGet(str,
2348                                                    bounds_check,
2349                                                    DataType::Type::kUint16,
2350                                                    SideEffects::None(),  // Strings are immutable.
2351                                                    dex_pc,
2352                                                    /* is_string_char_at= */ true);
2353   invoke->GetBlock()->ReplaceAndRemoveInstructionWith(invoke, array_get);
2354   bounds_check->CopyEnvironmentFrom(invoke->GetEnvironment());
2355   GetGraph()->SetHasBoundsChecks(true);
2356 }
2357 
SimplifyStringIsEmptyOrLength(HInvoke * invoke)2358 void InstructionSimplifierVisitor::SimplifyStringIsEmptyOrLength(HInvoke* invoke) {
2359   HInstruction* str = invoke->InputAt(0);
2360   uint32_t dex_pc = invoke->GetDexPc();
2361   // We treat String as an array to allow DCE and BCE to seamlessly work on strings,
2362   // so create the HArrayLength.
2363   HArrayLength* length =
2364       new (GetGraph()->GetAllocator()) HArrayLength(str, dex_pc, /* is_string_length= */ true);
2365   HInstruction* replacement;
2366   if (invoke->GetIntrinsic() == Intrinsics::kStringIsEmpty) {
2367     // For String.isEmpty(), create the `HEqual` representing the `length == 0`.
2368     invoke->GetBlock()->InsertInstructionBefore(length, invoke);
2369     HIntConstant* zero = GetGraph()->GetIntConstant(0);
2370     HEqual* equal = new (GetGraph()->GetAllocator()) HEqual(length, zero, dex_pc);
2371     replacement = equal;
2372   } else {
2373     DCHECK_EQ(invoke->GetIntrinsic(), Intrinsics::kStringLength);
2374     replacement = length;
2375   }
2376   invoke->GetBlock()->ReplaceAndRemoveInstructionWith(invoke, replacement);
2377 }
2378 
SimplifyStringIndexOf(HInvoke * invoke)2379 void InstructionSimplifierVisitor::SimplifyStringIndexOf(HInvoke* invoke) {
2380   DCHECK(invoke->GetIntrinsic() == Intrinsics::kStringIndexOf ||
2381          invoke->GetIntrinsic() == Intrinsics::kStringIndexOfAfter);
2382   if (invoke->InputAt(0)->IsLoadString()) {
2383     HLoadString* load_string = invoke->InputAt(0)->AsLoadString();
2384     const DexFile& dex_file = load_string->GetDexFile();
2385     uint32_t utf16_length;
2386     const char* data =
2387         dex_file.StringDataAndUtf16LengthByIdx(load_string->GetStringIndex(), &utf16_length);
2388     if (utf16_length == 0) {
2389       invoke->ReplaceWith(GetGraph()->GetIntConstant(-1));
2390       invoke->GetBlock()->RemoveInstruction(invoke);
2391       RecordSimplification();
2392       return;
2393     }
2394     if (utf16_length == 1 && invoke->GetIntrinsic() == Intrinsics::kStringIndexOf) {
2395       // Simplify to HSelect(HEquals(., load_string.charAt(0)), 0, -1).
2396       // If the sought character is supplementary, this gives the correct result, i.e. -1.
2397       uint32_t c = GetUtf16FromUtf8(&data);
2398       DCHECK_EQ(GetTrailingUtf16Char(c), 0u);
2399       DCHECK_EQ(GetLeadingUtf16Char(c), c);
2400       uint32_t dex_pc = invoke->GetDexPc();
2401       ArenaAllocator* allocator = GetGraph()->GetAllocator();
2402       HEqual* equal =
2403           new (allocator) HEqual(invoke->InputAt(1), GetGraph()->GetIntConstant(c), dex_pc);
2404       invoke->GetBlock()->InsertInstructionBefore(equal, invoke);
2405       HSelect* result = new (allocator) HSelect(equal,
2406                                                 GetGraph()->GetIntConstant(0),
2407                                                 GetGraph()->GetIntConstant(-1),
2408                                                 dex_pc);
2409       invoke->GetBlock()->ReplaceAndRemoveInstructionWith(invoke, result);
2410       RecordSimplification();
2411       return;
2412     }
2413   }
2414 }
2415 
2416 // This method should only be used on intrinsics whose sole way of throwing an
2417 // exception is raising a NPE when the nth argument is null. If that argument
2418 // is provably non-null, we can clear the flag.
SimplifyNPEOnArgN(HInvoke * invoke,size_t n)2419 void InstructionSimplifierVisitor::SimplifyNPEOnArgN(HInvoke* invoke, size_t n) {
2420   HInstruction* arg = invoke->InputAt(n);
2421   if (invoke->CanThrow() && !arg->CanBeNull()) {
2422     invoke->SetCanThrow(false);
2423   }
2424 }
2425 
2426 // Methods that return "this" can replace the returned value with the receiver.
SimplifyReturnThis(HInvoke * invoke)2427 void InstructionSimplifierVisitor::SimplifyReturnThis(HInvoke* invoke) {
2428   if (invoke->HasUses()) {
2429     HInstruction* receiver = invoke->InputAt(0);
2430     invoke->ReplaceWith(receiver);
2431     RecordSimplification();
2432   }
2433 }
2434 
2435 // Helper method for StringBuffer escape analysis.
NoEscapeForStringBufferReference(HInstruction * reference,HInstruction * user)2436 static bool NoEscapeForStringBufferReference(HInstruction* reference, HInstruction* user) {
2437   if (user->IsInvokeStaticOrDirect()) {
2438     // Any constructor on StringBuffer is okay.
2439     return user->AsInvokeStaticOrDirect()->GetResolvedMethod() != nullptr &&
2440            user->AsInvokeStaticOrDirect()->GetResolvedMethod()->IsConstructor() &&
2441            user->InputAt(0) == reference;
2442   } else if (user->IsInvokeVirtual()) {
2443     switch (user->AsInvokeVirtual()->GetIntrinsic()) {
2444       case Intrinsics::kStringBufferLength:
2445       case Intrinsics::kStringBufferToString:
2446         DCHECK_EQ(user->InputAt(0), reference);
2447         return true;
2448       case Intrinsics::kStringBufferAppend:
2449         // Returns "this", so only okay if no further uses.
2450         DCHECK_EQ(user->InputAt(0), reference);
2451         DCHECK_NE(user->InputAt(1), reference);
2452         return !user->HasUses();
2453       default:
2454         break;
2455     }
2456   }
2457   return false;
2458 }
2459 
TryReplaceStringBuilderAppend(HInvoke * invoke)2460 static bool TryReplaceStringBuilderAppend(HInvoke* invoke) {
2461   DCHECK_EQ(invoke->GetIntrinsic(), Intrinsics::kStringBuilderToString);
2462   if (invoke->CanThrowIntoCatchBlock()) {
2463     return false;
2464   }
2465 
2466   HBasicBlock* block = invoke->GetBlock();
2467   HInstruction* sb = invoke->InputAt(0);
2468 
2469   // We support only a new StringBuilder, otherwise we cannot ensure that
2470   // the StringBuilder data does not need to be populated for other users.
2471   if (!sb->IsNewInstance()) {
2472     return false;
2473   }
2474 
2475   // For now, we support only single-block recognition.
2476   // (Ternary operators feeding the append could be implemented.)
2477   for (const HUseListNode<HInstruction*>& use : sb->GetUses()) {
2478     if (use.GetUser()->GetBlock() != block) {
2479       return false;
2480     }
2481     // The append pattern uses the StringBuilder only as the first argument.
2482     if (use.GetIndex() != 0u) {
2483       return false;
2484     }
2485   }
2486 
2487   // Collect args and check for unexpected uses.
2488   // We expect one call to a constructor with no arguments, one constructor fence (unless
2489   // eliminated), some number of append calls and one call to StringBuilder.toString().
2490   bool seen_constructor = false;
2491   bool seen_constructor_fence = false;
2492   bool seen_to_string = false;
2493   uint32_t format = 0u;
2494   uint32_t num_args = 0u;
2495   HInstruction* args[StringBuilderAppend::kMaxArgs];  // Added in reverse order.
2496   for (HBackwardInstructionIterator iter(block->GetInstructions()); !iter.Done(); iter.Advance()) {
2497     HInstruction* user = iter.Current();
2498     // Instructions of interest apply to `sb`, skip those that do not involve `sb`.
2499     if (user->InputCount() == 0u || user->InputAt(0u) != sb) {
2500       continue;
2501     }
2502     // We visit the uses in reverse order, so the StringBuilder.toString() must come first.
2503     if (!seen_to_string) {
2504       if (user == invoke) {
2505         seen_to_string = true;
2506         continue;
2507       } else {
2508         return false;
2509       }
2510     }
2511     // Then we should see the arguments.
2512     if (user->IsInvokeVirtual()) {
2513       HInvokeVirtual* as_invoke_virtual = user->AsInvokeVirtual();
2514       DCHECK(!seen_constructor);
2515       DCHECK(!seen_constructor_fence);
2516       StringBuilderAppend::Argument arg;
2517       switch (as_invoke_virtual->GetIntrinsic()) {
2518         case Intrinsics::kStringBuilderAppendObject:
2519           // TODO: Unimplemented, needs to call String.valueOf().
2520           return false;
2521         case Intrinsics::kStringBuilderAppendString:
2522           arg = StringBuilderAppend::Argument::kString;
2523           break;
2524         case Intrinsics::kStringBuilderAppendCharArray:
2525           // TODO: Unimplemented, StringBuilder.append(char[]) can throw NPE and we would
2526           // not have the correct stack trace for it.
2527           return false;
2528         case Intrinsics::kStringBuilderAppendBoolean:
2529           arg = StringBuilderAppend::Argument::kBoolean;
2530           break;
2531         case Intrinsics::kStringBuilderAppendChar:
2532           arg = StringBuilderAppend::Argument::kChar;
2533           break;
2534         case Intrinsics::kStringBuilderAppendInt:
2535           arg = StringBuilderAppend::Argument::kInt;
2536           break;
2537         case Intrinsics::kStringBuilderAppendLong:
2538           arg = StringBuilderAppend::Argument::kLong;
2539           break;
2540         case Intrinsics::kStringBuilderAppendCharSequence: {
2541           ReferenceTypeInfo rti = user->AsInvokeVirtual()->InputAt(1)->GetReferenceTypeInfo();
2542           if (!rti.IsValid()) {
2543             return false;
2544           }
2545           ScopedObjectAccess soa(Thread::Current());
2546           Handle<mirror::Class> input_type = rti.GetTypeHandle();
2547           DCHECK(input_type != nullptr);
2548           if (input_type.Get() == GetClassRoot<mirror::String>()) {
2549             arg = StringBuilderAppend::Argument::kString;
2550           } else {
2551             // TODO: Check and implement for StringBuilder. We could find the StringBuilder's
2552             // internal char[] inconsistent with the length, or the string compression
2553             // of the result could be compromised with a concurrent modification, and
2554             // we would need to throw appropriate exceptions.
2555             return false;
2556           }
2557           break;
2558         }
2559         case Intrinsics::kStringBuilderAppendFloat:
2560         case Intrinsics::kStringBuilderAppendDouble:
2561           // TODO: Unimplemented, needs to call FloatingDecimal.getBinaryToASCIIConverter().
2562           return false;
2563         default: {
2564           return false;
2565         }
2566       }
2567       // Uses of the append return value should have been replaced with the first input.
2568       DCHECK(!as_invoke_virtual->HasUses());
2569       DCHECK(!as_invoke_virtual->HasEnvironmentUses());
2570       if (num_args == StringBuilderAppend::kMaxArgs) {
2571         return false;
2572       }
2573       format = (format << StringBuilderAppend::kBitsPerArg) | static_cast<uint32_t>(arg);
2574       args[num_args] = as_invoke_virtual->InputAt(1u);
2575       ++num_args;
2576     } else if (user->IsInvokeStaticOrDirect() &&
2577                user->AsInvokeStaticOrDirect()->GetResolvedMethod() != nullptr &&
2578                user->AsInvokeStaticOrDirect()->GetResolvedMethod()->IsConstructor() &&
2579                user->AsInvokeStaticOrDirect()->GetNumberOfArguments() == 1u) {
2580       // After arguments, we should see the constructor.
2581       // We accept only the constructor with no extra arguments.
2582       DCHECK(!seen_constructor);
2583       DCHECK(!seen_constructor_fence);
2584       seen_constructor = true;
2585     } else if (user->IsConstructorFence()) {
2586       // The last use we see is the constructor fence.
2587       DCHECK(seen_constructor);
2588       DCHECK(!seen_constructor_fence);
2589       seen_constructor_fence = true;
2590     } else {
2591       return false;
2592     }
2593   }
2594 
2595   if (num_args == 0u) {
2596     return false;
2597   }
2598 
2599   // Check environment uses.
2600   for (const HUseListNode<HEnvironment*>& use : sb->GetEnvUses()) {
2601     HInstruction* holder = use.GetUser()->GetHolder();
2602     if (holder->GetBlock() != block) {
2603       return false;
2604     }
2605     // Accept only calls on the StringBuilder (which shall all be removed).
2606     // TODO: Carve-out for const-string? Or rely on environment pruning (to be implemented)?
2607     if (holder->InputCount() == 0 || holder->InputAt(0) != sb) {
2608       return false;
2609     }
2610   }
2611 
2612   // Create replacement instruction.
2613   HIntConstant* fmt = block->GetGraph()->GetIntConstant(static_cast<int32_t>(format));
2614   ArenaAllocator* allocator = block->GetGraph()->GetAllocator();
2615   HStringBuilderAppend* append =
2616       new (allocator) HStringBuilderAppend(fmt, num_args, allocator, invoke->GetDexPc());
2617   append->SetReferenceTypeInfo(invoke->GetReferenceTypeInfo());
2618   for (size_t i = 0; i != num_args; ++i) {
2619     append->SetArgumentAt(i, args[num_args - 1u - i]);
2620   }
2621   block->InsertInstructionBefore(append, invoke);
2622   DCHECK(!invoke->CanBeNull());
2623   DCHECK(!append->CanBeNull());
2624   invoke->ReplaceWith(append);
2625   // Copy environment, except for the StringBuilder uses.
2626   for (HEnvironment* env = invoke->GetEnvironment(); env != nullptr; env = env->GetParent()) {
2627     for (size_t i = 0, size = env->Size(); i != size; ++i) {
2628       if (env->GetInstructionAt(i) == sb) {
2629         env->RemoveAsUserOfInput(i);
2630         env->SetRawEnvAt(i, /*instruction=*/ nullptr);
2631       }
2632     }
2633   }
2634   append->CopyEnvironmentFrom(invoke->GetEnvironment());
2635   // Remove the old instruction.
2636   block->RemoveInstruction(invoke);
2637   // Remove the StringBuilder's uses and StringBuilder.
2638   while (sb->HasNonEnvironmentUses()) {
2639     block->RemoveInstruction(sb->GetUses().front().GetUser());
2640   }
2641   DCHECK(!sb->HasEnvironmentUses());
2642   block->RemoveInstruction(sb);
2643   return true;
2644 }
2645 
2646 // Certain allocation intrinsics are not removed by dead code elimination
2647 // because of potentially throwing an OOM exception or other side effects.
2648 // This method removes such intrinsics when special circumstances allow.
SimplifyAllocationIntrinsic(HInvoke * invoke)2649 void InstructionSimplifierVisitor::SimplifyAllocationIntrinsic(HInvoke* invoke) {
2650   if (!invoke->HasUses()) {
2651     // Instruction has no uses. If unsynchronized, we can remove right away, safely ignoring
2652     // the potential OOM of course. Otherwise, we must ensure the receiver object of this
2653     // call does not escape since only thread-local synchronization may be removed.
2654     bool is_synchronized = invoke->GetIntrinsic() == Intrinsics::kStringBufferToString;
2655     HInstruction* receiver = invoke->InputAt(0);
2656     if (!is_synchronized || DoesNotEscape(receiver, NoEscapeForStringBufferReference)) {
2657       invoke->GetBlock()->RemoveInstruction(invoke);
2658       RecordSimplification();
2659     }
2660   } else if (invoke->GetIntrinsic() == Intrinsics::kStringBuilderToString &&
2661              TryReplaceStringBuilderAppend(invoke)) {
2662     RecordSimplification();
2663   }
2664 }
2665 
SimplifyMemBarrier(HInvoke * invoke,MemBarrierKind barrier_kind)2666 void InstructionSimplifierVisitor::SimplifyMemBarrier(HInvoke* invoke,
2667                                                       MemBarrierKind barrier_kind) {
2668   uint32_t dex_pc = invoke->GetDexPc();
2669   HMemoryBarrier* mem_barrier =
2670       new (GetGraph()->GetAllocator()) HMemoryBarrier(barrier_kind, dex_pc);
2671   invoke->GetBlock()->ReplaceAndRemoveInstructionWith(invoke, mem_barrier);
2672 }
2673 
SimplifyMin(HInvoke * invoke,DataType::Type type)2674 void InstructionSimplifierVisitor::SimplifyMin(HInvoke* invoke, DataType::Type type) {
2675   DCHECK(invoke->IsInvokeStaticOrDirect());
2676   HMin* min = new (GetGraph()->GetAllocator())
2677       HMin(type, invoke->InputAt(0), invoke->InputAt(1), invoke->GetDexPc());
2678   invoke->GetBlock()->ReplaceAndRemoveInstructionWith(invoke, min);
2679 }
2680 
SimplifyMax(HInvoke * invoke,DataType::Type type)2681 void InstructionSimplifierVisitor::SimplifyMax(HInvoke* invoke, DataType::Type type) {
2682   DCHECK(invoke->IsInvokeStaticOrDirect());
2683   HMax* max = new (GetGraph()->GetAllocator())
2684       HMax(type, invoke->InputAt(0), invoke->InputAt(1), invoke->GetDexPc());
2685   invoke->GetBlock()->ReplaceAndRemoveInstructionWith(invoke, max);
2686 }
2687 
SimplifyAbs(HInvoke * invoke,DataType::Type type)2688 void InstructionSimplifierVisitor::SimplifyAbs(HInvoke* invoke, DataType::Type type) {
2689   DCHECK(invoke->IsInvokeStaticOrDirect());
2690   HAbs* abs = new (GetGraph()->GetAllocator())
2691       HAbs(type, invoke->InputAt(0), invoke->GetDexPc());
2692   invoke->GetBlock()->ReplaceAndRemoveInstructionWith(invoke, abs);
2693 }
2694 
VisitInvoke(HInvoke * instruction)2695 void InstructionSimplifierVisitor::VisitInvoke(HInvoke* instruction) {
2696   switch (instruction->GetIntrinsic()) {
2697     case Intrinsics::kStringEquals:
2698       SimplifyStringEquals(instruction);
2699       break;
2700     case Intrinsics::kSystemArrayCopy:
2701       SimplifySystemArrayCopy(instruction);
2702       break;
2703     case Intrinsics::kIntegerRotateRight:
2704       SimplifyRotate(instruction, /* is_left= */ false, DataType::Type::kInt32);
2705       break;
2706     case Intrinsics::kLongRotateRight:
2707       SimplifyRotate(instruction, /* is_left= */ false, DataType::Type::kInt64);
2708       break;
2709     case Intrinsics::kIntegerRotateLeft:
2710       SimplifyRotate(instruction, /* is_left= */ true, DataType::Type::kInt32);
2711       break;
2712     case Intrinsics::kLongRotateLeft:
2713       SimplifyRotate(instruction, /* is_left= */ true, DataType::Type::kInt64);
2714       break;
2715     case Intrinsics::kIntegerCompare:
2716       SimplifyCompare(instruction, /* is_signum= */ false, DataType::Type::kInt32);
2717       break;
2718     case Intrinsics::kLongCompare:
2719       SimplifyCompare(instruction, /* is_signum= */ false, DataType::Type::kInt64);
2720       break;
2721     case Intrinsics::kIntegerSignum:
2722       SimplifyCompare(instruction, /* is_signum= */ true, DataType::Type::kInt32);
2723       break;
2724     case Intrinsics::kLongSignum:
2725       SimplifyCompare(instruction, /* is_signum= */ true, DataType::Type::kInt64);
2726       break;
2727     case Intrinsics::kFloatIsNaN:
2728     case Intrinsics::kDoubleIsNaN:
2729       SimplifyIsNaN(instruction);
2730       break;
2731     case Intrinsics::kFloatFloatToIntBits:
2732     case Intrinsics::kDoubleDoubleToLongBits:
2733       SimplifyFP2Int(instruction);
2734       break;
2735     case Intrinsics::kStringCharAt:
2736       SimplifyStringCharAt(instruction);
2737       break;
2738     case Intrinsics::kStringIsEmpty:
2739     case Intrinsics::kStringLength:
2740       SimplifyStringIsEmptyOrLength(instruction);
2741       break;
2742     case Intrinsics::kStringIndexOf:
2743     case Intrinsics::kStringIndexOfAfter:
2744       SimplifyStringIndexOf(instruction);
2745       break;
2746     case Intrinsics::kStringStringIndexOf:
2747     case Intrinsics::kStringStringIndexOfAfter:
2748       SimplifyNPEOnArgN(instruction, 1);  // 0th has own NullCheck
2749       break;
2750     case Intrinsics::kStringBufferAppend:
2751     case Intrinsics::kStringBuilderAppendObject:
2752     case Intrinsics::kStringBuilderAppendString:
2753     case Intrinsics::kStringBuilderAppendCharSequence:
2754     case Intrinsics::kStringBuilderAppendCharArray:
2755     case Intrinsics::kStringBuilderAppendBoolean:
2756     case Intrinsics::kStringBuilderAppendChar:
2757     case Intrinsics::kStringBuilderAppendInt:
2758     case Intrinsics::kStringBuilderAppendLong:
2759     case Intrinsics::kStringBuilderAppendFloat:
2760     case Intrinsics::kStringBuilderAppendDouble:
2761       SimplifyReturnThis(instruction);
2762       break;
2763     case Intrinsics::kStringBufferToString:
2764     case Intrinsics::kStringBuilderToString:
2765       SimplifyAllocationIntrinsic(instruction);
2766       break;
2767     case Intrinsics::kUnsafeLoadFence:
2768       SimplifyMemBarrier(instruction, MemBarrierKind::kLoadAny);
2769       break;
2770     case Intrinsics::kUnsafeStoreFence:
2771       SimplifyMemBarrier(instruction, MemBarrierKind::kAnyStore);
2772       break;
2773     case Intrinsics::kUnsafeFullFence:
2774       SimplifyMemBarrier(instruction, MemBarrierKind::kAnyAny);
2775       break;
2776     case Intrinsics::kVarHandleFullFence:
2777       SimplifyMemBarrier(instruction, MemBarrierKind::kAnyAny);
2778       break;
2779     case Intrinsics::kVarHandleAcquireFence:
2780       SimplifyMemBarrier(instruction, MemBarrierKind::kLoadAny);
2781       break;
2782     case Intrinsics::kVarHandleReleaseFence:
2783       SimplifyMemBarrier(instruction, MemBarrierKind::kAnyStore);
2784       break;
2785     case Intrinsics::kVarHandleLoadLoadFence:
2786       SimplifyMemBarrier(instruction, MemBarrierKind::kLoadAny);
2787       break;
2788     case Intrinsics::kVarHandleStoreStoreFence:
2789       SimplifyMemBarrier(instruction, MemBarrierKind::kStoreStore);
2790       break;
2791     case Intrinsics::kMathMinIntInt:
2792       SimplifyMin(instruction, DataType::Type::kInt32);
2793       break;
2794     case Intrinsics::kMathMinLongLong:
2795       SimplifyMin(instruction, DataType::Type::kInt64);
2796       break;
2797     case Intrinsics::kMathMinFloatFloat:
2798       SimplifyMin(instruction, DataType::Type::kFloat32);
2799       break;
2800     case Intrinsics::kMathMinDoubleDouble:
2801       SimplifyMin(instruction, DataType::Type::kFloat64);
2802       break;
2803     case Intrinsics::kMathMaxIntInt:
2804       SimplifyMax(instruction, DataType::Type::kInt32);
2805       break;
2806     case Intrinsics::kMathMaxLongLong:
2807       SimplifyMax(instruction, DataType::Type::kInt64);
2808       break;
2809     case Intrinsics::kMathMaxFloatFloat:
2810       SimplifyMax(instruction, DataType::Type::kFloat32);
2811       break;
2812     case Intrinsics::kMathMaxDoubleDouble:
2813       SimplifyMax(instruction, DataType::Type::kFloat64);
2814       break;
2815     case Intrinsics::kMathAbsInt:
2816       SimplifyAbs(instruction, DataType::Type::kInt32);
2817       break;
2818     case Intrinsics::kMathAbsLong:
2819       SimplifyAbs(instruction, DataType::Type::kInt64);
2820       break;
2821     case Intrinsics::kMathAbsFloat:
2822       SimplifyAbs(instruction, DataType::Type::kFloat32);
2823       break;
2824     case Intrinsics::kMathAbsDouble:
2825       SimplifyAbs(instruction, DataType::Type::kFloat64);
2826       break;
2827     default:
2828       break;
2829   }
2830 }
2831 
VisitDeoptimize(HDeoptimize * deoptimize)2832 void InstructionSimplifierVisitor::VisitDeoptimize(HDeoptimize* deoptimize) {
2833   HInstruction* cond = deoptimize->InputAt(0);
2834   if (cond->IsConstant()) {
2835     if (cond->AsIntConstant()->IsFalse()) {
2836       // Never deopt: instruction can be removed.
2837       if (deoptimize->GuardsAnInput()) {
2838         deoptimize->ReplaceWith(deoptimize->GuardedInput());
2839       }
2840       deoptimize->GetBlock()->RemoveInstruction(deoptimize);
2841     } else {
2842       // Always deopt.
2843     }
2844   }
2845 }
2846 
2847 // Replace code looking like
2848 //    OP y, x, const1
2849 //    OP z, y, const2
2850 // with
2851 //    OP z, x, const3
2852 // where OP is both an associative and a commutative operation.
TryHandleAssociativeAndCommutativeOperation(HBinaryOperation * instruction)2853 bool InstructionSimplifierVisitor::TryHandleAssociativeAndCommutativeOperation(
2854     HBinaryOperation* instruction) {
2855   DCHECK(instruction->IsCommutative());
2856 
2857   if (!DataType::IsIntegralType(instruction->GetType())) {
2858     return false;
2859   }
2860 
2861   HInstruction* left = instruction->GetLeft();
2862   HInstruction* right = instruction->GetRight();
2863   // Variable names as described above.
2864   HConstant* const2;
2865   HBinaryOperation* y;
2866 
2867   if (instruction->GetKind() == left->GetKind() && right->IsConstant()) {
2868     const2 = right->AsConstant();
2869     y = left->AsBinaryOperation();
2870   } else if (left->IsConstant() && instruction->GetKind() == right->GetKind()) {
2871     const2 = left->AsConstant();
2872     y = right->AsBinaryOperation();
2873   } else {
2874     // The node does not match the pattern.
2875     return false;
2876   }
2877 
2878   // If `y` has more than one use, we do not perform the optimization
2879   // because it might increase code size (e.g. if the new constant is
2880   // no longer encodable as an immediate operand in the target ISA).
2881   if (!y->HasOnlyOneNonEnvironmentUse()) {
2882     return false;
2883   }
2884 
2885   // GetConstantRight() can return both left and right constants
2886   // for commutative operations.
2887   HConstant* const1 = y->GetConstantRight();
2888   if (const1 == nullptr) {
2889     return false;
2890   }
2891 
2892   instruction->ReplaceInput(const1, 0);
2893   instruction->ReplaceInput(const2, 1);
2894   HConstant* const3 = instruction->TryStaticEvaluation();
2895   DCHECK(const3 != nullptr);
2896   instruction->ReplaceInput(y->GetLeastConstantLeft(), 0);
2897   instruction->ReplaceInput(const3, 1);
2898   RecordSimplification();
2899   return true;
2900 }
2901 
AsAddOrSub(HInstruction * binop)2902 static HBinaryOperation* AsAddOrSub(HInstruction* binop) {
2903   return (binop->IsAdd() || binop->IsSub()) ? binop->AsBinaryOperation() : nullptr;
2904 }
2905 
2906 // Helper function that performs addition statically, considering the result type.
ComputeAddition(DataType::Type type,int64_t x,int64_t y)2907 static int64_t ComputeAddition(DataType::Type type, int64_t x, int64_t y) {
2908   // Use the Compute() method for consistency with TryStaticEvaluation().
2909   if (type == DataType::Type::kInt32) {
2910     return HAdd::Compute<int32_t>(x, y);
2911   } else {
2912     DCHECK_EQ(type, DataType::Type::kInt64);
2913     return HAdd::Compute<int64_t>(x, y);
2914   }
2915 }
2916 
2917 // Helper function that handles the child classes of HConstant
2918 // and returns an integer with the appropriate sign.
GetValue(HConstant * constant,bool is_negated)2919 static int64_t GetValue(HConstant* constant, bool is_negated) {
2920   int64_t ret = Int64FromConstant(constant);
2921   return is_negated ? -ret : ret;
2922 }
2923 
2924 // Replace code looking like
2925 //    OP1 y, x, const1
2926 //    OP2 z, y, const2
2927 // with
2928 //    OP3 z, x, const3
2929 // where OPx is either ADD or SUB, and at least one of OP{1,2} is SUB.
TrySubtractionChainSimplification(HBinaryOperation * instruction)2930 bool InstructionSimplifierVisitor::TrySubtractionChainSimplification(
2931     HBinaryOperation* instruction) {
2932   DCHECK(instruction->IsAdd() || instruction->IsSub()) << instruction->DebugName();
2933 
2934   DataType::Type type = instruction->GetType();
2935   if (!DataType::IsIntegralType(type)) {
2936     return false;
2937   }
2938 
2939   HInstruction* left = instruction->GetLeft();
2940   HInstruction* right = instruction->GetRight();
2941   // Variable names as described above.
2942   HConstant* const2 = right->IsConstant() ? right->AsConstant() : left->AsConstant();
2943   if (const2 == nullptr) {
2944     return false;
2945   }
2946 
2947   HBinaryOperation* y = (AsAddOrSub(left) != nullptr)
2948       ? left->AsBinaryOperation()
2949       : AsAddOrSub(right);
2950   // If y has more than one use, we do not perform the optimization because
2951   // it might increase code size (e.g. if the new constant is no longer
2952   // encodable as an immediate operand in the target ISA).
2953   if ((y == nullptr) || !y->HasOnlyOneNonEnvironmentUse()) {
2954     return false;
2955   }
2956 
2957   left = y->GetLeft();
2958   HConstant* const1 = left->IsConstant() ? left->AsConstant() : y->GetRight()->AsConstant();
2959   if (const1 == nullptr) {
2960     return false;
2961   }
2962 
2963   HInstruction* x = (const1 == left) ? y->GetRight() : left;
2964   // If both inputs are constants, let the constant folding pass deal with it.
2965   if (x->IsConstant()) {
2966     return false;
2967   }
2968 
2969   bool is_const2_negated = (const2 == right) && instruction->IsSub();
2970   int64_t const2_val = GetValue(const2, is_const2_negated);
2971   bool is_y_negated = (y == right) && instruction->IsSub();
2972   right = y->GetRight();
2973   bool is_const1_negated = is_y_negated ^ ((const1 == right) && y->IsSub());
2974   int64_t const1_val = GetValue(const1, is_const1_negated);
2975   bool is_x_negated = is_y_negated ^ ((x == right) && y->IsSub());
2976   int64_t const3_val = ComputeAddition(type, const1_val, const2_val);
2977   HBasicBlock* block = instruction->GetBlock();
2978   HConstant* const3 = block->GetGraph()->GetConstant(type, const3_val);
2979   ArenaAllocator* allocator = instruction->GetAllocator();
2980   HInstruction* z;
2981 
2982   if (is_x_negated) {
2983     z = new (allocator) HSub(type, const3, x, instruction->GetDexPc());
2984   } else {
2985     z = new (allocator) HAdd(type, x, const3, instruction->GetDexPc());
2986   }
2987 
2988   block->ReplaceAndRemoveInstructionWith(instruction, z);
2989   RecordSimplification();
2990   return true;
2991 }
2992 
VisitVecMul(HVecMul * instruction)2993 void InstructionSimplifierVisitor::VisitVecMul(HVecMul* instruction) {
2994   if (TryCombineVecMultiplyAccumulate(instruction)) {
2995     RecordSimplification();
2996   }
2997 }
2998 
2999 }  // namespace art
3000