Beispiel #1
0
void TempScopInfo::buildAccessFunctions(Region &R, ParamSetType &Params,
                                        BasicBlock &BB) {
  AccFuncSetType Functions;
  for (BasicBlock::iterator I = BB.begin(), E = --BB.end(); I != E; ++I) {
    Instruction &Inst = *I;
    if (isa<LoadInst>(&Inst) || isa<StoreInst>(&Inst)) {
      // Create the SCEVAffFunc.
      if (LoadInst *ld = dyn_cast<LoadInst>(&Inst)) {
        unsigned size = TD->getTypeStoreSize(ld->getType());
        Functions.push_back(
          std::make_pair(SCEVAffFunc(SCEVAffFunc::ReadMem, size), &Inst));
      } else {//Else it must be a StoreInst.
        StoreInst *st = cast<StoreInst>(&Inst);
        unsigned size = TD->getTypeStoreSize(st->getValueOperand()->getType());
        Functions.push_back(
          std::make_pair(SCEVAffFunc(SCEVAffFunc::WriteMem, size), &Inst));
      }

      Value *Ptr = getPointerOperand(Inst);
      buildAffineFunction(SE->getSCEV(Ptr), Functions.back().first, R, Params);
    }
  }

  if (Functions.empty())
    return;

  AccFuncSetType &Accs = AccFuncMap[&BB];
  Accs.insert(Accs.end(), Functions.begin(), Functions.end());
}
Beispiel #2
0
void TempScopInfo::buildAccessFunctions(Region &R, BasicBlock &BB) {
  AccFuncSetType Functions;

  for (BasicBlock::iterator I = BB.begin(), E = --BB.end(); I != E; ++I) {
    Instruction &Inst = *I;
    if (isa<LoadInst>(&Inst) || isa<StoreInst>(&Inst)) {
      unsigned Size;
      enum IRAccess::TypeKind Type;

      if (LoadInst *Load = dyn_cast<LoadInst>(&Inst)) {
        Size = TD->getTypeStoreSize(Load->getType());
        Type = IRAccess::READ;
      } else {
        StoreInst *Store = cast<StoreInst>(&Inst);
        Size = TD->getTypeStoreSize(Store->getValueOperand()->getType());
        Type = IRAccess::WRITE;
      }

      const SCEV *AccessFunction = SE->getSCEV(getPointerOperand(Inst));
      const SCEVUnknown *BasePointer =
          dyn_cast<SCEVUnknown>(SE->getPointerBase(AccessFunction));

      assert(BasePointer && "Could not find base pointer");
      AccessFunction = SE->getMinusSCEV(AccessFunction, BasePointer);

      bool IsAffine =
          isAffineExpr(&R, AccessFunction, *SE, BasePointer->getValue());

      Functions.push_back(
          std::make_pair(IRAccess(Type, BasePointer->getValue(), AccessFunction,
                                  Size, IsAffine), &Inst));
    }
  }

  if (Functions.empty())
    return;

  AccFuncSetType &Accs = AccFuncMap[&BB];
  Accs.insert(Accs.end(), Functions.begin(), Functions.end());
}
Beispiel #3
0
void TempScopInfo::buildAccessFunctions(Region &R, BasicBlock &BB,
                                        Region *NonAffineSubRegion) {
  AccFuncSetType Functions;
  Loop *L = LI->getLoopFor(&BB);

  // The set of loops contained in non-affine subregions that are part of R.
  const ScopDetection::BoxedLoopsSetTy *BoxedLoops = SD->getBoxedLoops(&R);

  for (BasicBlock::iterator I = BB.begin(), E = --BB.end(); I != E; ++I) {
    Instruction *Inst = I;
    if (isa<LoadInst>(Inst) || isa<StoreInst>(Inst))
      Functions.push_back(
          std::make_pair(buildIRAccess(Inst, L, &R, BoxedLoops), Inst));

    if (PHINode *PHI = dyn_cast<PHINode>(Inst))
      buildPHIAccesses(PHI, R, Functions, NonAffineSubRegion);

    if (!isa<StoreInst>(Inst) &&
        buildScalarDependences(Inst, &R, NonAffineSubRegion)) {
      // If the Instruction is used outside the statement, we need to build the
      // write access.
      IRAccess ScalarAccess(IRAccess::MUST_WRITE, Inst, ZeroOffset, 1, true);
      Functions.push_back(std::make_pair(ScalarAccess, Inst));
    }
  }

  if (Functions.empty())
    return;

  AccFuncSetType &Accs = AccFuncMap[&BB];
  Accs.insert(Accs.end(), Functions.begin(), Functions.end());
}
Beispiel #4
0
void TempScopInfo::buildPHIAccesses(PHINode *PHI, Region &R,
                                    AccFuncSetType &Functions,
                                    Region *NonAffineSubRegion) {
  if (canSynthesize(PHI, LI, SE, &R))
    return;

  // PHI nodes are modeled as if they had been demoted prior to the SCoP
  // detection. Hence, the PHI is a load of a new memory location in which the
  // incoming value was written at the end of the incoming basic block.
  bool Written = false;
  for (unsigned u = 0; u < PHI->getNumIncomingValues(); u++) {
    Value *Op = PHI->getIncomingValue(u);
    BasicBlock *OpBB = PHI->getIncomingBlock(u);

    if (!R.contains(OpBB))
      continue;

    // Do not build scalar dependences inside a non-affine subregion.
    if (NonAffineSubRegion && NonAffineSubRegion->contains(OpBB))
      continue;

    Instruction *OpI = dyn_cast<Instruction>(Op);
    if (OpI) {
      BasicBlock *OpIBB = OpI->getParent();
      // As we pretend there is a use (or more precise a write) of OpI in OpBB
      // we have to insert a scalar dependence from the definition of OpI to
      // OpBB if the definition is not in OpBB.
      if (OpIBB != OpBB) {
        IRAccess ScalarRead(IRAccess::READ, OpI, ZeroOffset, 1, true);
        AccFuncMap[OpBB].push_back(std::make_pair(ScalarRead, PHI));
        IRAccess ScalarWrite(IRAccess::MUST_WRITE, OpI, ZeroOffset, 1, true);
        AccFuncMap[OpIBB].push_back(std::make_pair(ScalarWrite, OpI));
      }
    }

    // If the operand is a constant, global or argument we need an access
    // instruction and just choose the PHI.
    if (!OpI)
      OpI = PHI;

    Written = true;

    IRAccess ScalarAccess(IRAccess::MUST_WRITE, PHI, ZeroOffset, 1, true);
    AccFuncMap[OpBB].push_back(std::make_pair(ScalarAccess, OpI));
  }

  if (Written) {
    IRAccess ScalarAccess(IRAccess::READ, PHI, ZeroOffset, 1, true);
    Functions.push_back(std::make_pair(ScalarAccess, PHI));
  }
}