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 "intrinsics.h" 20#include "mirror/class-inl.h" 21#include "scoped_thread_state_change.h" 22 23namespace art { 24 25class InstructionSimplifierVisitor : public HGraphDelegateVisitor { 26 public: 27 InstructionSimplifierVisitor(HGraph* graph, OptimizingCompilerStats* stats) 28 : HGraphDelegateVisitor(graph), 29 stats_(stats) {} 30 31 void Run(); 32 33 private: 34 void RecordSimplification() { 35 simplification_occurred_ = true; 36 simplifications_at_current_position_++; 37 MaybeRecordStat(kInstructionSimplifications); 38 } 39 40 void MaybeRecordStat(MethodCompilationStat stat) { 41 if (stats_ != nullptr) { 42 stats_->RecordStat(stat); 43 } 44 } 45 46 bool ReplaceRotateWithRor(HBinaryOperation* op, HUShr* ushr, HShl* shl); 47 bool TryReplaceWithRotate(HBinaryOperation* instruction); 48 bool TryReplaceWithRotateConstantPattern(HBinaryOperation* op, HUShr* ushr, HShl* shl); 49 bool TryReplaceWithRotateRegisterNegPattern(HBinaryOperation* op, HUShr* ushr, HShl* shl); 50 bool TryReplaceWithRotateRegisterSubPattern(HBinaryOperation* op, HUShr* ushr, HShl* shl); 51 52 bool TryMoveNegOnInputsAfterBinop(HBinaryOperation* binop); 53 // `op` should be either HOr or HAnd. 54 // De Morgan's laws: 55 // ~a & ~b = ~(a | b) and ~a | ~b = ~(a & b) 56 bool TryDeMorganNegationFactoring(HBinaryOperation* op); 57 void VisitShift(HBinaryOperation* shift); 58 59 void VisitEqual(HEqual* equal) OVERRIDE; 60 void VisitNotEqual(HNotEqual* equal) OVERRIDE; 61 void VisitBooleanNot(HBooleanNot* bool_not) OVERRIDE; 62 void VisitInstanceFieldSet(HInstanceFieldSet* equal) OVERRIDE; 63 void VisitStaticFieldSet(HStaticFieldSet* equal) OVERRIDE; 64 void VisitArraySet(HArraySet* equal) OVERRIDE; 65 void VisitTypeConversion(HTypeConversion* instruction) OVERRIDE; 66 void VisitNullCheck(HNullCheck* instruction) OVERRIDE; 67 void VisitArrayLength(HArrayLength* instruction) OVERRIDE; 68 void VisitCheckCast(HCheckCast* instruction) OVERRIDE; 69 void VisitAdd(HAdd* instruction) OVERRIDE; 70 void VisitAnd(HAnd* instruction) OVERRIDE; 71 void VisitCondition(HCondition* instruction) OVERRIDE; 72 void VisitGreaterThan(HGreaterThan* condition) OVERRIDE; 73 void VisitGreaterThanOrEqual(HGreaterThanOrEqual* condition) OVERRIDE; 74 void VisitLessThan(HLessThan* condition) OVERRIDE; 75 void VisitLessThanOrEqual(HLessThanOrEqual* condition) OVERRIDE; 76 void VisitBelow(HBelow* condition) OVERRIDE; 77 void VisitBelowOrEqual(HBelowOrEqual* condition) OVERRIDE; 78 void VisitAbove(HAbove* condition) OVERRIDE; 79 void VisitAboveOrEqual(HAboveOrEqual* condition) OVERRIDE; 80 void VisitDiv(HDiv* instruction) OVERRIDE; 81 void VisitMul(HMul* instruction) OVERRIDE; 82 void VisitNeg(HNeg* instruction) OVERRIDE; 83 void VisitNot(HNot* instruction) OVERRIDE; 84 void VisitOr(HOr* instruction) OVERRIDE; 85 void VisitShl(HShl* instruction) OVERRIDE; 86 void VisitShr(HShr* instruction) OVERRIDE; 87 void VisitSub(HSub* instruction) OVERRIDE; 88 void VisitUShr(HUShr* instruction) OVERRIDE; 89 void VisitXor(HXor* instruction) OVERRIDE; 90 void VisitSelect(HSelect* select) OVERRIDE; 91 void VisitIf(HIf* instruction) OVERRIDE; 92 void VisitInstanceOf(HInstanceOf* instruction) OVERRIDE; 93 void VisitInvoke(HInvoke* invoke) OVERRIDE; 94 void VisitDeoptimize(HDeoptimize* deoptimize) OVERRIDE; 95 96 bool CanEnsureNotNullAt(HInstruction* instr, HInstruction* at) const; 97 98 void SimplifyRotate(HInvoke* invoke, bool is_left, Primitive::Type type); 99 void SimplifySystemArrayCopy(HInvoke* invoke); 100 void SimplifyStringEquals(HInvoke* invoke); 101 void SimplifyCompare(HInvoke* invoke, bool is_signum, Primitive::Type type); 102 void SimplifyIsNaN(HInvoke* invoke); 103 void SimplifyFP2Int(HInvoke* invoke); 104 void SimplifyMemBarrier(HInvoke* invoke, MemBarrierKind barrier_kind); 105 106 OptimizingCompilerStats* stats_; 107 bool simplification_occurred_ = false; 108 int simplifications_at_current_position_ = 0; 109 // We ensure we do not loop infinitely. The value is a finger in the air guess 110 // that should allow enough simplification. 111 static constexpr int kMaxSamePositionSimplifications = 10; 112}; 113 114void InstructionSimplifier::Run() { 115 InstructionSimplifierVisitor visitor(graph_, stats_); 116 visitor.Run(); 117} 118 119void InstructionSimplifierVisitor::Run() { 120 // Iterate in reverse post order to open up more simplifications to users 121 // of instructions that got simplified. 122 for (HReversePostOrderIterator it(*GetGraph()); !it.Done();) { 123 // The simplification of an instruction to another instruction may yield 124 // possibilities for other simplifications. So although we perform a reverse 125 // post order visit, we sometimes need to revisit an instruction index. 126 simplification_occurred_ = false; 127 VisitBasicBlock(it.Current()); 128 if (simplification_occurred_ && 129 (simplifications_at_current_position_ < kMaxSamePositionSimplifications)) { 130 // New simplifications may be applicable to the instruction at the 131 // current index, so don't advance the iterator. 132 continue; 133 } 134 simplifications_at_current_position_ = 0; 135 it.Advance(); 136 } 137} 138 139namespace { 140 141bool AreAllBitsSet(HConstant* constant) { 142 return Int64FromConstant(constant) == -1; 143} 144 145} // namespace 146 147// Returns true if the code was simplified to use only one negation operation 148// after the binary operation instead of one on each of the inputs. 149bool InstructionSimplifierVisitor::TryMoveNegOnInputsAfterBinop(HBinaryOperation* binop) { 150 DCHECK(binop->IsAdd() || binop->IsSub()); 151 DCHECK(binop->GetLeft()->IsNeg() && binop->GetRight()->IsNeg()); 152 HNeg* left_neg = binop->GetLeft()->AsNeg(); 153 HNeg* right_neg = binop->GetRight()->AsNeg(); 154 if (!left_neg->HasOnlyOneNonEnvironmentUse() || 155 !right_neg->HasOnlyOneNonEnvironmentUse()) { 156 return false; 157 } 158 // Replace code looking like 159 // NEG tmp1, a 160 // NEG tmp2, b 161 // ADD dst, tmp1, tmp2 162 // with 163 // ADD tmp, a, b 164 // NEG dst, tmp 165 // Note that we cannot optimize `(-a) + (-b)` to `-(a + b)` for floating-point. 166 // When `a` is `-0.0` and `b` is `0.0`, the former expression yields `0.0`, 167 // while the later yields `-0.0`. 168 if (!Primitive::IsIntegralType(binop->GetType())) { 169 return false; 170 } 171 binop->ReplaceInput(left_neg->GetInput(), 0); 172 binop->ReplaceInput(right_neg->GetInput(), 1); 173 left_neg->GetBlock()->RemoveInstruction(left_neg); 174 right_neg->GetBlock()->RemoveInstruction(right_neg); 175 HNeg* neg = new (GetGraph()->GetArena()) HNeg(binop->GetType(), binop); 176 binop->GetBlock()->InsertInstructionBefore(neg, binop->GetNext()); 177 binop->ReplaceWithExceptInReplacementAtIndex(neg, 0); 178 RecordSimplification(); 179 return true; 180} 181 182bool InstructionSimplifierVisitor::TryDeMorganNegationFactoring(HBinaryOperation* op) { 183 DCHECK(op->IsAnd() || op->IsOr()) << op->DebugName(); 184 Primitive::Type type = op->GetType(); 185 HInstruction* left = op->GetLeft(); 186 HInstruction* right = op->GetRight(); 187 188 // We can apply De Morgan's laws if both inputs are Not's and are only used 189 // by `op`. 190 if (((left->IsNot() && right->IsNot()) || 191 (left->IsBooleanNot() && right->IsBooleanNot())) && 192 left->HasOnlyOneNonEnvironmentUse() && 193 right->HasOnlyOneNonEnvironmentUse()) { 194 // Replace code looking like 195 // NOT nota, a 196 // NOT notb, b 197 // AND dst, nota, notb (respectively OR) 198 // with 199 // OR or, a, b (respectively AND) 200 // NOT dest, or 201 HInstruction* src_left = left->InputAt(0); 202 HInstruction* src_right = right->InputAt(0); 203 uint32_t dex_pc = op->GetDexPc(); 204 205 // Remove the negations on the inputs. 206 left->ReplaceWith(src_left); 207 right->ReplaceWith(src_right); 208 left->GetBlock()->RemoveInstruction(left); 209 right->GetBlock()->RemoveInstruction(right); 210 211 // Replace the `HAnd` or `HOr`. 212 HBinaryOperation* hbin; 213 if (op->IsAnd()) { 214 hbin = new (GetGraph()->GetArena()) HOr(type, src_left, src_right, dex_pc); 215 } else { 216 hbin = new (GetGraph()->GetArena()) HAnd(type, src_left, src_right, dex_pc); 217 } 218 HInstruction* hnot; 219 if (left->IsBooleanNot()) { 220 hnot = new (GetGraph()->GetArena()) HBooleanNot(hbin, dex_pc); 221 } else { 222 hnot = new (GetGraph()->GetArena()) HNot(type, hbin, dex_pc); 223 } 224 225 op->GetBlock()->InsertInstructionBefore(hbin, op); 226 op->GetBlock()->ReplaceAndRemoveInstructionWith(op, hnot); 227 228 RecordSimplification(); 229 return true; 230 } 231 232 return false; 233} 234 235void InstructionSimplifierVisitor::VisitShift(HBinaryOperation* instruction) { 236 DCHECK(instruction->IsShl() || instruction->IsShr() || instruction->IsUShr()); 237 HConstant* input_cst = instruction->GetConstantRight(); 238 HInstruction* input_other = instruction->GetLeastConstantLeft(); 239 240 if (input_cst != nullptr) { 241 int64_t cst = Int64FromConstant(input_cst); 242 int64_t mask = (input_other->GetType() == Primitive::kPrimLong) 243 ? kMaxLongShiftDistance 244 : kMaxIntShiftDistance; 245 if ((cst & mask) == 0) { 246 // Replace code looking like 247 // SHL dst, src, 0 248 // with 249 // src 250 instruction->ReplaceWith(input_other); 251 instruction->GetBlock()->RemoveInstruction(instruction); 252 } 253 } 254} 255 256static bool IsSubRegBitsMinusOther(HSub* sub, size_t reg_bits, HInstruction* other) { 257 return (sub->GetRight() == other && 258 sub->GetLeft()->IsConstant() && 259 (Int64FromConstant(sub->GetLeft()->AsConstant()) & (reg_bits - 1)) == 0); 260} 261 262bool InstructionSimplifierVisitor::ReplaceRotateWithRor(HBinaryOperation* op, 263 HUShr* ushr, 264 HShl* shl) { 265 DCHECK(op->IsAdd() || op->IsXor() || op->IsOr()) << op->DebugName(); 266 HRor* ror = new (GetGraph()->GetArena()) HRor(ushr->GetType(), ushr->GetLeft(), ushr->GetRight()); 267 op->GetBlock()->ReplaceAndRemoveInstructionWith(op, ror); 268 if (!ushr->HasUses()) { 269 ushr->GetBlock()->RemoveInstruction(ushr); 270 } 271 if (!ushr->GetRight()->HasUses()) { 272 ushr->GetRight()->GetBlock()->RemoveInstruction(ushr->GetRight()); 273 } 274 if (!shl->HasUses()) { 275 shl->GetBlock()->RemoveInstruction(shl); 276 } 277 if (!shl->GetRight()->HasUses()) { 278 shl->GetRight()->GetBlock()->RemoveInstruction(shl->GetRight()); 279 } 280 return true; 281} 282 283// Try to replace a binary operation flanked by one UShr and one Shl with a bitfield rotation. 284bool InstructionSimplifierVisitor::TryReplaceWithRotate(HBinaryOperation* op) { 285 DCHECK(op->IsAdd() || op->IsXor() || op->IsOr()); 286 HInstruction* left = op->GetLeft(); 287 HInstruction* right = op->GetRight(); 288 // If we have an UShr and a Shl (in either order). 289 if ((left->IsUShr() && right->IsShl()) || (left->IsShl() && right->IsUShr())) { 290 HUShr* ushr = left->IsUShr() ? left->AsUShr() : right->AsUShr(); 291 HShl* shl = left->IsShl() ? left->AsShl() : right->AsShl(); 292 DCHECK(Primitive::IsIntOrLongType(ushr->GetType())); 293 if (ushr->GetType() == shl->GetType() && 294 ushr->GetLeft() == shl->GetLeft()) { 295 if (ushr->GetRight()->IsConstant() && shl->GetRight()->IsConstant()) { 296 // Shift distances are both constant, try replacing with Ror if they 297 // add up to the register size. 298 return TryReplaceWithRotateConstantPattern(op, ushr, shl); 299 } else if (ushr->GetRight()->IsSub() || shl->GetRight()->IsSub()) { 300 // Shift distances are potentially of the form x and (reg_size - x). 301 return TryReplaceWithRotateRegisterSubPattern(op, ushr, shl); 302 } else if (ushr->GetRight()->IsNeg() || shl->GetRight()->IsNeg()) { 303 // Shift distances are potentially of the form d and -d. 304 return TryReplaceWithRotateRegisterNegPattern(op, ushr, shl); 305 } 306 } 307 } 308 return false; 309} 310 311// Try replacing code looking like (x >>> #rdist OP x << #ldist): 312// UShr dst, x, #rdist 313// Shl tmp, x, #ldist 314// OP dst, dst, tmp 315// or like (x >>> #rdist OP x << #-ldist): 316// UShr dst, x, #rdist 317// Shl tmp, x, #-ldist 318// OP dst, dst, tmp 319// with 320// Ror dst, x, #rdist 321bool InstructionSimplifierVisitor::TryReplaceWithRotateConstantPattern(HBinaryOperation* op, 322 HUShr* ushr, 323 HShl* shl) { 324 DCHECK(op->IsAdd() || op->IsXor() || op->IsOr()); 325 size_t reg_bits = Primitive::ComponentSize(ushr->GetType()) * kBitsPerByte; 326 size_t rdist = Int64FromConstant(ushr->GetRight()->AsConstant()); 327 size_t ldist = Int64FromConstant(shl->GetRight()->AsConstant()); 328 if (((ldist + rdist) & (reg_bits - 1)) == 0) { 329 ReplaceRotateWithRor(op, ushr, shl); 330 return true; 331 } 332 return false; 333} 334 335// Replace code looking like (x >>> -d OP x << d): 336// Neg neg, d 337// UShr dst, x, neg 338// Shl tmp, x, d 339// OP dst, dst, tmp 340// with 341// Neg neg, d 342// Ror dst, x, neg 343// *** OR *** 344// Replace code looking like (x >>> d OP x << -d): 345// UShr dst, x, d 346// Neg neg, d 347// Shl tmp, x, neg 348// OP dst, dst, tmp 349// with 350// Ror dst, x, d 351bool InstructionSimplifierVisitor::TryReplaceWithRotateRegisterNegPattern(HBinaryOperation* op, 352 HUShr* ushr, 353 HShl* shl) { 354 DCHECK(op->IsAdd() || op->IsXor() || op->IsOr()); 355 DCHECK(ushr->GetRight()->IsNeg() || shl->GetRight()->IsNeg()); 356 bool neg_is_left = shl->GetRight()->IsNeg(); 357 HNeg* neg = neg_is_left ? shl->GetRight()->AsNeg() : ushr->GetRight()->AsNeg(); 358 // And the shift distance being negated is the distance being shifted the other way. 359 if (neg->InputAt(0) == (neg_is_left ? ushr->GetRight() : shl->GetRight())) { 360 ReplaceRotateWithRor(op, ushr, shl); 361 } 362 return false; 363} 364 365// Try replacing code looking like (x >>> d OP x << (#bits - d)): 366// UShr dst, x, d 367// Sub ld, #bits, d 368// Shl tmp, x, ld 369// OP dst, dst, tmp 370// with 371// Ror dst, x, d 372// *** OR *** 373// Replace code looking like (x >>> (#bits - d) OP x << d): 374// Sub rd, #bits, d 375// UShr dst, x, rd 376// Shl tmp, x, d 377// OP dst, dst, tmp 378// with 379// Neg neg, d 380// Ror dst, x, neg 381bool InstructionSimplifierVisitor::TryReplaceWithRotateRegisterSubPattern(HBinaryOperation* op, 382 HUShr* ushr, 383 HShl* shl) { 384 DCHECK(op->IsAdd() || op->IsXor() || op->IsOr()); 385 DCHECK(ushr->GetRight()->IsSub() || shl->GetRight()->IsSub()); 386 size_t reg_bits = Primitive::ComponentSize(ushr->GetType()) * kBitsPerByte; 387 HInstruction* shl_shift = shl->GetRight(); 388 HInstruction* ushr_shift = ushr->GetRight(); 389 if ((shl_shift->IsSub() && IsSubRegBitsMinusOther(shl_shift->AsSub(), reg_bits, ushr_shift)) || 390 (ushr_shift->IsSub() && IsSubRegBitsMinusOther(ushr_shift->AsSub(), reg_bits, shl_shift))) { 391 return ReplaceRotateWithRor(op, ushr, shl); 392 } 393 return false; 394} 395 396void InstructionSimplifierVisitor::VisitNullCheck(HNullCheck* null_check) { 397 HInstruction* obj = null_check->InputAt(0); 398 if (!obj->CanBeNull()) { 399 null_check->ReplaceWith(obj); 400 null_check->GetBlock()->RemoveInstruction(null_check); 401 if (stats_ != nullptr) { 402 stats_->RecordStat(MethodCompilationStat::kRemovedNullCheck); 403 } 404 } 405} 406 407bool InstructionSimplifierVisitor::CanEnsureNotNullAt(HInstruction* input, HInstruction* at) const { 408 if (!input->CanBeNull()) { 409 return true; 410 } 411 412 for (const HUseListNode<HInstruction*>& use : input->GetUses()) { 413 HInstruction* user = use.GetUser(); 414 if (user->IsNullCheck() && user->StrictlyDominates(at)) { 415 return true; 416 } 417 } 418 419 return false; 420} 421 422// Returns whether doing a type test between the class of `object` against `klass` has 423// a statically known outcome. The result of the test is stored in `outcome`. 424static bool TypeCheckHasKnownOutcome(HLoadClass* klass, HInstruction* object, bool* outcome) { 425 DCHECK(!object->IsNullConstant()) << "Null constants should be special cased"; 426 ReferenceTypeInfo obj_rti = object->GetReferenceTypeInfo(); 427 ScopedObjectAccess soa(Thread::Current()); 428 if (!obj_rti.IsValid()) { 429 // We run the simplifier before the reference type propagation so type info might not be 430 // available. 431 return false; 432 } 433 434 ReferenceTypeInfo class_rti = klass->GetLoadedClassRTI(); 435 if (!class_rti.IsValid()) { 436 // Happens when the loaded class is unresolved. 437 return false; 438 } 439 DCHECK(class_rti.IsExact()); 440 if (class_rti.IsSupertypeOf(obj_rti)) { 441 *outcome = true; 442 return true; 443 } else if (obj_rti.IsExact()) { 444 // The test failed at compile time so will also fail at runtime. 445 *outcome = false; 446 return true; 447 } else if (!class_rti.IsInterface() 448 && !obj_rti.IsInterface() 449 && !obj_rti.IsSupertypeOf(class_rti)) { 450 // Different type hierarchy. The test will fail. 451 *outcome = false; 452 return true; 453 } 454 return false; 455} 456 457void InstructionSimplifierVisitor::VisitCheckCast(HCheckCast* check_cast) { 458 HInstruction* object = check_cast->InputAt(0); 459 HLoadClass* load_class = check_cast->InputAt(1)->AsLoadClass(); 460 if (load_class->NeedsAccessCheck()) { 461 // If we need to perform an access check we cannot remove the instruction. 462 return; 463 } 464 465 if (CanEnsureNotNullAt(object, check_cast)) { 466 check_cast->ClearMustDoNullCheck(); 467 } 468 469 if (object->IsNullConstant()) { 470 check_cast->GetBlock()->RemoveInstruction(check_cast); 471 MaybeRecordStat(MethodCompilationStat::kRemovedCheckedCast); 472 return; 473 } 474 475 // Note: The `outcome` is initialized to please valgrind - the compiler can reorder 476 // the return value check with the `outcome` check, b/27651442 . 477 bool outcome = false; 478 if (TypeCheckHasKnownOutcome(load_class, object, &outcome)) { 479 if (outcome) { 480 check_cast->GetBlock()->RemoveInstruction(check_cast); 481 MaybeRecordStat(MethodCompilationStat::kRemovedCheckedCast); 482 if (!load_class->HasUses()) { 483 // We cannot rely on DCE to remove the class because the `HLoadClass` thinks it can throw. 484 // However, here we know that it cannot because the checkcast was successfull, hence 485 // the class was already loaded. 486 load_class->GetBlock()->RemoveInstruction(load_class); 487 } 488 } else { 489 // Don't do anything for exceptional cases for now. Ideally we should remove 490 // all instructions and blocks this instruction dominates. 491 } 492 } 493} 494 495void InstructionSimplifierVisitor::VisitInstanceOf(HInstanceOf* instruction) { 496 HInstruction* object = instruction->InputAt(0); 497 HLoadClass* load_class = instruction->InputAt(1)->AsLoadClass(); 498 if (load_class->NeedsAccessCheck()) { 499 // If we need to perform an access check we cannot remove the instruction. 500 return; 501 } 502 503 bool can_be_null = true; 504 if (CanEnsureNotNullAt(object, instruction)) { 505 can_be_null = false; 506 instruction->ClearMustDoNullCheck(); 507 } 508 509 HGraph* graph = GetGraph(); 510 if (object->IsNullConstant()) { 511 MaybeRecordStat(kRemovedInstanceOf); 512 instruction->ReplaceWith(graph->GetIntConstant(0)); 513 instruction->GetBlock()->RemoveInstruction(instruction); 514 RecordSimplification(); 515 return; 516 } 517 518 // Note: The `outcome` is initialized to please valgrind - the compiler can reorder 519 // the return value check with the `outcome` check, b/27651442 . 520 bool outcome = false; 521 if (TypeCheckHasKnownOutcome(load_class, object, &outcome)) { 522 MaybeRecordStat(kRemovedInstanceOf); 523 if (outcome && can_be_null) { 524 // Type test will succeed, we just need a null test. 525 HNotEqual* test = new (graph->GetArena()) HNotEqual(graph->GetNullConstant(), object); 526 instruction->GetBlock()->InsertInstructionBefore(test, instruction); 527 instruction->ReplaceWith(test); 528 } else { 529 // We've statically determined the result of the instanceof. 530 instruction->ReplaceWith(graph->GetIntConstant(outcome)); 531 } 532 RecordSimplification(); 533 instruction->GetBlock()->RemoveInstruction(instruction); 534 if (outcome && !load_class->HasUses()) { 535 // We cannot rely on DCE to remove the class because the `HLoadClass` thinks it can throw. 536 // However, here we know that it cannot because the instanceof check was successfull, hence 537 // the class was already loaded. 538 load_class->GetBlock()->RemoveInstruction(load_class); 539 } 540 } 541} 542 543void InstructionSimplifierVisitor::VisitInstanceFieldSet(HInstanceFieldSet* instruction) { 544 if ((instruction->GetValue()->GetType() == Primitive::kPrimNot) 545 && CanEnsureNotNullAt(instruction->GetValue(), instruction)) { 546 instruction->ClearValueCanBeNull(); 547 } 548} 549 550void InstructionSimplifierVisitor::VisitStaticFieldSet(HStaticFieldSet* instruction) { 551 if ((instruction->GetValue()->GetType() == Primitive::kPrimNot) 552 && CanEnsureNotNullAt(instruction->GetValue(), instruction)) { 553 instruction->ClearValueCanBeNull(); 554 } 555} 556 557static HCondition* GetOppositeConditionSwapOps(ArenaAllocator* arena, HInstruction* cond) { 558 HInstruction *lhs = cond->InputAt(0); 559 HInstruction *rhs = cond->InputAt(1); 560 switch (cond->GetKind()) { 561 case HInstruction::kEqual: 562 return new (arena) HEqual(rhs, lhs); 563 case HInstruction::kNotEqual: 564 return new (arena) HNotEqual(rhs, lhs); 565 case HInstruction::kLessThan: 566 return new (arena) HGreaterThan(rhs, lhs); 567 case HInstruction::kLessThanOrEqual: 568 return new (arena) HGreaterThanOrEqual(rhs, lhs); 569 case HInstruction::kGreaterThan: 570 return new (arena) HLessThan(rhs, lhs); 571 case HInstruction::kGreaterThanOrEqual: 572 return new (arena) HLessThanOrEqual(rhs, lhs); 573 case HInstruction::kBelow: 574 return new (arena) HAbove(rhs, lhs); 575 case HInstruction::kBelowOrEqual: 576 return new (arena) HAboveOrEqual(rhs, lhs); 577 case HInstruction::kAbove: 578 return new (arena) HBelow(rhs, lhs); 579 case HInstruction::kAboveOrEqual: 580 return new (arena) HBelowOrEqual(rhs, lhs); 581 default: 582 LOG(FATAL) << "Unknown ConditionType " << cond->GetKind(); 583 } 584 return nullptr; 585} 586 587void InstructionSimplifierVisitor::VisitEqual(HEqual* equal) { 588 HInstruction* input_const = equal->GetConstantRight(); 589 if (input_const != nullptr) { 590 HInstruction* input_value = equal->GetLeastConstantLeft(); 591 if (input_value->GetType() == Primitive::kPrimBoolean && input_const->IsIntConstant()) { 592 HBasicBlock* block = equal->GetBlock(); 593 // We are comparing the boolean to a constant which is of type int and can 594 // be any constant. 595 if (input_const->AsIntConstant()->IsTrue()) { 596 // Replace (bool_value == true) with bool_value 597 equal->ReplaceWith(input_value); 598 block->RemoveInstruction(equal); 599 RecordSimplification(); 600 } else if (input_const->AsIntConstant()->IsFalse()) { 601 equal->ReplaceWith(GetGraph()->InsertOppositeCondition(input_value, equal)); 602 block->RemoveInstruction(equal); 603 RecordSimplification(); 604 } else { 605 // Replace (bool_value == integer_not_zero_nor_one_constant) with false 606 equal->ReplaceWith(GetGraph()->GetIntConstant(0)); 607 block->RemoveInstruction(equal); 608 RecordSimplification(); 609 } 610 } else { 611 VisitCondition(equal); 612 } 613 } else { 614 VisitCondition(equal); 615 } 616} 617 618void InstructionSimplifierVisitor::VisitNotEqual(HNotEqual* not_equal) { 619 HInstruction* input_const = not_equal->GetConstantRight(); 620 if (input_const != nullptr) { 621 HInstruction* input_value = not_equal->GetLeastConstantLeft(); 622 if (input_value->GetType() == Primitive::kPrimBoolean && input_const->IsIntConstant()) { 623 HBasicBlock* block = not_equal->GetBlock(); 624 // We are comparing the boolean to a constant which is of type int and can 625 // be any constant. 626 if (input_const->AsIntConstant()->IsTrue()) { 627 not_equal->ReplaceWith(GetGraph()->InsertOppositeCondition(input_value, not_equal)); 628 block->RemoveInstruction(not_equal); 629 RecordSimplification(); 630 } else if (input_const->AsIntConstant()->IsFalse()) { 631 // Replace (bool_value != false) with bool_value 632 not_equal->ReplaceWith(input_value); 633 block->RemoveInstruction(not_equal); 634 RecordSimplification(); 635 } else { 636 // Replace (bool_value != integer_not_zero_nor_one_constant) with true 637 not_equal->ReplaceWith(GetGraph()->GetIntConstant(1)); 638 block->RemoveInstruction(not_equal); 639 RecordSimplification(); 640 } 641 } else { 642 VisitCondition(not_equal); 643 } 644 } else { 645 VisitCondition(not_equal); 646 } 647} 648 649void InstructionSimplifierVisitor::VisitBooleanNot(HBooleanNot* bool_not) { 650 HInstruction* input = bool_not->InputAt(0); 651 HInstruction* replace_with = nullptr; 652 653 if (input->IsIntConstant()) { 654 // Replace !(true/false) with false/true. 655 if (input->AsIntConstant()->IsTrue()) { 656 replace_with = GetGraph()->GetIntConstant(0); 657 } else { 658 DCHECK(input->AsIntConstant()->IsFalse()) << input->AsIntConstant()->GetValue(); 659 replace_with = GetGraph()->GetIntConstant(1); 660 } 661 } else if (input->IsBooleanNot()) { 662 // Replace (!(!bool_value)) with bool_value. 663 replace_with = input->InputAt(0); 664 } else if (input->IsCondition() && 665 // Don't change FP compares. The definition of compares involving 666 // NaNs forces the compares to be done as written by the user. 667 !Primitive::IsFloatingPointType(input->InputAt(0)->GetType())) { 668 // Replace condition with its opposite. 669 replace_with = GetGraph()->InsertOppositeCondition(input->AsCondition(), bool_not); 670 } 671 672 if (replace_with != nullptr) { 673 bool_not->ReplaceWith(replace_with); 674 bool_not->GetBlock()->RemoveInstruction(bool_not); 675 RecordSimplification(); 676 } 677} 678 679void InstructionSimplifierVisitor::VisitSelect(HSelect* select) { 680 HInstruction* replace_with = nullptr; 681 HInstruction* condition = select->GetCondition(); 682 HInstruction* true_value = select->GetTrueValue(); 683 HInstruction* false_value = select->GetFalseValue(); 684 685 if (condition->IsBooleanNot()) { 686 // Change ((!cond) ? x : y) to (cond ? y : x). 687 condition = condition->InputAt(0); 688 std::swap(true_value, false_value); 689 select->ReplaceInput(false_value, 0); 690 select->ReplaceInput(true_value, 1); 691 select->ReplaceInput(condition, 2); 692 RecordSimplification(); 693 } 694 695 if (true_value == false_value) { 696 // Replace (cond ? x : x) with (x). 697 replace_with = true_value; 698 } else if (condition->IsIntConstant()) { 699 if (condition->AsIntConstant()->IsTrue()) { 700 // Replace (true ? x : y) with (x). 701 replace_with = true_value; 702 } else { 703 // Replace (false ? x : y) with (y). 704 DCHECK(condition->AsIntConstant()->IsFalse()) << condition->AsIntConstant()->GetValue(); 705 replace_with = false_value; 706 } 707 } else if (true_value->IsIntConstant() && false_value->IsIntConstant()) { 708 if (true_value->AsIntConstant()->IsTrue() && false_value->AsIntConstant()->IsFalse()) { 709 // Replace (cond ? true : false) with (cond). 710 replace_with = condition; 711 } else if (true_value->AsIntConstant()->IsFalse() && false_value->AsIntConstant()->IsTrue()) { 712 // Replace (cond ? false : true) with (!cond). 713 replace_with = GetGraph()->InsertOppositeCondition(condition, select); 714 } 715 } 716 717 if (replace_with != nullptr) { 718 select->ReplaceWith(replace_with); 719 select->GetBlock()->RemoveInstruction(select); 720 RecordSimplification(); 721 } 722} 723 724void InstructionSimplifierVisitor::VisitIf(HIf* instruction) { 725 HInstruction* condition = instruction->InputAt(0); 726 if (condition->IsBooleanNot()) { 727 // Swap successors if input is negated. 728 instruction->ReplaceInput(condition->InputAt(0), 0); 729 instruction->GetBlock()->SwapSuccessors(); 730 RecordSimplification(); 731 } 732} 733 734void InstructionSimplifierVisitor::VisitArrayLength(HArrayLength* instruction) { 735 HInstruction* input = instruction->InputAt(0); 736 // If the array is a NewArray with constant size, replace the array length 737 // with the constant instruction. This helps the bounds check elimination phase. 738 if (input->IsNewArray()) { 739 input = input->InputAt(0); 740 if (input->IsIntConstant()) { 741 instruction->ReplaceWith(input); 742 } 743 } 744} 745 746void InstructionSimplifierVisitor::VisitArraySet(HArraySet* instruction) { 747 HInstruction* value = instruction->GetValue(); 748 if (value->GetType() != Primitive::kPrimNot) return; 749 750 if (CanEnsureNotNullAt(value, instruction)) { 751 instruction->ClearValueCanBeNull(); 752 } 753 754 if (value->IsArrayGet()) { 755 if (value->AsArrayGet()->GetArray() == instruction->GetArray()) { 756 // If the code is just swapping elements in the array, no need for a type check. 757 instruction->ClearNeedsTypeCheck(); 758 return; 759 } 760 } 761 762 if (value->IsNullConstant()) { 763 instruction->ClearNeedsTypeCheck(); 764 return; 765 } 766 767 ScopedObjectAccess soa(Thread::Current()); 768 ReferenceTypeInfo array_rti = instruction->GetArray()->GetReferenceTypeInfo(); 769 ReferenceTypeInfo value_rti = value->GetReferenceTypeInfo(); 770 if (!array_rti.IsValid()) { 771 return; 772 } 773 774 if (value_rti.IsValid() && array_rti.CanArrayHold(value_rti)) { 775 instruction->ClearNeedsTypeCheck(); 776 return; 777 } 778 779 if (array_rti.IsObjectArray()) { 780 if (array_rti.IsExact()) { 781 instruction->ClearNeedsTypeCheck(); 782 return; 783 } 784 instruction->SetStaticTypeOfArrayIsObjectArray(); 785 } 786} 787 788static bool IsTypeConversionImplicit(Primitive::Type input_type, Primitive::Type result_type) { 789 // Invariant: We should never generate a conversion to a Boolean value. 790 DCHECK_NE(Primitive::kPrimBoolean, result_type); 791 792 // Besides conversion to the same type, widening integral conversions are implicit, 793 // excluding conversions to long and the byte->char conversion where we need to 794 // clear the high 16 bits of the 32-bit sign-extended representation of byte. 795 return result_type == input_type || 796 (result_type == Primitive::kPrimInt && (input_type == Primitive::kPrimBoolean || 797 input_type == Primitive::kPrimByte || 798 input_type == Primitive::kPrimShort || 799 input_type == Primitive::kPrimChar)) || 800 (result_type == Primitive::kPrimChar && input_type == Primitive::kPrimBoolean) || 801 (result_type == Primitive::kPrimShort && (input_type == Primitive::kPrimBoolean || 802 input_type == Primitive::kPrimByte)) || 803 (result_type == Primitive::kPrimByte && input_type == Primitive::kPrimBoolean); 804} 805 806static bool IsTypeConversionLossless(Primitive::Type input_type, Primitive::Type result_type) { 807 // The conversion to a larger type is loss-less with the exception of two cases, 808 // - conversion to char, the only unsigned type, where we may lose some bits, and 809 // - conversion from float to long, the only FP to integral conversion with smaller FP type. 810 // For integral to FP conversions this holds because the FP mantissa is large enough. 811 DCHECK_NE(input_type, result_type); 812 return Primitive::ComponentSize(result_type) > Primitive::ComponentSize(input_type) && 813 result_type != Primitive::kPrimChar && 814 !(result_type == Primitive::kPrimLong && input_type == Primitive::kPrimFloat); 815} 816 817void InstructionSimplifierVisitor::VisitTypeConversion(HTypeConversion* instruction) { 818 HInstruction* input = instruction->GetInput(); 819 Primitive::Type input_type = input->GetType(); 820 Primitive::Type result_type = instruction->GetResultType(); 821 if (IsTypeConversionImplicit(input_type, result_type)) { 822 // Remove the implicit conversion; this includes conversion to the same type. 823 instruction->ReplaceWith(input); 824 instruction->GetBlock()->RemoveInstruction(instruction); 825 RecordSimplification(); 826 return; 827 } 828 829 if (input->IsTypeConversion()) { 830 HTypeConversion* input_conversion = input->AsTypeConversion(); 831 HInstruction* original_input = input_conversion->GetInput(); 832 Primitive::Type original_type = original_input->GetType(); 833 834 // When the first conversion is lossless, a direct conversion from the original type 835 // to the final type yields the same result, even for a lossy second conversion, for 836 // example float->double->int or int->double->float. 837 bool is_first_conversion_lossless = IsTypeConversionLossless(original_type, input_type); 838 839 // For integral conversions, see if the first conversion loses only bits that the second 840 // doesn't need, i.e. the final type is no wider than the intermediate. If so, direct 841 // conversion yields the same result, for example long->int->short or int->char->short. 842 bool integral_conversions_with_non_widening_second = 843 Primitive::IsIntegralType(input_type) && 844 Primitive::IsIntegralType(original_type) && 845 Primitive::IsIntegralType(result_type) && 846 Primitive::ComponentSize(result_type) <= Primitive::ComponentSize(input_type); 847 848 if (is_first_conversion_lossless || integral_conversions_with_non_widening_second) { 849 // If the merged conversion is implicit, do the simplification unconditionally. 850 if (IsTypeConversionImplicit(original_type, result_type)) { 851 instruction->ReplaceWith(original_input); 852 instruction->GetBlock()->RemoveInstruction(instruction); 853 if (!input_conversion->HasUses()) { 854 // Don't wait for DCE. 855 input_conversion->GetBlock()->RemoveInstruction(input_conversion); 856 } 857 RecordSimplification(); 858 return; 859 } 860 // Otherwise simplify only if the first conversion has no other use. 861 if (input_conversion->HasOnlyOneNonEnvironmentUse()) { 862 input_conversion->ReplaceWith(original_input); 863 input_conversion->GetBlock()->RemoveInstruction(input_conversion); 864 RecordSimplification(); 865 return; 866 } 867 } 868 } else if (input->IsAnd() && Primitive::IsIntegralType(result_type)) { 869 DCHECK(Primitive::IsIntegralType(input_type)); 870 HAnd* input_and = input->AsAnd(); 871 HConstant* constant = input_and->GetConstantRight(); 872 if (constant != nullptr) { 873 int64_t value = Int64FromConstant(constant); 874 DCHECK_NE(value, -1); // "& -1" would have been optimized away in VisitAnd(). 875 size_t trailing_ones = CTZ(~static_cast<uint64_t>(value)); 876 if (trailing_ones >= kBitsPerByte * Primitive::ComponentSize(result_type)) { 877 // The `HAnd` is useless, for example in `(byte) (x & 0xff)`, get rid of it. 878 HInstruction* original_input = input_and->GetLeastConstantLeft(); 879 if (IsTypeConversionImplicit(original_input->GetType(), result_type)) { 880 instruction->ReplaceWith(original_input); 881 instruction->GetBlock()->RemoveInstruction(instruction); 882 RecordSimplification(); 883 return; 884 } else if (input->HasOnlyOneNonEnvironmentUse()) { 885 input_and->ReplaceWith(original_input); 886 input_and->GetBlock()->RemoveInstruction(input_and); 887 RecordSimplification(); 888 return; 889 } 890 } 891 } 892 } 893} 894 895void InstructionSimplifierVisitor::VisitAdd(HAdd* instruction) { 896 HConstant* input_cst = instruction->GetConstantRight(); 897 HInstruction* input_other = instruction->GetLeastConstantLeft(); 898 if ((input_cst != nullptr) && input_cst->IsArithmeticZero()) { 899 // Replace code looking like 900 // ADD dst, src, 0 901 // with 902 // src 903 // Note that we cannot optimize `x + 0.0` to `x` for floating-point. When 904 // `x` is `-0.0`, the former expression yields `0.0`, while the later 905 // yields `-0.0`. 906 if (Primitive::IsIntegralType(instruction->GetType())) { 907 instruction->ReplaceWith(input_other); 908 instruction->GetBlock()->RemoveInstruction(instruction); 909 return; 910 } 911 } 912 913 HInstruction* left = instruction->GetLeft(); 914 HInstruction* right = instruction->GetRight(); 915 bool left_is_neg = left->IsNeg(); 916 bool right_is_neg = right->IsNeg(); 917 918 if (left_is_neg && right_is_neg) { 919 if (TryMoveNegOnInputsAfterBinop(instruction)) { 920 return; 921 } 922 } 923 924 HNeg* neg = left_is_neg ? left->AsNeg() : right->AsNeg(); 925 if ((left_is_neg ^ right_is_neg) && neg->HasOnlyOneNonEnvironmentUse()) { 926 // Replace code looking like 927 // NEG tmp, b 928 // ADD dst, a, tmp 929 // with 930 // SUB dst, a, b 931 // We do not perform the optimization if the input negation has environment 932 // uses or multiple non-environment uses as it could lead to worse code. In 933 // particular, we do not want the live range of `b` to be extended if we are 934 // not sure the initial 'NEG' instruction can be removed. 935 HInstruction* other = left_is_neg ? right : left; 936 HSub* sub = new(GetGraph()->GetArena()) HSub(instruction->GetType(), other, neg->GetInput()); 937 instruction->GetBlock()->ReplaceAndRemoveInstructionWith(instruction, sub); 938 RecordSimplification(); 939 neg->GetBlock()->RemoveInstruction(neg); 940 return; 941 } 942 943 TryReplaceWithRotate(instruction); 944} 945 946void InstructionSimplifierVisitor::VisitAnd(HAnd* instruction) { 947 HConstant* input_cst = instruction->GetConstantRight(); 948 HInstruction* input_other = instruction->GetLeastConstantLeft(); 949 950 if (input_cst != nullptr) { 951 int64_t value = Int64FromConstant(input_cst); 952 if (value == -1) { 953 // Replace code looking like 954 // AND dst, src, 0xFFF...FF 955 // with 956 // src 957 instruction->ReplaceWith(input_other); 958 instruction->GetBlock()->RemoveInstruction(instruction); 959 RecordSimplification(); 960 return; 961 } 962 // Eliminate And from UShr+And if the And-mask contains all the bits that 963 // can be non-zero after UShr. Transform Shr+And to UShr if the And-mask 964 // precisely clears the shifted-in sign bits. 965 if ((input_other->IsUShr() || input_other->IsShr()) && input_other->InputAt(1)->IsConstant()) { 966 size_t reg_bits = (instruction->GetResultType() == Primitive::kPrimLong) ? 64 : 32; 967 size_t shift = Int64FromConstant(input_other->InputAt(1)->AsConstant()) & (reg_bits - 1); 968 size_t num_tail_bits_set = CTZ(value + 1); 969 if ((num_tail_bits_set >= reg_bits - shift) && input_other->IsUShr()) { 970 // This AND clears only bits known to be clear, for example "(x >>> 24) & 0xff". 971 instruction->ReplaceWith(input_other); 972 instruction->GetBlock()->RemoveInstruction(instruction); 973 RecordSimplification(); 974 return; 975 } else if ((num_tail_bits_set == reg_bits - shift) && IsPowerOfTwo(value + 1) && 976 input_other->HasOnlyOneNonEnvironmentUse()) { 977 DCHECK(input_other->IsShr()); // For UShr, we would have taken the branch above. 978 // Replace SHR+AND with USHR, for example "(x >> 24) & 0xff" -> "x >>> 24". 979 HUShr* ushr = new (GetGraph()->GetArena()) HUShr(instruction->GetType(), 980 input_other->InputAt(0), 981 input_other->InputAt(1), 982 input_other->GetDexPc()); 983 instruction->GetBlock()->ReplaceAndRemoveInstructionWith(instruction, ushr); 984 input_other->GetBlock()->RemoveInstruction(input_other); 985 RecordSimplification(); 986 return; 987 } 988 } 989 } 990 991 // We assume that GVN has run before, so we only perform a pointer comparison. 992 // If for some reason the values are equal but the pointers are different, we 993 // are still correct and only miss an optimization opportunity. 994 if (instruction->GetLeft() == instruction->GetRight()) { 995 // Replace code looking like 996 // AND dst, src, src 997 // with 998 // src 999 instruction->ReplaceWith(instruction->GetLeft()); 1000 instruction->GetBlock()->RemoveInstruction(instruction); 1001 return; 1002 } 1003 1004 TryDeMorganNegationFactoring(instruction); 1005} 1006 1007void InstructionSimplifierVisitor::VisitGreaterThan(HGreaterThan* condition) { 1008 VisitCondition(condition); 1009} 1010 1011void InstructionSimplifierVisitor::VisitGreaterThanOrEqual(HGreaterThanOrEqual* condition) { 1012 VisitCondition(condition); 1013} 1014 1015void InstructionSimplifierVisitor::VisitLessThan(HLessThan* condition) { 1016 VisitCondition(condition); 1017} 1018 1019void InstructionSimplifierVisitor::VisitLessThanOrEqual(HLessThanOrEqual* condition) { 1020 VisitCondition(condition); 1021} 1022 1023void InstructionSimplifierVisitor::VisitBelow(HBelow* condition) { 1024 VisitCondition(condition); 1025} 1026 1027void InstructionSimplifierVisitor::VisitBelowOrEqual(HBelowOrEqual* condition) { 1028 VisitCondition(condition); 1029} 1030 1031void InstructionSimplifierVisitor::VisitAbove(HAbove* condition) { 1032 VisitCondition(condition); 1033} 1034 1035void InstructionSimplifierVisitor::VisitAboveOrEqual(HAboveOrEqual* condition) { 1036 VisitCondition(condition); 1037} 1038 1039void InstructionSimplifierVisitor::VisitCondition(HCondition* condition) { 1040 // Reverse condition if left is constant. Our code generators prefer constant 1041 // on the right hand side. 1042 if (condition->GetLeft()->IsConstant() && !condition->GetRight()->IsConstant()) { 1043 HBasicBlock* block = condition->GetBlock(); 1044 HCondition* replacement = GetOppositeConditionSwapOps(block->GetGraph()->GetArena(), condition); 1045 // If it is a fp we must set the opposite bias. 1046 if (replacement != nullptr) { 1047 if (condition->IsLtBias()) { 1048 replacement->SetBias(ComparisonBias::kGtBias); 1049 } else if (condition->IsGtBias()) { 1050 replacement->SetBias(ComparisonBias::kLtBias); 1051 } 1052 block->ReplaceAndRemoveInstructionWith(condition, replacement); 1053 RecordSimplification(); 1054 1055 condition = replacement; 1056 } 1057 } 1058 1059 HInstruction* left = condition->GetLeft(); 1060 HInstruction* right = condition->GetRight(); 1061 1062 // Try to fold an HCompare into this HCondition. 1063 1064 // We can only replace an HCondition which compares a Compare to 0. 1065 // Both 'dx' and 'jack' generate a compare to 0 when compiling a 1066 // condition with a long, float or double comparison as input. 1067 if (!left->IsCompare() || !right->IsConstant() || right->AsIntConstant()->GetValue() != 0) { 1068 // Conversion is not possible. 1069 return; 1070 } 1071 1072 // Is the Compare only used for this purpose? 1073 if (!left->GetUses().HasExactlyOneElement()) { 1074 // Someone else also wants the result of the compare. 1075 return; 1076 } 1077 1078 if (!left->GetEnvUses().empty()) { 1079 // There is a reference to the compare result in an environment. Do we really need it? 1080 if (GetGraph()->IsDebuggable()) { 1081 return; 1082 } 1083 1084 // We have to ensure that there are no deopt points in the sequence. 1085 if (left->HasAnyEnvironmentUseBefore(condition)) { 1086 return; 1087 } 1088 } 1089 1090 // Clean up any environment uses from the HCompare, if any. 1091 left->RemoveEnvironmentUsers(); 1092 1093 // We have decided to fold the HCompare into the HCondition. Transfer the information. 1094 condition->SetBias(left->AsCompare()->GetBias()); 1095 1096 // Replace the operands of the HCondition. 1097 condition->ReplaceInput(left->InputAt(0), 0); 1098 condition->ReplaceInput(left->InputAt(1), 1); 1099 1100 // Remove the HCompare. 1101 left->GetBlock()->RemoveInstruction(left); 1102 1103 RecordSimplification(); 1104} 1105 1106void InstructionSimplifierVisitor::VisitDiv(HDiv* instruction) { 1107 HConstant* input_cst = instruction->GetConstantRight(); 1108 HInstruction* input_other = instruction->GetLeastConstantLeft(); 1109 Primitive::Type type = instruction->GetType(); 1110 1111 if ((input_cst != nullptr) && input_cst->IsOne()) { 1112 // Replace code looking like 1113 // DIV dst, src, 1 1114 // with 1115 // src 1116 instruction->ReplaceWith(input_other); 1117 instruction->GetBlock()->RemoveInstruction(instruction); 1118 return; 1119 } 1120 1121 if ((input_cst != nullptr) && input_cst->IsMinusOne()) { 1122 // Replace code looking like 1123 // DIV dst, src, -1 1124 // with 1125 // NEG dst, src 1126 instruction->GetBlock()->ReplaceAndRemoveInstructionWith( 1127 instruction, new (GetGraph()->GetArena()) HNeg(type, input_other)); 1128 RecordSimplification(); 1129 return; 1130 } 1131 1132 if ((input_cst != nullptr) && Primitive::IsFloatingPointType(type)) { 1133 // Try replacing code looking like 1134 // DIV dst, src, constant 1135 // with 1136 // MUL dst, src, 1 / constant 1137 HConstant* reciprocal = nullptr; 1138 if (type == Primitive::Primitive::kPrimDouble) { 1139 double value = input_cst->AsDoubleConstant()->GetValue(); 1140 if (CanDivideByReciprocalMultiplyDouble(bit_cast<int64_t, double>(value))) { 1141 reciprocal = GetGraph()->GetDoubleConstant(1.0 / value); 1142 } 1143 } else { 1144 DCHECK_EQ(type, Primitive::kPrimFloat); 1145 float value = input_cst->AsFloatConstant()->GetValue(); 1146 if (CanDivideByReciprocalMultiplyFloat(bit_cast<int32_t, float>(value))) { 1147 reciprocal = GetGraph()->GetFloatConstant(1.0f / value); 1148 } 1149 } 1150 1151 if (reciprocal != nullptr) { 1152 instruction->GetBlock()->ReplaceAndRemoveInstructionWith( 1153 instruction, new (GetGraph()->GetArena()) HMul(type, input_other, reciprocal)); 1154 RecordSimplification(); 1155 return; 1156 } 1157 } 1158} 1159 1160void InstructionSimplifierVisitor::VisitMul(HMul* instruction) { 1161 HConstant* input_cst = instruction->GetConstantRight(); 1162 HInstruction* input_other = instruction->GetLeastConstantLeft(); 1163 Primitive::Type type = instruction->GetType(); 1164 HBasicBlock* block = instruction->GetBlock(); 1165 ArenaAllocator* allocator = GetGraph()->GetArena(); 1166 1167 if (input_cst == nullptr) { 1168 return; 1169 } 1170 1171 if (input_cst->IsOne()) { 1172 // Replace code looking like 1173 // MUL dst, src, 1 1174 // with 1175 // src 1176 instruction->ReplaceWith(input_other); 1177 instruction->GetBlock()->RemoveInstruction(instruction); 1178 return; 1179 } 1180 1181 if (input_cst->IsMinusOne() && 1182 (Primitive::IsFloatingPointType(type) || Primitive::IsIntOrLongType(type))) { 1183 // Replace code looking like 1184 // MUL dst, src, -1 1185 // with 1186 // NEG dst, src 1187 HNeg* neg = new (allocator) HNeg(type, input_other); 1188 block->ReplaceAndRemoveInstructionWith(instruction, neg); 1189 RecordSimplification(); 1190 return; 1191 } 1192 1193 if (Primitive::IsFloatingPointType(type) && 1194 ((input_cst->IsFloatConstant() && input_cst->AsFloatConstant()->GetValue() == 2.0f) || 1195 (input_cst->IsDoubleConstant() && input_cst->AsDoubleConstant()->GetValue() == 2.0))) { 1196 // Replace code looking like 1197 // FP_MUL dst, src, 2.0 1198 // with 1199 // FP_ADD dst, src, src 1200 // The 'int' and 'long' cases are handled below. 1201 block->ReplaceAndRemoveInstructionWith(instruction, 1202 new (allocator) HAdd(type, input_other, input_other)); 1203 RecordSimplification(); 1204 return; 1205 } 1206 1207 if (Primitive::IsIntOrLongType(type)) { 1208 int64_t factor = Int64FromConstant(input_cst); 1209 // Even though constant propagation also takes care of the zero case, other 1210 // optimizations can lead to having a zero multiplication. 1211 if (factor == 0) { 1212 // Replace code looking like 1213 // MUL dst, src, 0 1214 // with 1215 // 0 1216 instruction->ReplaceWith(input_cst); 1217 instruction->GetBlock()->RemoveInstruction(instruction); 1218 } else if (IsPowerOfTwo(factor)) { 1219 // Replace code looking like 1220 // MUL dst, src, pow_of_2 1221 // with 1222 // SHL dst, src, log2(pow_of_2) 1223 HIntConstant* shift = GetGraph()->GetIntConstant(WhichPowerOf2(factor)); 1224 HShl* shl = new (allocator) HShl(type, input_other, shift); 1225 block->ReplaceAndRemoveInstructionWith(instruction, shl); 1226 RecordSimplification(); 1227 } else if (IsPowerOfTwo(factor - 1)) { 1228 // Transform code looking like 1229 // MUL dst, src, (2^n + 1) 1230 // into 1231 // SHL tmp, src, n 1232 // ADD dst, src, tmp 1233 HShl* shl = new (allocator) HShl(type, 1234 input_other, 1235 GetGraph()->GetIntConstant(WhichPowerOf2(factor - 1))); 1236 HAdd* add = new (allocator) HAdd(type, input_other, shl); 1237 1238 block->InsertInstructionBefore(shl, instruction); 1239 block->ReplaceAndRemoveInstructionWith(instruction, add); 1240 RecordSimplification(); 1241 } else if (IsPowerOfTwo(factor + 1)) { 1242 // Transform code looking like 1243 // MUL dst, src, (2^n - 1) 1244 // into 1245 // SHL tmp, src, n 1246 // SUB dst, tmp, src 1247 HShl* shl = new (allocator) HShl(type, 1248 input_other, 1249 GetGraph()->GetIntConstant(WhichPowerOf2(factor + 1))); 1250 HSub* sub = new (allocator) HSub(type, shl, input_other); 1251 1252 block->InsertInstructionBefore(shl, instruction); 1253 block->ReplaceAndRemoveInstructionWith(instruction, sub); 1254 RecordSimplification(); 1255 } 1256 } 1257} 1258 1259void InstructionSimplifierVisitor::VisitNeg(HNeg* instruction) { 1260 HInstruction* input = instruction->GetInput(); 1261 if (input->IsNeg()) { 1262 // Replace code looking like 1263 // NEG tmp, src 1264 // NEG dst, tmp 1265 // with 1266 // src 1267 HNeg* previous_neg = input->AsNeg(); 1268 instruction->ReplaceWith(previous_neg->GetInput()); 1269 instruction->GetBlock()->RemoveInstruction(instruction); 1270 // We perform the optimization even if the input negation has environment 1271 // uses since it allows removing the current instruction. But we only delete 1272 // the input negation only if it is does not have any uses left. 1273 if (!previous_neg->HasUses()) { 1274 previous_neg->GetBlock()->RemoveInstruction(previous_neg); 1275 } 1276 RecordSimplification(); 1277 return; 1278 } 1279 1280 if (input->IsSub() && input->HasOnlyOneNonEnvironmentUse() && 1281 !Primitive::IsFloatingPointType(input->GetType())) { 1282 // Replace code looking like 1283 // SUB tmp, a, b 1284 // NEG dst, tmp 1285 // with 1286 // SUB dst, b, a 1287 // We do not perform the optimization if the input subtraction has 1288 // environment uses or multiple non-environment uses as it could lead to 1289 // worse code. In particular, we do not want the live ranges of `a` and `b` 1290 // to be extended if we are not sure the initial 'SUB' instruction can be 1291 // removed. 1292 // We do not perform optimization for fp because we could lose the sign of zero. 1293 HSub* sub = input->AsSub(); 1294 HSub* new_sub = 1295 new (GetGraph()->GetArena()) HSub(instruction->GetType(), sub->GetRight(), sub->GetLeft()); 1296 instruction->GetBlock()->ReplaceAndRemoveInstructionWith(instruction, new_sub); 1297 if (!sub->HasUses()) { 1298 sub->GetBlock()->RemoveInstruction(sub); 1299 } 1300 RecordSimplification(); 1301 } 1302} 1303 1304void InstructionSimplifierVisitor::VisitNot(HNot* instruction) { 1305 HInstruction* input = instruction->GetInput(); 1306 if (input->IsNot()) { 1307 // Replace code looking like 1308 // NOT tmp, src 1309 // NOT dst, tmp 1310 // with 1311 // src 1312 // We perform the optimization even if the input negation has environment 1313 // uses since it allows removing the current instruction. But we only delete 1314 // the input negation only if it is does not have any uses left. 1315 HNot* previous_not = input->AsNot(); 1316 instruction->ReplaceWith(previous_not->GetInput()); 1317 instruction->GetBlock()->RemoveInstruction(instruction); 1318 if (!previous_not->HasUses()) { 1319 previous_not->GetBlock()->RemoveInstruction(previous_not); 1320 } 1321 RecordSimplification(); 1322 } 1323} 1324 1325void InstructionSimplifierVisitor::VisitOr(HOr* instruction) { 1326 HConstant* input_cst = instruction->GetConstantRight(); 1327 HInstruction* input_other = instruction->GetLeastConstantLeft(); 1328 1329 if ((input_cst != nullptr) && input_cst->IsZeroBitPattern()) { 1330 // Replace code looking like 1331 // OR dst, src, 0 1332 // with 1333 // src 1334 instruction->ReplaceWith(input_other); 1335 instruction->GetBlock()->RemoveInstruction(instruction); 1336 return; 1337 } 1338 1339 // We assume that GVN has run before, so we only perform a pointer comparison. 1340 // If for some reason the values are equal but the pointers are different, we 1341 // are still correct and only miss an optimization opportunity. 1342 if (instruction->GetLeft() == instruction->GetRight()) { 1343 // Replace code looking like 1344 // OR dst, src, src 1345 // with 1346 // src 1347 instruction->ReplaceWith(instruction->GetLeft()); 1348 instruction->GetBlock()->RemoveInstruction(instruction); 1349 return; 1350 } 1351 1352 if (TryDeMorganNegationFactoring(instruction)) return; 1353 1354 TryReplaceWithRotate(instruction); 1355} 1356 1357void InstructionSimplifierVisitor::VisitShl(HShl* instruction) { 1358 VisitShift(instruction); 1359} 1360 1361void InstructionSimplifierVisitor::VisitShr(HShr* instruction) { 1362 VisitShift(instruction); 1363} 1364 1365void InstructionSimplifierVisitor::VisitSub(HSub* instruction) { 1366 HConstant* input_cst = instruction->GetConstantRight(); 1367 HInstruction* input_other = instruction->GetLeastConstantLeft(); 1368 1369 Primitive::Type type = instruction->GetType(); 1370 if (Primitive::IsFloatingPointType(type)) { 1371 return; 1372 } 1373 1374 if ((input_cst != nullptr) && input_cst->IsArithmeticZero()) { 1375 // Replace code looking like 1376 // SUB dst, src, 0 1377 // with 1378 // src 1379 // Note that we cannot optimize `x - 0.0` to `x` for floating-point. When 1380 // `x` is `-0.0`, the former expression yields `0.0`, while the later 1381 // yields `-0.0`. 1382 instruction->ReplaceWith(input_other); 1383 instruction->GetBlock()->RemoveInstruction(instruction); 1384 return; 1385 } 1386 1387 HBasicBlock* block = instruction->GetBlock(); 1388 ArenaAllocator* allocator = GetGraph()->GetArena(); 1389 1390 HInstruction* left = instruction->GetLeft(); 1391 HInstruction* right = instruction->GetRight(); 1392 if (left->IsConstant()) { 1393 if (Int64FromConstant(left->AsConstant()) == 0) { 1394 // Replace code looking like 1395 // SUB dst, 0, src 1396 // with 1397 // NEG dst, src 1398 // Note that we cannot optimize `0.0 - x` to `-x` for floating-point. When 1399 // `x` is `0.0`, the former expression yields `0.0`, while the later 1400 // yields `-0.0`. 1401 HNeg* neg = new (allocator) HNeg(type, right); 1402 block->ReplaceAndRemoveInstructionWith(instruction, neg); 1403 RecordSimplification(); 1404 return; 1405 } 1406 } 1407 1408 if (left->IsNeg() && right->IsNeg()) { 1409 if (TryMoveNegOnInputsAfterBinop(instruction)) { 1410 return; 1411 } 1412 } 1413 1414 if (right->IsNeg() && right->HasOnlyOneNonEnvironmentUse()) { 1415 // Replace code looking like 1416 // NEG tmp, b 1417 // SUB dst, a, tmp 1418 // with 1419 // ADD dst, a, b 1420 HAdd* add = new(GetGraph()->GetArena()) HAdd(type, left, right->AsNeg()->GetInput()); 1421 instruction->GetBlock()->ReplaceAndRemoveInstructionWith(instruction, add); 1422 RecordSimplification(); 1423 right->GetBlock()->RemoveInstruction(right); 1424 return; 1425 } 1426 1427 if (left->IsNeg() && left->HasOnlyOneNonEnvironmentUse()) { 1428 // Replace code looking like 1429 // NEG tmp, a 1430 // SUB dst, tmp, b 1431 // with 1432 // ADD tmp, a, b 1433 // NEG dst, tmp 1434 // The second version is not intrinsically better, but enables more 1435 // transformations. 1436 HAdd* add = new(GetGraph()->GetArena()) HAdd(type, left->AsNeg()->GetInput(), right); 1437 instruction->GetBlock()->InsertInstructionBefore(add, instruction); 1438 HNeg* neg = new (GetGraph()->GetArena()) HNeg(instruction->GetType(), add); 1439 instruction->GetBlock()->InsertInstructionBefore(neg, instruction); 1440 instruction->ReplaceWith(neg); 1441 instruction->GetBlock()->RemoveInstruction(instruction); 1442 RecordSimplification(); 1443 left->GetBlock()->RemoveInstruction(left); 1444 } 1445} 1446 1447void InstructionSimplifierVisitor::VisitUShr(HUShr* instruction) { 1448 VisitShift(instruction); 1449} 1450 1451void InstructionSimplifierVisitor::VisitXor(HXor* instruction) { 1452 HConstant* input_cst = instruction->GetConstantRight(); 1453 HInstruction* input_other = instruction->GetLeastConstantLeft(); 1454 1455 if ((input_cst != nullptr) && input_cst->IsZeroBitPattern()) { 1456 // Replace code looking like 1457 // XOR dst, src, 0 1458 // with 1459 // src 1460 instruction->ReplaceWith(input_other); 1461 instruction->GetBlock()->RemoveInstruction(instruction); 1462 return; 1463 } 1464 1465 if ((input_cst != nullptr) && AreAllBitsSet(input_cst)) { 1466 // Replace code looking like 1467 // XOR dst, src, 0xFFF...FF 1468 // with 1469 // NOT dst, src 1470 HNot* bitwise_not = new (GetGraph()->GetArena()) HNot(instruction->GetType(), input_other); 1471 instruction->GetBlock()->ReplaceAndRemoveInstructionWith(instruction, bitwise_not); 1472 RecordSimplification(); 1473 return; 1474 } 1475 1476 HInstruction* left = instruction->GetLeft(); 1477 HInstruction* right = instruction->GetRight(); 1478 if (((left->IsNot() && right->IsNot()) || 1479 (left->IsBooleanNot() && right->IsBooleanNot())) && 1480 left->HasOnlyOneNonEnvironmentUse() && 1481 right->HasOnlyOneNonEnvironmentUse()) { 1482 // Replace code looking like 1483 // NOT nota, a 1484 // NOT notb, b 1485 // XOR dst, nota, notb 1486 // with 1487 // XOR dst, a, b 1488 instruction->ReplaceInput(left->InputAt(0), 0); 1489 instruction->ReplaceInput(right->InputAt(0), 1); 1490 left->GetBlock()->RemoveInstruction(left); 1491 right->GetBlock()->RemoveInstruction(right); 1492 RecordSimplification(); 1493 return; 1494 } 1495 1496 TryReplaceWithRotate(instruction); 1497} 1498 1499void InstructionSimplifierVisitor::SimplifyStringEquals(HInvoke* instruction) { 1500 HInstruction* argument = instruction->InputAt(1); 1501 HInstruction* receiver = instruction->InputAt(0); 1502 if (receiver == argument) { 1503 // Because String.equals is an instance call, the receiver is 1504 // a null check if we don't know it's null. The argument however, will 1505 // be the actual object. So we cannot end up in a situation where both 1506 // are equal but could be null. 1507 DCHECK(CanEnsureNotNullAt(argument, instruction)); 1508 instruction->ReplaceWith(GetGraph()->GetIntConstant(1)); 1509 instruction->GetBlock()->RemoveInstruction(instruction); 1510 } else { 1511 StringEqualsOptimizations optimizations(instruction); 1512 if (CanEnsureNotNullAt(argument, instruction)) { 1513 optimizations.SetArgumentNotNull(); 1514 } 1515 ScopedObjectAccess soa(Thread::Current()); 1516 ReferenceTypeInfo argument_rti = argument->GetReferenceTypeInfo(); 1517 if (argument_rti.IsValid() && argument_rti.IsStringClass()) { 1518 optimizations.SetArgumentIsString(); 1519 } 1520 } 1521} 1522 1523void InstructionSimplifierVisitor::SimplifyRotate(HInvoke* invoke, 1524 bool is_left, 1525 Primitive::Type type) { 1526 DCHECK(invoke->IsInvokeStaticOrDirect()); 1527 DCHECK_EQ(invoke->GetOriginalInvokeType(), InvokeType::kStatic); 1528 HInstruction* value = invoke->InputAt(0); 1529 HInstruction* distance = invoke->InputAt(1); 1530 // Replace the invoke with an HRor. 1531 if (is_left) { 1532 // Unconditionally set the type of the negated distance to `int`, 1533 // as shift and rotate operations expect a 32-bit (or narrower) 1534 // value for their distance input. 1535 distance = new (GetGraph()->GetArena()) HNeg(Primitive::kPrimInt, distance); 1536 invoke->GetBlock()->InsertInstructionBefore(distance, invoke); 1537 } 1538 HRor* ror = new (GetGraph()->GetArena()) HRor(type, value, distance); 1539 invoke->GetBlock()->ReplaceAndRemoveInstructionWith(invoke, ror); 1540 // Remove ClinitCheck and LoadClass, if possible. 1541 HInstruction* clinit = invoke->InputAt(invoke->InputCount() - 1); 1542 if (clinit->IsClinitCheck() && !clinit->HasUses()) { 1543 clinit->GetBlock()->RemoveInstruction(clinit); 1544 HInstruction* ldclass = clinit->InputAt(0); 1545 if (ldclass->IsLoadClass() && !ldclass->HasUses()) { 1546 ldclass->GetBlock()->RemoveInstruction(ldclass); 1547 } 1548 } 1549} 1550 1551static bool IsArrayLengthOf(HInstruction* potential_length, HInstruction* potential_array) { 1552 if (potential_length->IsArrayLength()) { 1553 return potential_length->InputAt(0) == potential_array; 1554 } 1555 1556 if (potential_array->IsNewArray()) { 1557 return potential_array->InputAt(0) == potential_length; 1558 } 1559 1560 return false; 1561} 1562 1563void InstructionSimplifierVisitor::SimplifySystemArrayCopy(HInvoke* instruction) { 1564 HInstruction* source = instruction->InputAt(0); 1565 HInstruction* destination = instruction->InputAt(2); 1566 HInstruction* count = instruction->InputAt(4); 1567 SystemArrayCopyOptimizations optimizations(instruction); 1568 if (CanEnsureNotNullAt(source, instruction)) { 1569 optimizations.SetSourceIsNotNull(); 1570 } 1571 if (CanEnsureNotNullAt(destination, instruction)) { 1572 optimizations.SetDestinationIsNotNull(); 1573 } 1574 if (destination == source) { 1575 optimizations.SetDestinationIsSource(); 1576 } 1577 1578 if (IsArrayLengthOf(count, source)) { 1579 optimizations.SetCountIsSourceLength(); 1580 } 1581 1582 if (IsArrayLengthOf(count, destination)) { 1583 optimizations.SetCountIsDestinationLength(); 1584 } 1585 1586 { 1587 ScopedObjectAccess soa(Thread::Current()); 1588 ReferenceTypeInfo destination_rti = destination->GetReferenceTypeInfo(); 1589 if (destination_rti.IsValid()) { 1590 if (destination_rti.IsObjectArray()) { 1591 if (destination_rti.IsExact()) { 1592 optimizations.SetDoesNotNeedTypeCheck(); 1593 } 1594 optimizations.SetDestinationIsTypedObjectArray(); 1595 } 1596 if (destination_rti.IsPrimitiveArrayClass()) { 1597 optimizations.SetDestinationIsPrimitiveArray(); 1598 } else if (destination_rti.IsNonPrimitiveArrayClass()) { 1599 optimizations.SetDestinationIsNonPrimitiveArray(); 1600 } 1601 } 1602 ReferenceTypeInfo source_rti = source->GetReferenceTypeInfo(); 1603 if (source_rti.IsValid()) { 1604 if (destination_rti.IsValid() && destination_rti.CanArrayHoldValuesOf(source_rti)) { 1605 optimizations.SetDoesNotNeedTypeCheck(); 1606 } 1607 if (source_rti.IsPrimitiveArrayClass()) { 1608 optimizations.SetSourceIsPrimitiveArray(); 1609 } else if (source_rti.IsNonPrimitiveArrayClass()) { 1610 optimizations.SetSourceIsNonPrimitiveArray(); 1611 } 1612 } 1613 } 1614} 1615 1616void InstructionSimplifierVisitor::SimplifyCompare(HInvoke* invoke, 1617 bool is_signum, 1618 Primitive::Type type) { 1619 DCHECK(invoke->IsInvokeStaticOrDirect()); 1620 uint32_t dex_pc = invoke->GetDexPc(); 1621 HInstruction* left = invoke->InputAt(0); 1622 HInstruction* right; 1623 if (!is_signum) { 1624 right = invoke->InputAt(1); 1625 } else if (type == Primitive::kPrimLong) { 1626 right = GetGraph()->GetLongConstant(0); 1627 } else { 1628 right = GetGraph()->GetIntConstant(0); 1629 } 1630 HCompare* compare = new (GetGraph()->GetArena()) 1631 HCompare(type, left, right, ComparisonBias::kNoBias, dex_pc); 1632 invoke->GetBlock()->ReplaceAndRemoveInstructionWith(invoke, compare); 1633} 1634 1635void InstructionSimplifierVisitor::SimplifyIsNaN(HInvoke* invoke) { 1636 DCHECK(invoke->IsInvokeStaticOrDirect()); 1637 uint32_t dex_pc = invoke->GetDexPc(); 1638 // IsNaN(x) is the same as x != x. 1639 HInstruction* x = invoke->InputAt(0); 1640 HCondition* condition = new (GetGraph()->GetArena()) HNotEqual(x, x, dex_pc); 1641 condition->SetBias(ComparisonBias::kLtBias); 1642 invoke->GetBlock()->ReplaceAndRemoveInstructionWith(invoke, condition); 1643} 1644 1645void InstructionSimplifierVisitor::SimplifyFP2Int(HInvoke* invoke) { 1646 DCHECK(invoke->IsInvokeStaticOrDirect()); 1647 uint32_t dex_pc = invoke->GetDexPc(); 1648 HInstruction* x = invoke->InputAt(0); 1649 Primitive::Type type = x->GetType(); 1650 // Set proper bit pattern for NaN and replace intrinsic with raw version. 1651 HInstruction* nan; 1652 if (type == Primitive::kPrimDouble) { 1653 nan = GetGraph()->GetLongConstant(0x7ff8000000000000L); 1654 invoke->SetIntrinsic(Intrinsics::kDoubleDoubleToRawLongBits, 1655 kNeedsEnvironmentOrCache, 1656 kNoSideEffects, 1657 kNoThrow); 1658 } else { 1659 DCHECK_EQ(type, Primitive::kPrimFloat); 1660 nan = GetGraph()->GetIntConstant(0x7fc00000); 1661 invoke->SetIntrinsic(Intrinsics::kFloatFloatToRawIntBits, 1662 kNeedsEnvironmentOrCache, 1663 kNoSideEffects, 1664 kNoThrow); 1665 } 1666 // Test IsNaN(x), which is the same as x != x. 1667 HCondition* condition = new (GetGraph()->GetArena()) HNotEqual(x, x, dex_pc); 1668 condition->SetBias(ComparisonBias::kLtBias); 1669 invoke->GetBlock()->InsertInstructionBefore(condition, invoke->GetNext()); 1670 // Select between the two. 1671 HInstruction* select = new (GetGraph()->GetArena()) HSelect(condition, nan, invoke, dex_pc); 1672 invoke->GetBlock()->InsertInstructionBefore(select, condition->GetNext()); 1673 invoke->ReplaceWithExceptInReplacementAtIndex(select, 0); // false at index 0 1674} 1675 1676void InstructionSimplifierVisitor::SimplifyMemBarrier(HInvoke* invoke, MemBarrierKind barrier_kind) { 1677 uint32_t dex_pc = invoke->GetDexPc(); 1678 HMemoryBarrier* mem_barrier = new (GetGraph()->GetArena()) HMemoryBarrier(barrier_kind, dex_pc); 1679 invoke->GetBlock()->ReplaceAndRemoveInstructionWith(invoke, mem_barrier); 1680} 1681 1682void InstructionSimplifierVisitor::VisitInvoke(HInvoke* instruction) { 1683 switch (instruction->GetIntrinsic()) { 1684 case Intrinsics::kStringEquals: 1685 SimplifyStringEquals(instruction); 1686 break; 1687 case Intrinsics::kSystemArrayCopy: 1688 SimplifySystemArrayCopy(instruction); 1689 break; 1690 case Intrinsics::kIntegerRotateRight: 1691 SimplifyRotate(instruction, /* is_left */ false, Primitive::kPrimInt); 1692 break; 1693 case Intrinsics::kLongRotateRight: 1694 SimplifyRotate(instruction, /* is_left */ false, Primitive::kPrimLong); 1695 break; 1696 case Intrinsics::kIntegerRotateLeft: 1697 SimplifyRotate(instruction, /* is_left */ true, Primitive::kPrimInt); 1698 break; 1699 case Intrinsics::kLongRotateLeft: 1700 SimplifyRotate(instruction, /* is_left */ true, Primitive::kPrimLong); 1701 break; 1702 case Intrinsics::kIntegerCompare: 1703 SimplifyCompare(instruction, /* is_signum */ false, Primitive::kPrimInt); 1704 break; 1705 case Intrinsics::kLongCompare: 1706 SimplifyCompare(instruction, /* is_signum */ false, Primitive::kPrimLong); 1707 break; 1708 case Intrinsics::kIntegerSignum: 1709 SimplifyCompare(instruction, /* is_signum */ true, Primitive::kPrimInt); 1710 break; 1711 case Intrinsics::kLongSignum: 1712 SimplifyCompare(instruction, /* is_signum */ true, Primitive::kPrimLong); 1713 break; 1714 case Intrinsics::kFloatIsNaN: 1715 case Intrinsics::kDoubleIsNaN: 1716 SimplifyIsNaN(instruction); 1717 break; 1718 case Intrinsics::kFloatFloatToIntBits: 1719 case Intrinsics::kDoubleDoubleToLongBits: 1720 SimplifyFP2Int(instruction); 1721 break; 1722 case Intrinsics::kUnsafeLoadFence: 1723 SimplifyMemBarrier(instruction, MemBarrierKind::kLoadAny); 1724 break; 1725 case Intrinsics::kUnsafeStoreFence: 1726 SimplifyMemBarrier(instruction, MemBarrierKind::kAnyStore); 1727 break; 1728 case Intrinsics::kUnsafeFullFence: 1729 SimplifyMemBarrier(instruction, MemBarrierKind::kAnyAny); 1730 break; 1731 default: 1732 break; 1733 } 1734} 1735 1736void InstructionSimplifierVisitor::VisitDeoptimize(HDeoptimize* deoptimize) { 1737 HInstruction* cond = deoptimize->InputAt(0); 1738 if (cond->IsConstant()) { 1739 if (cond->AsIntConstant()->IsFalse()) { 1740 // Never deopt: instruction can be removed. 1741 deoptimize->GetBlock()->RemoveInstruction(deoptimize); 1742 } else { 1743 // Always deopt. 1744 } 1745 } 1746} 1747 1748} // namespace art 1749