void fun_llvm_2_nts::process_instruction ( const llvm::Instruction & i, StateInfo & st ) { switch ( i.getOpcode() ) { case Instruction::Alloca: return ctx.m_alloca.process ( bni, st, funmap, i ); case Instruction::Call: return ctx.m_icall.process ( bni, st, funmap, i ); case Instruction::Store: case Instruction::Load: case Instruction::Ret: return ctx.m_ils.process ( bni, st, funmap, i ); case Instruction::Add: return ctx.m_ia.process ( bni, st, funmap, i ); case Instruction::ICmp: return ctx.m_icmp.process ( bni, st, funmap, i ); case Instruction::Br: return ctx.m_ibr.process ( bni, st, funmap, i ); default: { string s ( "Instruction not implemented: " ); throw std::domain_error ( ( s + i.getOpcodeName() ).c_str() ); } } }
/// \brief Set the currently active llvm::Instruction. /// void setActiveInstruction(llvm::Instruction const * const NewActiveInstruction) { ActiveInstruction = NewActiveInstruction; auto const BB = ActiveInstruction->getParent(); if (BB != ActiveBasicBlock) { PreviousBasicBlock = ActiveBasicBlock; ActiveBasicBlock = BB; } }
bool DINOGlobal::isFuncEntryInstruction(llvm::Instruction &I){ llvm::BasicBlock *B = I.getParent(); llvm::Function *F = B->getParent(); llvm::BasicBlock &FuncEntryBlock = F->front(); llvm::Instruction &FuncEntryInst = FuncEntryBlock.front(); if( &I == &FuncEntryInst ){ return true; } return false; }
static bool instMatchesCrit(LLVMDependenceGraph& dg, const llvm::Instruction& I, const std::vector<std::pair<int, std::string>>& parsedCrit) { for (const auto& c : parsedCrit) { auto& Loc = I.getDebugLoc(); if (!Loc) continue; if (static_cast<int>(Loc.getLine()) != c.first) continue; if (isStoreToTheVar(dg, I, c.second) || isLoadOfTheVar(dg, I, c.second)) { llvm::errs() << "Matched line " << c.first << " with variable " << c.second << " to:\n" << I << "\n"; return true; } } return false; }
/// canHoistInst - Return true if the hoister can handle this instruction. bool Hoister::canHoistInst(llvm::Instruction &I, llvm::AliasAnalysis *AA) { // Loads have extra constraints we have to verify before we can hoist them. if (llvm::LoadInst *LI = llvm::dyn_cast<llvm::LoadInst>(&I)) { if (LI->isVolatile()) { return false; // Don't hoist volatile loads! } // Loads from constant memory are always safe to move, even if they end up // in the same alias set as something that ends up being modified. if (AA->pointsToConstantMemory(LI->getOperand(0))) { return true; } // Don't hoist loads which have may-aliased stores in loop. uint64_t Size = 0; if (LI->getType()->isSized()) { #if LLVM_VERSION <= VERSION(3, 7) Size = AA->getTypeStoreSize(LI->getType()); #else Size = I.getModule()->getDataLayout().getTypeStoreSize(LI->getType()); #endif } #if LLVM_VERSION <= VERSION(3, 5) return !CurAST->getAliasSetForPointer(LI->getOperand(0), Size, LI->getMetadata(llvm::LLVMContext::MD_tbaa)).isMod(); #else llvm::AAMDNodes AAInfo; LI->getAAMetadata(AAInfo); return !CurAST->getAliasSetForPointer(LI->getOperand(0), Size, AAInfo).isMod(); #endif } else if (llvm::CallInst *CI = llvm::dyn_cast<llvm::CallInst>(&I)) { // Handle obvious cases efficiently. #if LLVM_VERSION <= VERSION(3, 7) llvm::AliasAnalysis::ModRefBehavior Behavior = AA->getModRefBehavior(CI); #else llvm::FunctionModRefBehavior Behavior = AA->getModRefBehavior(CI); #endif #if LLVM_VERSION <= VERSION(3, 7) if (Behavior == llvm::AliasAnalysis::DoesNotAccessMemory || doesNotAccessMemory(CI->getCalledFunction())) { #else if (Behavior == llvm::FMRB_DoesNotAccessMemory || doesNotAccessMemory(CI->getCalledFunction())) { #endif return true; #if LLVM_VERSION <= VERSION(3, 7) } else if (Behavior == llvm::AliasAnalysis::OnlyReadsMemory) { #else } else if (Behavior == llvm::FMRB_OnlyReadsMemory) { #endif // If this call only reads from memory and there are no writes to memory // in the loop, we can hoist or sink the call as appropriate. bool FoundMod = false; for (llvm::AliasSetTracker::iterator IT = CurAST->begin(), ET = CurAST->end(); IT != ET; ++IT) { llvm::AliasSet &AS = *IT; if (!AS.isForwardingAliasSet() && AS.isMod()) { FoundMod = true; break; } } if (!FoundMod) { return true; } } // FIXME: This should use mod/ref information to see if we can hoist the call. return false; } // Otherwise these instructions are hoistable. if (llvm::isa<llvm::BinaryOperator>(I)) { llvm::BinaryOperator *binop = llvm::cast<llvm::BinaryOperator>(&I); llvm::BinaryOperator::BinaryOps opcode = binop->getOpcode(); if (opcode == llvm::BinaryOperator::Xor) { if (llvm::isa<llvm::ConstantInt>(I.getOperand(1)) && llvm::cast<llvm::ConstantInt>(I.getOperand(1))->isAllOnesValue()) { // it is xor %i, -1 --> actually, it is -%i - 1 return false; } else { return true; } } else if (I.getType()->isFloatingPointTy()) { return true; } else { bool res = (opcode == llvm::BinaryOperator::SDiv); res |= (opcode == llvm::BinaryOperator::UDiv); res |= (opcode == llvm::BinaryOperator::SRem); res |= (opcode == llvm::BinaryOperator::URem); res |= (opcode == llvm::BinaryOperator::AShr); res |= (opcode == llvm::BinaryOperator::LShr); res |= (opcode == llvm::BinaryOperator::Shl); res |= (opcode == llvm::BinaryOperator::And); res |= (opcode == llvm::BinaryOperator::Or); res |= (opcode == llvm::BinaryOperator::Xor); return res; } } else if (llvm::isa<llvm::ZExtInst>(I) || llvm::isa<llvm::SExtInst>(I) || llvm::isa<llvm::TruncInst>(I)) { return true; } else if (llvm::isa<llvm::PHINode>(I)) { return false; } else if (llvm::isa<llvm::PtrToIntInst>(I)) { return true; } else if (llvm::isa<llvm::FPToSIInst>(I) || llvm::isa<llvm::FPToUIInst>(I)) { return true; } else if (llvm::isa<llvm::PointerType>(I.getType())) { return true; } else { return false; } } /// isLoopInvariantInst - Return true if all operands of this instruction are loop invariant. bool Hoister::isLoopInvariantInst(llvm::Loop *L, llvm::Instruction &I) { // The instruction is loop invariant if all of its operands are loop-invariant for (unsigned int i = 0, e = I.getNumOperands(); i != e; ++i) { if (!L->isLoopInvariant(I.getOperand(i))) { return false; } } // If we got this far, the instruction is loop invariant! return true; } /// hoist - When an instruction is found to only use loop invariant operands /// that is safe to hoist, this instruction is called to do the dirty work. void Hoister::hoist(llvm::BasicBlock *preheader, llvm::Instruction &I) { // Remove the instruction from its current basic block... but don't delete the // instruction. I.removeFromParent(); // Insert the new node in Preheader, before the terminator. I.insertBefore(preheader->getTerminator()); changed = true; }
unsigned InstructionCostEstimator::getInstructionCost(const llvm::Instruction &I) { switch (I.getOpcode()) { case llvm::Instruction::GetElementPtr: return Cost::Low; case llvm::Instruction::Ret: case llvm::Instruction::PHI: case llvm::Instruction::Br: return Cost::No; case llvm::Instruction::FRem: case llvm::Instruction::FAdd: case llvm::Instruction::FSub: case llvm::Instruction::FMul: case llvm::Instruction::FDiv: return Cost::Medium; case llvm::Instruction::Add: case llvm::Instruction::Sub: case llvm::Instruction::Mul: case llvm::Instruction::UDiv: case llvm::Instruction::SDiv: case llvm::Instruction::URem: case llvm::Instruction::SRem: case llvm::Instruction::Shl: case llvm::Instruction::LShr: case llvm::Instruction::AShr: case llvm::Instruction::And: case llvm::Instruction::Or: case llvm::Instruction::Xor: return Cost::Low; case llvm::Instruction::Select: return Cost::Low; case llvm::Instruction::ICmp: case llvm::Instruction::FCmp: return Cost::Low; case llvm::Instruction::Store: return Cost::Low; case llvm::Instruction::Load: return Cost::Low; case llvm::Instruction::ZExt: case llvm::Instruction::SExt: case llvm::Instruction::FPToUI: case llvm::Instruction::FPToSI: case llvm::Instruction::FPExt: case llvm::Instruction::PtrToInt: case llvm::Instruction::IntToPtr: case llvm::Instruction::SIToFP: case llvm::Instruction::UIToFP: case llvm::Instruction::Trunc: case llvm::Instruction::FPTrunc: case llvm::Instruction::BitCast: case llvm::Instruction::AddrSpaceCast: return Cost::No; case llvm::Instruction::ExtractElement: return Cost::Low; case llvm::Instruction::InsertElement: return Cost::Low; case llvm::Instruction::ShuffleVector: return Cost::Low; case llvm::Instruction::Call: return Cost::Low; default: return Cost::Low; } }