void MemoryValue::dumpMeta(CommaPrinter& comma, PrintStream& out) const { if (m_offset) out.print(comma, "offset = ", m_offset); if ((isLoad() && effects().reads != range()) || (isStore() && effects().writes != range())) out.print(comma, "range = ", range()); }
/* Funct m, stage 4 / Memory, assumes the em and mw Baskets */ void m(MIPS_SIM* sim, EMB* emBasket, MWB* mwBasket) /* memory write */ { if(emBasket->aluOut != 0) { int opc = emBasket->ir >> 26; printf("--- In Mem ---\n"); if(isStore(opc)) /* For Store Word Insturctions */ { printf("in m: exe store type\n"); switch(opc) { case 0x28: /* store byte */ mem[emBasket->aluOut] = emBasket->bReg & 0x000000FF; break; case 0x29: /* store half word */ mem[emBasket->aluOut] = emBasket->bReg & 0x0000FFFF; break; case 0x2B: /* store word */ mem[emBasket->aluOut] = emBasket->bReg; break; } printRegs(sim); clearem(emBasket); } else /* For Load Word Instrustions */ { if(mwBasket->wBusy) return; else { printf("in mem: exe load type\n"); mwBasket->wBusy = 1; mwBasket->type = 2; mwBasket->mdr = mem[emBasket->aluOut]; /* write to mdr */ clearem(emBasket); } } }
void SimpleAliasAnalysis::analyze(ir::IRKernel& kernel) { // Functions can be called _aStoreCanReachThisFunction = !kernel.function(); _kernel = &kernel; if(_aStoreCanReachThisFunction) return; for(auto block = kernel.cfg()->begin(); block != kernel.cfg()->end(); ++block) { for(auto instruction = block->instructions.begin(); instruction != block->instructions.end(); ++instruction) { auto ptx = static_cast<ir::PTXInstruction*>(*instruction); if(ptx->isStore()) { _aStoreCanReachThisFunction = true; return; } } } }
void MemMap::optimizeMemoryAccesses(Trace* trace) { StoreList tracking; for (IRInstruction* inst : trace->getInstructionList()) { // initialize each instruction as live inst->setId(LIVE); int offset = -1; Opcode op = inst->getOpcode(); if (isLoad(op)) { if (op == LdProp) { offset = inst->getSrc(1)->getConstValAsInt(); } optimizeLoad(inst, offset); } else if (isStore(op)) { if (op == StProp || op == StPropNT) { offset = inst->getSrc(1)->getConstValAsInt(); } // if we see a store, first check if its last available access is a store // if it is, then the last access is a dead store IRInstruction* access = getLastAccess(inst->getSrc(0), offset); if (access != NULL && isStore(access->getOpcode())) { // if a dead St* is followed by a St*NT, then the second store needs to // now write in the type because the first store will be removed if (access->getOpcode() == StProp && op == StPropNT) { inst->setOpcode(StProp); } else if (access->getOpcode() == StLoc && op == StLocNT) { inst->setOpcode(StLoc); } else if (access->getOpcode() == StRef && op == StRefNT) { inst->setOpcode(StRef); } access->setId(DEAD); } // start tracking the current store tracking.push_back(std::make_pair(inst, std::vector<IRInstruction*>())); } else if (inst->mayRaiseError()) { // if the function has an exit edge that we don't know anything about // (raising an error), then all stores we're currently tracking need to // be erased. all stores already declared dead are untouched StoreList::iterator it, end; for (it = tracking.begin(), end = tracking.end(); it != end; ) { StoreList::iterator copy = it; ++it; if (copy->first->getId() != DEAD) { // XXX: t1779667 tracking.erase(copy); } } } // if the current instruction is guarded, make sure all of our stores that // are not yet dead know about it if (inst->getLabel() != NULL) { for (auto& entry : tracking) { if (entry.first->getId() != DEAD) { entry.second.push_back(inst); } } } Simplifier::copyProp(inst); processInstruction(inst); } sinkStores(tracking); // kill the dead stores removeDeadInstructions(trace); }
void MemMap::optimizeMemoryAccesses(Trace* trace) { if (hasInternalFlow(trace)) { // This algorithm only works with linear traces. // TODO t2066994: reset state after each block, at least. return; } StoreList tracking; const Func* curFunc = nullptr; for (Block* block : trace->getBlocks()) { for (IRInstruction& inst : *block) { if (inst.getOpcode() == Marker) { curFunc = inst.getExtra<Marker>()->func; } // initialize each instruction as live setLive(inst, true); int offset = -1; Opcode op = inst.getOpcode(); if (isLoad(op)) { if (op == LdProp) { offset = inst.getSrc(1)->getValInt(); } // initialize each instruction as live setLive(inst, true); optimizeLoad(&inst, offset); } else if (isStore(op)) { if (op == StProp || op == StPropNT) { offset = inst.getSrc(1)->getValInt(); } // if we see a store, first check if its last available access is a store // if it is, then the last access is a dead store auto access = inst.getOpcode() == StLoc || inst.getOpcode() == StLocNT ? lastLocalAccess(inst.getExtra<LocalId>()->locId) : getLastAccess(inst.getSrc(0), offset); if (access && isStore(access->getOpcode())) { // if a dead St* is followed by a St*NT, then the second store needs to // now write in the type because the first store will be removed if (access->getOpcode() == StProp && op == StPropNT) { inst.setOpcode(StProp); } else if (access->getOpcode() == StLoc && op == StLocNT) { inst.setOpcode(StLoc); } else if (access->getOpcode() == StRef && op == StRefNT) { inst.setOpcode(StRef); } setLive(*access, false); } // start tracking the current store tracking.push_back(std::make_pair(&inst, std::vector<IRInstruction*>())); } else if (inst.mayRaiseError()) { // if the function has an exit edge that we don't know anything about // (raising an error), then all stores we're currently tracking need to // be erased. all stores already declared dead are untouched StoreList::iterator it, end; for (it = tracking.begin(), end = tracking.end(); it != end; ) { StoreList::iterator copy = it; ++it; if (isLive(copy->first)) { // XXX: t1779667 tracking.erase(copy); } } } // if the current instruction is guarded, make sure all of our stores that // are not yet dead know about it if (inst.getTaken()) { for (auto& entry : tracking) { if (isLive(entry.first)) { entry.second.push_back(&inst); } } } Simplifier::copyProp(&inst); processInstruction(&inst, curFunc && curFunc->isPseudoMain()); } } sinkStores(tracking); // kill the dead stores removeDeadInstructions(trace, m_liveInsts); }
bool Instruction::isMemop(){ return (isLoad() || isStore()); }
bool Instruction::accessesMemory() const { return isLoad() || isStore(); }