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