void LinearScanMD::LegalizeConstantUse(IR::Instr * instr, IR::Opnd * opnd) { Assert(opnd->IsAddrOpnd() || opnd->IsIntConstOpnd()); intptr_t value = opnd->IsAddrOpnd() ? (intptr_t)opnd->AsAddrOpnd()->m_address : opnd->AsIntConstOpnd()->GetValue(); if (value == 0 && instr->m_opcode == Js::OpCode::MOV && !instr->GetDst()->IsRegOpnd() && TySize[opnd->GetType()] >= 4) { Assert(this->linearScan->instrUseRegs.IsEmpty()); // MOV doesn't have an imm8 encoding for 32-bit/64-bit assignment, so if we have a register available, // we should hoist it and generate xor reg, reg and MOV dst, reg BitVector regsBv; regsBv.Copy(this->linearScan->activeRegs); regsBv.Or(this->linearScan->callSetupRegs); regsBv.ComplimentAll(); regsBv.And(this->linearScan->int32Regs); regsBv.Minus(this->linearScan->tempRegs); // Avoid tempRegs BVIndex regIndex = regsBv.GetNextBit(); if (regIndex != BVInvalidIndex) { instr->HoistSrc1(Js::OpCode::MOV, (RegNum)regIndex); this->linearScan->instrUseRegs.Set(regIndex); this->func->m_regsUsed.Set(regIndex); // If we are in a loop, we need to mark the register being used by the loop so that // reload to that register will not be hoisted out of the loop this->linearScan->RecordLoopUse(nullptr, (RegNum)regIndex); } } }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void AggregateCopyPropagation::IterateToFixedpoint() { // We use an iterative data-flow algorithm to propagate the copies // that are available on entry of each block. Add the blocks // in reverse-postorder, this minimizes the number of iterations. StaticList<Block*, 64> worklist; SparseBitVector inWorklist; CFGInfo<Block, Function> cfgInfo(funct_->FirstBlock(), false); auto& postorderList = cfgInfo.PostorderList(); int copyCount = infoList_.Count(); // Add all blocks to the worklist. for(int i = 0; i < postorderList.Count(); i++) { auto block = const_cast<Block*>(postorderList[i]); worklist.Add(block); inWorklist.SetBit(block->Id()); } while(worklist.IsNotEmpty()) { // Extract a block from the worklist. auto block = worklist.RemoveLast(); inWorklist.ResetBit(block->Id()); // Compute the 'in' set, which is the intersection // out the 'out' sets of the predecessors. BitVector inSet(copyCount, false); auto predecessorEnum = block->GetPredecessorEnum(); bool first = true; while(predecessorEnum.IsValid()) { auto predecessorBlock = predecessorEnum.Next(); if(first) { inSet = outSets_[predecessorBlock]; first = false; } else inSet.And(outSets_[predecessorBlock]); } // Save the 'in' set, it's needed later // when we want to eliminate the copies. inSets_.Add(block, inSet); // Now compute the new 'out' set, which is the union of the 'copy' set // with the 'in' set, from which the 'kill' set has been subtracted. // Out(B) = Copy(B) U (In(B) - Kill(B)) BitVector outSet = copySets_[block]; inSet.Difference(killSets_[block]); outSet.Or(inSet); if(outSets_[block] != outSet) { // The 'out' set must be updated, and all successors // must be added to the worklist and reprocessed. outSets_[block] = outSet; auto successorEnum = block->GetSuccessorEnum(); while(successorEnum.IsValid()) { auto successorBlock = successorEnum.Next(); if(inWorklist.IsSet(successorBlock->Id()) == false) { worklist.Add(successorBlock); inWorklist.IsSet(successorBlock->Id()); } } } } }