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