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