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