コード例 #1
0
ファイル: MemorySSA.cpp プロジェクト: CAFxX/llvm-1
TEST_F(MemorySSATest, RemoveMemoryAccess) {
  // We create a diamond where there is a store on one side, and then a load
  // after the merge point.  This enables us to test a bunch of different
  // removal cases.
  F = Function::Create(
      FunctionType::get(B.getVoidTy(), {B.getInt8PtrTy()}, false),
      GlobalValue::ExternalLinkage, "F", &M);
  BasicBlock *Entry(BasicBlock::Create(C, "", F));
  BasicBlock *Left(BasicBlock::Create(C, "", F));
  BasicBlock *Right(BasicBlock::Create(C, "", F));
  BasicBlock *Merge(BasicBlock::Create(C, "", F));
  B.SetInsertPoint(Entry);
  B.CreateCondBr(B.getTrue(), Left, Right);
  B.SetInsertPoint(Left);
  Argument *PointerArg = &*F->arg_begin();
  StoreInst *StoreInst = B.CreateStore(B.getInt8(16), PointerArg);
  BranchInst::Create(Merge, Left);
  BranchInst::Create(Merge, Right);
  B.SetInsertPoint(Merge);
  LoadInst *LoadInst = B.CreateLoad(PointerArg);

  setupAnalyses();
  MemorySSA &MSSA = Analyses->MSSA;
  MemorySSAWalker *Walker = &*Analyses->Walker;

  // Before, the load will be a use of a phi<store, liveonentry>. It should be
  // the same after.
  MemoryUse *LoadAccess = cast<MemoryUse>(MSSA.getMemoryAccess(LoadInst));
  MemoryDef *StoreAccess = cast<MemoryDef>(MSSA.getMemoryAccess(StoreInst));
  MemoryAccess *DefiningAccess = LoadAccess->getDefiningAccess();
  EXPECT_TRUE(isa<MemoryPhi>(DefiningAccess));
  // The load is currently clobbered by one of the phi arguments, so the walker
  // should determine the clobbering access as the phi.
  EXPECT_EQ(DefiningAccess, Walker->getClobberingMemoryAccess(LoadInst));
  MSSA.removeMemoryAccess(StoreAccess);
  MSSA.verifyMemorySSA();
  // After the removeaccess, let's see if we got the right accesses
  // The load should still point to the phi ...
  EXPECT_EQ(DefiningAccess, LoadAccess->getDefiningAccess());
  // but we should now get live on entry for the clobbering definition of the
  // load, since it will walk past the phi node since every argument is the
  // same.
  EXPECT_TRUE(
      MSSA.isLiveOnEntryDef(Walker->getClobberingMemoryAccess(LoadInst)));

  // The phi should now be a two entry phi with two live on entry defs.
  for (const auto &Op : DefiningAccess->operands()) {
    MemoryAccess *Operand = cast<MemoryAccess>(&*Op);
    EXPECT_TRUE(MSSA.isLiveOnEntryDef(Operand));
  }

  // Now we try to remove the single valued phi
  MSSA.removeMemoryAccess(DefiningAccess);
  MSSA.verifyMemorySSA();
  // Now the load should be a load of live on entry.
  EXPECT_TRUE(MSSA.isLiveOnEntryDef(LoadAccess->getDefiningAccess()));
}
コード例 #2
0
ファイル: JITOptimize.cpp プロジェクト: ajwlucas/tool_axe
static unsigned
getFlagsForCheck(const MemoryAccess &access)
{
    unsigned flags = 0;
    if (access.getSize() > 1)
        flags |= MemoryCheck::CheckAlignment;
    flags |= MemoryCheck::CheckAddress;
    if (access.getIsStore())
        flags |= MemoryCheck::CheckInvalidation;
    return flags;
}
コード例 #3
0
ファイル: x86_64_systemv.cpp プロジェクト: EgoIncarnate/fcd
bool CallingConvention_x86_64_systemv::analyzeCallSite(ParameterRegistry &registry, CallInformation &fillOut, CallSite cs)
{
	fillOut.clear();
	TargetInfo& targetInfo = registry.getTargetInfo();
	
	Instruction& inst = *cs.getInstruction();
	Function& caller = *inst.getParent()->getParent();
	MemorySSA& mssa = *registry.getMemorySSA(caller);
	MemoryAccess* thisDef = mssa.getMemoryAccess(&inst);
	
	identifyParameterCandidates(targetInfo, mssa, thisDef->getDefiningAccess(), fillOut);
	identifyReturnCandidates(targetInfo, mssa, thisDef, fillOut);
	return true;
}
コード例 #4
0
void MemoryReservationDirective::execute(
    const ExecuteImmutableArguments& immutable,
    CompileErrorList& errors,
    FinalCommandVector& commandOutput,
    MemoryAccess& memoryAccess) {
  // Finally, we may put some zeros into memory.
  if (_size > 0) {
    memoryAccess.putMemoryValueAt(_absolutePosition, MemoryValue(_size));
  }
}
コード例 #5
0
ファイル: mssa.cpp プロジェクト: yu810226/MemorySSA
bool mssa::runOnFunction(Function &F) {
    
    MemorySSA *MSSA = &getAnalysis<MemorySSAWrapperPass>().getMSSA();
    //MemorySSAWalker MAW = new MemorySSAWalker(MSSA);
    errs()<<"\n";

    for (Function::iterator BB = F.begin(); BB != F.end(); BB++){
	errs() << "Basic block (name=" << BB->getName() << ")\n"; 
	
	//Get MemoryPhi and print it out
	MemoryPhi* MP = MSSA->getMemoryAccess(dyn_cast<BasicBlock>(BB));
	if (MP != NULL)
	    MP->dump();
        for (BasicBlock::iterator itrIns = (*BB).begin(); itrIns != (*BB).end(); itrIns++) {
	    //MemoryAccess* MA = MAW.getClobberingMemoryAccess(itrIns);
	    //MemoryLocation Location;
	    //MemoryAccess* MAR = MAW.getClobberingMemoryAccess(MA,&Location);
	    //MAR->dump();
	    errs()<<"Instruction: "<< *itrIns <<"\n";

	    //Get MemoryDef or MemoryUse and print it out
	    MemoryAccess *MA = MSSA->getMemoryAccess(dyn_cast<Value>(itrIns));
	    if (MA != NULL) {
	    	MA->dump();
		//if(MSSA->isLiveOnEntryDef(MA))

		//Get immediate MemoryDef of the instruction annotated MemoryDef/MemoryUse
    		for (memoryaccess_def_iterator MAitr = MA->defs_begin(); 
		     MAitr != MA->defs_end(); 
		     MAitr++)
		{
		     errs()<<"Def: "<<**MAitr<<"\n";
		     //Get the instruction the immediate Memory Def annotation represent
		     Instruction* u = cast<MemoryUseOrDef>(*MAitr)->getMemoryInst();
		     if (u != NULL)
			errs()<<"     Def Inst: "<<*u<<"\n";
		}	
	    }
	}
    }
    return 0;
}
コード例 #6
0
ファイル: MemorySSA.cpp プロジェクト: AnachroNia/llvm
TEST(MemorySSA, RemoveMemoryAccess) {
  LLVMContext C;
  std::unique_ptr<Module> M(new Module("Remove memory access", C));
  IRBuilder<> B(C);
  DataLayout DL("e-i64:64-f80:128-n8:16:32:64-S128");
  TargetLibraryInfoImpl TLII;
  TargetLibraryInfo TLI(TLII);

  // We create a diamond where there is a store on one side, and then a load
  // after the merge point.  This enables us to test a bunch of different
  // removal cases.
  Function *F = Function::Create(
      FunctionType::get(B.getVoidTy(), {B.getInt8PtrTy()}, false),
      GlobalValue::ExternalLinkage, "F", M.get());
  BasicBlock *Entry(BasicBlock::Create(C, "", F));
  BasicBlock *Left(BasicBlock::Create(C, "", F));
  BasicBlock *Right(BasicBlock::Create(C, "", F));
  BasicBlock *Merge(BasicBlock::Create(C, "", F));
  B.SetInsertPoint(Entry);
  B.CreateCondBr(B.getTrue(), Left, Right);
  B.SetInsertPoint(Left);
  Argument *PointerArg = &*F->arg_begin();
  StoreInst *StoreInst = B.CreateStore(B.getInt8(16), PointerArg);
  BranchInst::Create(Merge, Left);
  BranchInst::Create(Merge, Right);
  B.SetInsertPoint(Merge);
  LoadInst *LoadInst = B.CreateLoad(PointerArg);

  std::unique_ptr<MemorySSA> MSSA(new MemorySSA(*F));
  std::unique_ptr<DominatorTree> DT(new DominatorTree(*F));
  std::unique_ptr<AssumptionCache> AC(new AssumptionCache(*F));
  AAResults AA(TLI);
  BasicAAResult BAA(DL, TLI, *AC, &*DT);
  AA.addAAResult(BAA);
  std::unique_ptr<MemorySSAWalker> Walker(MSSA->buildMemorySSA(&AA, &*DT));
  // Before, the load will be a use of a phi<store, liveonentry>. It should be
  // the same after.
  MemoryUse *LoadAccess = cast<MemoryUse>(MSSA->getMemoryAccess(LoadInst));
  MemoryDef *StoreAccess = cast<MemoryDef>(MSSA->getMemoryAccess(StoreInst));
  MemoryAccess *DefiningAccess = LoadAccess->getDefiningAccess();
  EXPECT_TRUE(isa<MemoryPhi>(DefiningAccess));
  // The load is currently clobbered by one of the phi arguments, so the walker
  // should determine the clobbering access as the phi.
  EXPECT_EQ(DefiningAccess, Walker->getClobberingMemoryAccess(LoadInst));
  MSSA->removeMemoryAccess(StoreAccess);
  MSSA->verifyMemorySSA();
  // After the removeaccess, let's see if we got the right accesses
  // The load should still point to the phi ...
  EXPECT_EQ(DefiningAccess, LoadAccess->getDefiningAccess());
  // but we should now get live on entry for the clobbering definition of the
  // load, since it will walk past the phi node since every argument is the
  // same.
  EXPECT_TRUE(
      MSSA->isLiveOnEntryDef(Walker->getClobberingMemoryAccess(LoadInst)));

  // The phi should now be a two entry phi with two live on entry defs.
  for (const auto &Op : DefiningAccess->operands()) {
    MemoryAccess *Operand = cast<MemoryAccess>(&*Op);
    EXPECT_TRUE(MSSA->isLiveOnEntryDef(Operand));
  }

  // Now we try to remove the single valued phi
  MSSA->removeMemoryAccess(DefiningAccess);
  MSSA->verifyMemorySSA();
  // Now the load should be a load of live on entry.
  EXPECT_TRUE(MSSA->isLiveOnEntryDef(LoadAccess->getDefiningAccess()));
}
コード例 #7
0
FinalRepresentation
IntermediateRepresentator::transform(const TransformationParameters& parameters,
                                     const CompileErrorList& parsingErrors,
                                     MemoryAccess& memoryAccess) {
  auto errors = parsingErrors;
  if (_currentOutput) {
    errors.pushError(_currentOutput->positionInterval(),
                     "Macro not closed. Missing a macro end directive?");
  }

  PrecompileImmutableArguments precompileArguments(parameters.architecture(),
                                                   parameters.generator());

  SymbolGraph graph;
  MacroDirectiveTable macroTable;
  for (const auto& command : _commandList) {
    command->precompile(precompileArguments, errors, graph, macroTable);
  }

  IntermediateMacroInstruction::replaceWithMacros(
      _commandList.begin(), _commandList.end(), macroTable, errors);

  auto macroList = generateMacroInformation();
  auto preliminaryEvaluation = graph.evaluate();

  if (!evaluateGraph(preliminaryEvaluation, errors)) {
    return FinalRepresentation({}, errors, macroList);
  }

  SymbolReplacer preliminaryReplacer(preliminaryEvaluation);

  MemoryAllocator allocator(parameters.allocator());
  SectionTracker tracker;

  auto allowedSize = memoryAccess.getMemorySize().get();
  IntermediateOperationPointer firstMemoryExceedingOperation(nullptr);

  AllocateMemoryImmutableArguments allocateMemoryArguments(precompileArguments,
                                                           preliminaryReplacer);

  for (const auto& command : _commandList) {
    command->allocateMemory(
        allocateMemoryArguments, errors, allocator, tracker);
    if (allocator.estimateSize() > allowedSize &&
        !firstMemoryExceedingOperation) {
      firstMemoryExceedingOperation = command;
    }
  }

  auto allocatedSize = allocator.calculatePositions();

  EnhanceSymbolTableImmutableArguments symbolTableArguments(
      allocateMemoryArguments, allocator);
  for (const auto& command : _commandList) {
    command->enhanceSymbolTable(symbolTableArguments, errors, graph);
  }

  auto graphEvaluation = graph.evaluate();
  auto graphValid = evaluateGraph(graphEvaluation, errors);
  auto memoryValid = checkMemorySize(
      allocatedSize, allowedSize, firstMemoryExceedingOperation, errors);
  if (!(graphValid && memoryValid)) {
    return FinalRepresentation({}, errors, macroList);
  }

  SymbolReplacer replacer(graphEvaluation);
  ExecuteImmutableArguments executeArguments(symbolTableArguments, replacer);
  FinalCommandVector commandOutput;
  for (const auto& command : _commandList) {
    command->execute(executeArguments, errors, commandOutput, memoryAccess);
  }

  return FinalRepresentation(commandOutput, errors, macroList);
}
コード例 #8
0
ファイル: MemorySSAUpdater.cpp プロジェクト: Lucretia/llvm
void MemorySSAUpdater::fixupDefs(const SmallVectorImpl<WeakVH> &Vars) {
  SmallPtrSet<const BasicBlock *, 8> Seen;
  SmallVector<const BasicBlock *, 16> Worklist;
  for (auto &Var : Vars) {
    MemoryAccess *NewDef = dyn_cast_or_null<MemoryAccess>(Var);
    if (!NewDef)
      continue;
    // First, see if there is a local def after the operand.
    auto *Defs = MSSA->getWritableBlockDefs(NewDef->getBlock());
    auto DefIter = NewDef->getDefsIterator();

    // The temporary Phi is being fixed, unmark it for not to optimize.
    if (MemoryPhi *Phi = dyn_cast<MemoryPhi>(NewDef))
      NonOptPhis.erase(Phi);

    // If there is a local def after us, we only have to rename that.
    if (++DefIter != Defs->end()) {
      cast<MemoryDef>(DefIter)->setDefiningAccess(NewDef);
      continue;
    }

    // Otherwise, we need to search down through the CFG.
    // For each of our successors, handle it directly if their is a phi, or
    // place on the fixup worklist.
    for (const auto *S : successors(NewDef->getBlock())) {
      if (auto *MP = MSSA->getMemoryAccess(S))
        setMemoryPhiValueForBlock(MP, NewDef->getBlock(), NewDef);
      else
        Worklist.push_back(S);
    }

    while (!Worklist.empty()) {
      const BasicBlock *FixupBlock = Worklist.back();
      Worklist.pop_back();

      // Get the first def in the block that isn't a phi node.
      if (auto *Defs = MSSA->getWritableBlockDefs(FixupBlock)) {
        auto *FirstDef = &*Defs->begin();
        // The loop above and below should have taken care of phi nodes
        assert(!isa<MemoryPhi>(FirstDef) &&
               "Should have already handled phi nodes!");
        // We are now this def's defining access, make sure we actually dominate
        // it
        assert(MSSA->dominates(NewDef, FirstDef) &&
               "Should have dominated the new access");

        // This may insert new phi nodes, because we are not guaranteed the
        // block we are processing has a single pred, and depending where the
        // store was inserted, it may require phi nodes below it.
        cast<MemoryDef>(FirstDef)->setDefiningAccess(getPreviousDef(FirstDef));
        return;
      }
      // We didn't find a def, so we must continue.
      for (const auto *S : successors(FixupBlock)) {
        // If there is a phi node, handle it.
        // Otherwise, put the block on the worklist
        if (auto *MP = MSSA->getMemoryAccess(S))
          setMemoryPhiValueForBlock(MP, FixupBlock, NewDef);
        else {
          // If we cycle, we should have ended up at a phi node that we already
          // processed.  FIXME: Double check this
          if (!Seen.insert(S).second)
            continue;
          Worklist.push_back(S);
        }
      }
    }
  }
}
コード例 #9
0
ファイル: MemorySSAUpdater.cpp プロジェクト: Lucretia/llvm
// A brief description of the algorithm:
// First, we compute what should define the new def, using the SSA
// construction algorithm.
// Then, we update the defs below us (and any new phi nodes) in the graph to
// point to the correct new defs, to ensure we only have one variable, and no
// disconnected stores.
void MemorySSAUpdater::insertDef(MemoryDef *MD, bool RenameUses) {
  InsertedPHIs.clear();

  // See if we had a local def, and if not, go hunting.
  MemoryAccess *DefBefore = getPreviousDef(MD);
  bool DefBeforeSameBlock = DefBefore->getBlock() == MD->getBlock();

  // There is a def before us, which means we can replace any store/phi uses
  // of that thing with us, since we are in the way of whatever was there
  // before.
  // We now define that def's memorydefs and memoryphis
  if (DefBeforeSameBlock) {
    for (auto UI = DefBefore->use_begin(), UE = DefBefore->use_end();
         UI != UE;) {
      Use &U = *UI++;
      // Leave the uses alone
      if (isa<MemoryUse>(U.getUser()))
        continue;
      U.set(MD);
    }
  }

  // and that def is now our defining access.
  // We change them in this order otherwise we will appear in the use list
  // above and reset ourselves.
  MD->setDefiningAccess(DefBefore);

  SmallVector<WeakVH, 8> FixupList(InsertedPHIs.begin(), InsertedPHIs.end());
  if (!DefBeforeSameBlock) {
    // If there was a local def before us, we must have the same effect it
    // did. Because every may-def is the same, any phis/etc we would create, it
    // would also have created.  If there was no local def before us, we
    // performed a global update, and have to search all successors and make
    // sure we update the first def in each of them (following all paths until
    // we hit the first def along each path). This may also insert phi nodes.
    // TODO: There are other cases we can skip this work, such as when we have a
    // single successor, and only used a straight line of single pred blocks
    // backwards to find the def.  To make that work, we'd have to track whether
    // getDefRecursive only ever used the single predecessor case.  These types
    // of paths also only exist in between CFG simplifications.
    FixupList.push_back(MD);
  }

  while (!FixupList.empty()) {
    unsigned StartingPHISize = InsertedPHIs.size();
    fixupDefs(FixupList);
    FixupList.clear();
    // Put any new phis on the fixup list, and process them
    FixupList.append(InsertedPHIs.begin() + StartingPHISize, InsertedPHIs.end());
  }
  // Now that all fixups are done, rename all uses if we are asked.
  if (RenameUses) {
    SmallPtrSet<BasicBlock *, 16> Visited;
    BasicBlock *StartBlock = MD->getBlock();
    // We are guaranteed there is a def in the block, because we just got it
    // handed to us in this function.
    MemoryAccess *FirstDef = &*MSSA->getWritableBlockDefs(StartBlock)->begin();
    // Convert to incoming value if it's a memorydef. A phi *is* already an
    // incoming value.
    if (auto *MD = dyn_cast<MemoryDef>(FirstDef))
      FirstDef = MD->getDefiningAccess();

    MSSA->renamePass(MD->getBlock(), FirstDef, Visited);
    // We just inserted a phi into this block, so the incoming value will become
    // the phi anyway, so it does not matter what we pass.
    for (auto &MP : InsertedPHIs) {
      MemoryPhi *Phi = dyn_cast_or_null<MemoryPhi>(MP);
      if (Phi)
        MSSA->renamePass(Phi->getBlock(), nullptr, Visited);
    }
  }
}
コード例 #10
0
ファイル: JITOptimize.cpp プロジェクト: ajwlucas/tool_axe
void axe::
placeMemoryChecks(std::vector<InstructionOpcode> &opcode,
                  std::vector<Operands> &operands,
                  std::queue<std::pair<uint32_t,MemoryCheck*> > &checks)
{
    MemoryCheckState state;

    std::vector<MemoryCheckCandidate> candidates;
    // Gather expressions for memory accesses.
    for (unsigned i = 0, e = opcode.size(); i != e; ++i) {
        InstructionOpcode opc = opcode[i];
        const Operands &ops = operands[i];
        InstructionProperties &properties = instructionProperties[opc];
        MemoryAccess access;
        if (properties.memCheckHoistingOptEnabled() &&
                getInstructionMemoryAccess(opc, ops, access)) {
            assert(access.getOffsetImm() % access.getSize() == 0);
            // Compute the first offset where all registers are available.
            unsigned first = state.regDefs[access.getBaseReg()];
            if (access.getScale())
                first = std::min(first, state.regDefs[access.getOffsetReg()]);
            unsigned flags = getFlagsForCheck(access);
            bool updateBaseRegAlign = false;
            if (flags & MemoryCheck::CheckAlignment) {
                assert(access.getScale() == 0 ||
                       (access.getScale() % access.getSize()) == 0);
                assert((access.getOffsetImm() % access.getSize()) == 0);
                unsigned size = access.getSize();
                if ((state.getMinAlignment(access.getBaseReg()) % size) == 0) {
                    flags &= ~MemoryCheck::CheckAlignment;
                } else {
                    updateBaseRegAlign = true;
                }
            }
            MemoryCheck *check =
                new MemoryCheck(access.getSize(), access.getBaseReg(),
                                access.getScale(), access.getOffsetReg(),
                                access.getOffsetImm(), flags);
            candidates.push_back(MemoryCheckCandidate(first, i, check));
            if (updateBaseRegAlign) {
                state.setMinAlignment(access.getBaseReg(), access.getSize());
            }
        }
        // Update regDefs.
        state.update(opc, ops, i + 1);
    }
    if (candidates.empty())
        return;

    for (unsigned index = 0, size = candidates.size(); index < size; index++) {
        checks.push(std::make_pair(candidates[index].getInstructionIndex(),
                                   candidates[index].getMemoryCheck()));
    }
}