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