/* the instruction's result is considered an output if it's - a memory write - used outside its basic block - used in the block's terminator instruction (e.g. a return statement) */ bool Primitives::isOutputForBasicBlock(const Instruction *inst) { // memory write? if (isa<StoreInst>(inst)) return true; // used outside of its basic block? const BasicBlock *bb = inst->getParent(); if (isUsedOutsideOfBlock(inst, bb)) return true; // check terminator instruction const TerminatorInst *ti = bb->getTerminator(); if (ti != NULL) { if (isa<InvokeInst>(ti) || isa<ReturnInst>(ti) || isa<SwitchInst>(ti) || isa<BranchInst>(ti)) { for (User::const_op_iterator oi = ti->op_begin(), oe = ti->op_end(); oi != oe; ++oi) { const Value* v = oi->get(); if (isa<Instruction>(v) && v == inst) return true; } } } return false; }
/*! * Find the max possible offset for an object pointed to by (V). */ std::vector<LocationSet> SymbolTableInfo::getFlattenedFields(const Value *V) { assert(V); std::vector<LocationSet> fields; fields.push_back(LocationSet(0)); const Type *T = V->getType(); // Use the biggest struct type out of all operands. if (const User *U = dyn_cast<User>(V)) { Size_t msz = 1; //the max size seen so far for (User::const_op_iterator it = U->op_begin(), ie = U->op_end(); it != ie; ++it) { T = it->get()->getType(); Size_t sz = getFields(fields, T, msz); if (msz < sz) msz = sz; } } //If V is a CE or bitcast, the actual pointer type is its operand. else if (isa<ConstantExpr>(V) || isa<BitCastInst>(V)) { if (const ConstantExpr *E = dyn_cast<ConstantExpr>(V)) T = E->getOperand(0)->getType(); else if (const BitCastInst *BI = dyn_cast<BitCastInst>(V)) T = BI->getOperand(0)->getType(); getFields(fields, T, 0); } return fields; }
unsigned int ArchitectureVirtual::getSwInstructionTiming(const llvm::Instruction* inst) const { if (isa<BinaryOperator>(inst)) { const BinaryOperator *binop = cast<BinaryOperator>(inst); bool floatingPoint = false; for (User::const_op_iterator oi = inst->op_begin(), oe = inst->op_end(); oi != oe; ++oi) { if (oi->get()->getType()->isFloatingPoint()) { floatingPoint = true; break; } } int opcode = binop->getOpcode(); if (!floatingPoint) { if (opcode == Instruction::UDiv || opcode == Instruction::URem || opcode == Instruction::SDiv || opcode == Instruction::SRem) return 15; else if (opcode == Instruction::Mul) return 5; else return 1; } else { switch (opcode) { case Instruction::Add: case Instruction::Sub: case Instruction::FCmp: return 50; case Instruction::Mul: return 100; case Instruction::FPToUI: case Instruction::FPToSI: case Instruction::SIToFP: case Instruction::UIToFP: case Instruction::FPExt: case Instruction::FPTrunc: return 40; case Instruction::FDiv: case Instruction::FRem: return 1500; } } } else if (isa<StoreInst>(inst) || isa<LoadInst>(inst)) return 2; else if (isa<TerminatorInst>(inst)) return 3; else if (isa<BitCastInst>(inst) || isa<PtrToIntInst>(inst) || isa<IntToPtrInst>(inst)) return 0; return 1; }
bool SomeOperandIsSPPointer(std::set<const Value*> &SpPointers, const Instruction *I) { for (User::const_op_iterator OI = I->op_begin(), OE = I->op_end(); OI != OE; ++OI) { if (SpPointers.find(OI->get()) != SpPointers.end()) { return true; } } return false; }
bool TempScopInfo::isReduction(BasicBlock &BB) { int loadAccess = 0, storeAccess = 0; const StoreInst *storeInst; const Value *storePointer; const LoadInst *loadInst[2]; const Value *loadPointer[2]; for (BasicBlock::iterator I = BB.begin(), E = --BB.end(); I != E; ++I) { Instruction &Inst = *I; if (isa<LoadInst>(&Inst)) { if (loadAccess >= 2) return false; loadInst[loadAccess] = dyn_cast<LoadInst>(&Inst); loadPointer[loadAccess] = loadInst[loadAccess]->getPointerOperand(); loadAccess++; } else if (isa<StoreInst>(&Inst)) { if (storeAccess >= 1) return false; storeInst = dyn_cast<StoreInst>(&Inst); storePointer = storeInst->getPointerOperand(); storeAccess++; } } if (loadAccess < 2) return false; if (loadPointer[0] == loadPointer[1]) return false; const Value *reductionLoadInst; if (storePointer == loadPointer[0]) reductionLoadInst = loadInst[0]; else if (storePointer == loadPointer[1]) reductionLoadInst = loadInst[1]; else return false; const Instruction *reductionInst = dyn_cast<Instruction>(storeInst->getValueOperand()); // Check if the value stored is an instruction if (!reductionInst) return false; // Reduction operations must be associative and commutative if (!reductionInst->isAssociative() || !reductionInst->isCommutative()) return false; // Check if this instruction is using the loaded value for (User::const_op_iterator I = reductionInst->op_begin(), E = reductionInst->op_end(); I != E; I++) { const Value *operand = I->get(); if (operand == reductionLoadInst) { // The loaded value's one and only use must be this one. return operand->hasOneUse(); } } return false; }
/* 1 HW unit = 0.1 SW units */ unsigned int ArchitectureVirtual::getHwInstructionTiming(const llvm::Instruction* inst) const { // casts are 'free' if (isa<BitCastInst>(inst) || isa<TruncInst>(inst) || isa<ZExtInst>(inst) || isa<SExtInst>(inst) || isa<PtrToIntInst>(inst) || isa<IntToPtrInst>(inst)) return 0; if (isa<BinaryOperator>(inst)) { const BinaryOperator *binop = cast<BinaryOperator>(inst); int opcode = binop->getOpcode(); bool constantOperand = false, floatingPoint = false; for (User::const_op_iterator oi = inst->op_begin(), oe = inst->op_end(); oi != oe; ++oi) { if (isa<Constant>(oi->get())) constantOperand = true; if (oi->get()->getType()->isFloatingPoint()) floatingPoint = true; } switch (opcode) { // arithmetic operations case Instruction::Add: case Instruction::Sub: return floatingPoint ? 100 : (constantOperand ? 6 : 8); case Instruction::UDiv: case Instruction::SDiv: return constantOperand ? 45 : 75; case Instruction::URem: case Instruction::SRem: return constantOperand ? 100: 125; case Instruction::Mul: return floatingPoint ? 175 : (constantOperand ? 35 : 45); // logical operations case Instruction::Xor: case Instruction::And: case Instruction::Or: return constantOperand ? 6 : 8; // shift instructions case Instruction::Shl: case Instruction::LShr: case Instruction::AShr: return constantOperand ? 7 : 9; // floating point operations case Instruction::FPToUI: case Instruction::FPToSI: case Instruction::SIToFP: case Instruction::UIToFP: case Instruction::FPExt: case Instruction::FPTrunc: return 75; case Instruction::FCmp: return 100; case Instruction::FDiv: case Instruction::FRem: return 400; } } else if (isa<CmpInst>(inst)) { bool constantOperand = false; for (User::const_op_iterator oi = inst->op_begin(), oe = inst->op_end(); oi != oe; ++oi) { if (isa<Constant>(oi->get())) { constantOperand = true; break; } } if (cast<CmpInst>(inst)->getPredicate() > 31) return (constantOperand ? 6 : 8); // integer comparison else return 100; } return 10; }