bool RelativeMinMax::getMinMax(Expr Ex, Expr &Min, Expr &Max) {
  if (Ex.isConstant()) {
    Min = Ex;
    Max = Ex;
  } else if (Ex.isSymbol()) {
    // Bounds of induction variables have special treatment.
    if (PHINode *Phi = dyn_cast<PHINode>(Ex.getSymbolValue())) {
      if (Loop *L = LIE_->getLoopForInductionVariable(Phi)) {
        Expr IndvarStart, IndvarEnd, IndvarStep;
        LIE_->getLoopInfo(L, Phi, IndvarStart, IndvarEnd, IndvarStep);

        BranchInst *BI = cast<BranchInst>(L->getExitingBlock()->getTerminator());
        ICmpInst *ICI = cast<ICmpInst>(BI->getCondition());

        Expr MinStart, MaxStart, MinEnd, MaxEnd;
        if (!getMinMax(IndvarStart, MinStart, MaxStart) ||
            !getMinMax(IndvarEnd, MinEnd, MaxEnd)) {
          RMM_DEBUG(dbgs() << "RelativeMinMax: Could not infer min/max for "
                           << IndvarStart << " and/or" << IndvarEnd << "\n");
          return false;
        }

        // FIXME: we should wrap the loop in a conditional so that the following
        // min/max assumptions always hold.
        switch (ICI->getPredicate()) {
          case CmpInst::ICMP_SLT:
          case CmpInst::ICMP_ULT:
          case CmpInst::ICMP_SLE:
          case CmpInst::ICMP_ULE:
            Min = MinStart;
            Max = MaxEnd;
            break;
          case CmpInst::ICMP_SGT:
          case CmpInst::ICMP_UGT:
          case CmpInst::ICMP_UGE:
          case CmpInst::ICMP_SGE:
            Min = MaxStart;
            Max = MinEnd;
            break;
          default:
            llvm_unreachable("Invalid comparison predicate");
        }
        RMM_DEBUG(dbgs() << "RelativeMinMax: min/max for induction variable "
                         << *Phi << ": " << Min << ", " << Max << "\n");
        return true;
      }
    }
    Min = Ex;
    Max = Ex;
  } else if (Ex.isAdd()) {
    for (auto SubEx : Ex) {
      Expr TmpMin, TmpMax;
      if (!getMinMax(SubEx, TmpMin, TmpMax)) {
        RMM_DEBUG(dbgs() << "RelativeMinMax: Could not infer min/max for "
                         << SubEx << "\n");
        return false;
      }
      addMinMax(TmpMin, TmpMax, Min, Max, Min, Max);
    }
  } else if (Ex.isMul()) {
    Min = Expr::InvalidExpr();
    for (auto SubEx : Ex) {
      Expr TmpMin, TmpMax;
      if (!getMinMax(SubEx, TmpMin, TmpMax)) {
        RMM_DEBUG(dbgs() << "RelativeMinMax: Could not infer min/max for "
                         << SubEx << "\n");
        return false;
      }
      if (!Min.isValid()) {
        Min = TmpMin;
        Max = TmpMax;
      } else {
        mulMinMax(TmpMin, TmpMax, Min, Max, Min, Max);
      }
    }
  } else if (Ex.isPow()) {
    if (!Ex.getPowExp().isConstant()) {
      RMM_DEBUG(dbgs() << "RelativeMinMax: non-constant exponent\n");
      return false;
    }
    Expr BaseMin, BaseMax;
    if (!getMinMax(Ex.getPowBase(), BaseMin, BaseMax)) {
      RMM_DEBUG(dbgs() << "RelativeMinMax: Could not infer min/max for "
                       << Ex.getPowBase() << "\n");
      return false;
    }
    if (Ex.getPowExp().isPositive()) {
      Min = BaseMin ^ Ex.getPowExp();
      Max = BaseMax ^ Ex.getPowExp();
    } else {
      Min = BaseMax ^ Ex.getPowExp();
      Max = BaseMin ^ Ex.getPowExp();
    }
  } else if (Ex.isMin()) {
    Expr MinFirst, MinSecond, Bogus;
    getMinMax(Ex.at(0), MinFirst,  Bogus);
    getMinMax(Ex.at(1), MinSecond, Bogus);
    Min = Max = MinFirst.min(MinSecond);
  } else if (Ex.isMax()) {
    Expr MaxFirst, MaxSecond, Bogus;
    getMinMax(Ex.at(0), MaxFirst,  Bogus);
    getMinMax(Ex.at(1), MaxSecond, Bogus);
    Min = Max = MaxFirst.max(MaxSecond);
  } else {
    RMM_DEBUG(dbgs() << "RelativeMinMax: unhandled expression: " << Ex << "\n");
    return false;
  }
  return true;
}
Ejemplo n.º 2
0
StepCode EliminateNakedTriplesStep::runOnHouse(House &house) {
  bool modified = false;

  if (house.size() <= 3) {
    return {false, modified};
  }

  std::vector<std::pair<Mask, std::vector<const Cell *>>> found_masks;
  for (const Cell *cell : house) {
    std::size_t num_candidates = cell->candidates.count();
    if (num_candidates == 0) {
      return {true, modified};
    }
    if (num_candidates != 2 && num_candidates != 3) {
      continue;
    }

    const Mask mask = cell->candidates.to_ulong();

    bool found_match = false;
    for (unsigned i = 0; i < found_masks.size(); ++i) {
      const Mask m = found_masks[i].first;

      // ORing the two masks together will switch on all candidates found in
      // both masks. If it's less than three, then we're still a triple
      // candidate.
      // TODO: If the current mask is size 2 and the OR of the two is 3, then
      // we should create two masks: one for the two and one for the OR.
      // Otherwise you could get 1/2 match with 1/2/3 and 1/2/4.
      // For now, only accept found masks of size 3. Easy naked triples.
      if (bitCount(m) == 3 && bitCount(mask | m) == 3) {
        found_match = true;
        found_masks[i].second.push_back(cell);
      }
    }

    if (!found_match) {
      std::pair<Mask, std::vector<const Cell *>> pair;
      pair.first = mask;
      pair.second.push_back(cell);
      found_masks.push_back(pair);
    }
  }

  for (auto &pair : found_masks) {
    if (pair.second.size() != 3) {
      continue;
    }

    auto &matches = pair.second;
    const Mask mask = pair.first;

    for (Cell *cell : house) {
      if (cell->isFixed()) {
        continue;
      }

      if (std::find(matches.begin(), matches.end(), cell) != matches.end()) {
        continue;
      }

      CandidateSet *candidates = &cell->candidates;
      if (candidates->to_ulong() == mask) {
        continue;
      }
      auto new_cands = CandidateSet(candidates->to_ulong() & ~mask);
      if (*candidates == new_cands) {
        continue;
      }

      if (DEBUG) {
        const Mask intersection = candidates->to_ulong() & mask;
        dbgs() << "Naked Triple " << printCandidateString(mask) << " removes "
               << printCandidateString(intersection) << " from " << cell->coord
               << "\n";
      }

      modified = true;
      changed.insert(cell);
      *candidates = new_cands;
    }
  }

  return {false, modified};
}
Ejemplo n.º 3
0
 static inline bool doit(const bar &Val) {
   dbgs() << "Classof: " << &Val << "\n";
   return true;
 }
Ejemplo n.º 4
0
/// inlineFuctions - Walk all call sites in all functions supplied by
/// client. Inline as many call sites as possible. Delete completely
/// inlined functions.
void BasicInlinerImpl::inlineFunctions() {
      
  // Scan through and identify all call sites ahead of time so that we only
  // inline call sites in the original functions, not call sites that result
  // from inlining other functions.
  std::vector<CallSite> CallSites;
  
  for (std::vector<Function *>::iterator FI = Functions.begin(),
         FE = Functions.end(); FI != FE; ++FI) {
    Function *F = *FI;
    for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB)
      for (BasicBlock::iterator I = BB->begin(); I != BB->end(); ++I) {
        CallSite CS(cast<Value>(I));
        if (CS && CS.getCalledFunction()
            && !CS.getCalledFunction()->isDeclaration())
          CallSites.push_back(CS);
      }
  }
  
  DEBUG(dbgs() << ": " << CallSites.size() << " call sites.\n");
  
  // Inline call sites.
  bool Changed = false;
  do {
    Changed = false;
    for (unsigned index = 0; index != CallSites.size() && !CallSites.empty(); 
         ++index) {
      CallSite CS = CallSites[index];
      if (Function *Callee = CS.getCalledFunction()) {
        
        // Eliminate calls that are never inlinable.
        if (Callee->isDeclaration() ||
            CS.getInstruction()->getParent()->getParent() == Callee) {
          CallSites.erase(CallSites.begin() + index);
          --index;
          continue;
        }
        InlineCost IC = CA.getInlineCost(CS, NeverInline);
        if (IC.isAlways()) {        
          DEBUG(dbgs() << "  Inlining: cost=always"
                       <<", call: " << *CS.getInstruction());
        } else if (IC.isNever()) {
          DEBUG(dbgs() << "  NOT Inlining: cost=never"
                       <<", call: " << *CS.getInstruction());
          continue;
        } else {
          int Cost = IC.getValue();
          
          if (Cost >= (int) BasicInlineThreshold) {
            DEBUG(dbgs() << "  NOT Inlining: cost = " << Cost
                         << ", call: " <<  *CS.getInstruction());
            continue;
          } else {
            DEBUG(dbgs() << "  Inlining: cost = " << Cost
                         << ", call: " <<  *CS.getInstruction());
          }
        }
        
        // Inline
        InlineFunctionInfo IFI(0, TD);
        if (InlineFunction(CS, IFI)) {
          if (Callee->use_empty() && (Callee->hasLocalLinkage() ||
                                      Callee->hasAvailableExternallyLinkage()))
            DeadFunctions.insert(Callee);
          Changed = true;
          CallSites.erase(CallSites.begin() + index);
          --index;
        }
      }
    }
  } while (Changed);
  
  // Remove completely inlined functions from module.
  for(SmallPtrSet<Function *, 8>::iterator I = DeadFunctions.begin(),
        E = DeadFunctions.end(); I != E; ++I) {
    Function *D = *I;
    Module *M = D->getParent();
    M->getFunctionList().remove(D);
  }
}
Ejemplo n.º 5
0
ObjectImage *RuntimeDyldImpl::loadObject(ObjectBuffer *InputBuffer) {
  OwningPtr<ObjectImage> obj(createObjectImage(InputBuffer));
  if (!obj)
    report_fatal_error("Unable to create object image from memory buffer!");

  Arch = (Triple::ArchType)obj->getArch();

  // Symbols found in this object
  StringMap<SymbolLoc> LocalSymbols;
  // Used sections from the object file
  ObjSectionToIDMap LocalSections;

  // Common symbols requiring allocation, with their sizes and alignments
  CommonSymbolMap CommonSymbols;
  // Maximum required total memory to allocate all common symbols
  uint64_t CommonSize = 0;

  error_code err;
  // Parse symbols
  DEBUG(dbgs() << "Parse symbols:\n");
  for (symbol_iterator i = obj->begin_symbols(), e = obj->end_symbols();
       i != e; i.increment(err)) {
    Check(err);
    object::SymbolRef::Type SymType;
    StringRef Name;
    Check(i->getType(SymType));
    Check(i->getName(Name));

    uint32_t flags;
    Check(i->getFlags(flags));

    bool isCommon = flags & SymbolRef::SF_Common;
    if (isCommon) {
      // Add the common symbols to a list.  We'll allocate them all below.
      uint32_t Align;
      Check(i->getAlignment(Align));
      uint64_t Size = 0;
      Check(i->getSize(Size));
      CommonSize += Size + Align;
      CommonSymbols[*i] = CommonSymbolInfo(Size, Align);
    } else {
      if (SymType == object::SymbolRef::ST_Function ||
          SymType == object::SymbolRef::ST_Data ||
          SymType == object::SymbolRef::ST_Unknown) {
        uint64_t FileOffset;
        StringRef SectionData;
        bool IsCode;
        section_iterator si = obj->end_sections();
        Check(i->getFileOffset(FileOffset));
        Check(i->getSection(si));
        if (si == obj->end_sections()) continue;
        Check(si->getContents(SectionData));
        Check(si->isText(IsCode));
        const uint8_t* SymPtr = (const uint8_t*)InputBuffer->getBufferStart() +
                                (uintptr_t)FileOffset;
        uintptr_t SectOffset = (uintptr_t)(SymPtr -
                                           (const uint8_t*)SectionData.begin());
        unsigned SectionID = findOrEmitSection(*obj, *si, IsCode, LocalSections);
        LocalSymbols[Name.data()] = SymbolLoc(SectionID, SectOffset);
        DEBUG(dbgs() << "\tFileOffset: " << format("%p", (uintptr_t)FileOffset)
                     << " flags: " << flags
                     << " SID: " << SectionID
                     << " Offset: " << format("%p", SectOffset));
        GlobalSymbolTable[Name] = SymbolLoc(SectionID, SectOffset);
      }
    }
    DEBUG(dbgs() << "\tType: " << SymType << " Name: " << Name << "\n");
  }

  // Allocate common symbols
  if (CommonSize != 0)
    emitCommonSymbols(*obj, CommonSymbols, CommonSize, LocalSymbols);

  // Parse and process relocations
  DEBUG(dbgs() << "Parse relocations:\n");
  for (section_iterator si = obj->begin_sections(),
       se = obj->end_sections(); si != se; si.increment(err)) {
    Check(err);
    bool isFirstRelocation = true;
    unsigned SectionID = 0;
    StubMap Stubs;

    for (relocation_iterator i = si->begin_relocations(),
         e = si->end_relocations(); i != e; i.increment(err)) {
      Check(err);

      // If it's the first relocation in this section, find its SectionID
      if (isFirstRelocation) {
        SectionID = findOrEmitSection(*obj, *si, true, LocalSections);
        DEBUG(dbgs() << "\tSectionID: " << SectionID << "\n");
        isFirstRelocation = false;
      }

      processRelocationRef(SectionID, *i, *obj, LocalSections, LocalSymbols,
			   Stubs);
    }
  }

  return obj.take();
}
Ejemplo n.º 6
0
unsigned RuntimeDyldImpl::emitSection(ObjectImage &Obj,
                                      const SectionRef &Section,
                                      bool IsCode) {

  unsigned StubBufSize = 0,
           StubSize = getMaxStubSize();
  error_code err;
  if (StubSize > 0) {
    for (relocation_iterator i = Section.begin_relocations(),
         e = Section.end_relocations(); i != e; i.increment(err), Check(err))
      StubBufSize += StubSize;
  }
  StringRef data;
  uint64_t Alignment64;
  Check(Section.getContents(data));
  Check(Section.getAlignment(Alignment64));

  unsigned Alignment = (unsigned)Alignment64 & 0xffffffffL;
  bool IsRequired;
  bool IsVirtual;
  bool IsZeroInit;
  bool IsReadOnly;
  uint64_t DataSize;
  StringRef Name;
  Check(Section.isRequiredForExecution(IsRequired));
  Check(Section.isVirtual(IsVirtual));
  Check(Section.isZeroInit(IsZeroInit));
  Check(Section.isReadOnlyData(IsReadOnly));
  Check(Section.getSize(DataSize));
  Check(Section.getName(Name));
  if (StubSize > 0) {
    unsigned StubAlignment = getStubAlignment();
    unsigned EndAlignment = (DataSize | Alignment) & -(DataSize | Alignment);
    if (StubAlignment > EndAlignment)
      StubBufSize += StubAlignment - EndAlignment;
  }

  unsigned Allocate;
  unsigned SectionID = Sections.size();
  uint8_t *Addr;
  const char *pData = 0;

  // Some sections, such as debug info, don't need to be loaded for execution.
  // Leave those where they are.
  if (IsRequired) {
    Allocate = DataSize + StubBufSize;
    Addr = IsCode
      ? MemMgr->allocateCodeSection(Allocate, Alignment, SectionID)
      : MemMgr->allocateDataSection(Allocate, Alignment, SectionID, IsReadOnly);
    if (!Addr)
      report_fatal_error("Unable to allocate section memory!");

    // Virtual sections have no data in the object image, so leave pData = 0
    if (!IsVirtual)
      pData = data.data();

    // Zero-initialize or copy the data from the image
    if (IsZeroInit || IsVirtual)
      memset(Addr, 0, DataSize);
    else
      memcpy(Addr, pData, DataSize);

    DEBUG(dbgs() << "emitSection SectionID: " << SectionID
                 << " Name: " << Name
                 << " obj addr: " << format("%p", pData)
                 << " new addr: " << format("%p", Addr)
                 << " DataSize: " << DataSize
                 << " StubBufSize: " << StubBufSize
                 << " Allocate: " << Allocate
                 << "\n");
    Obj.updateSectionAddress(Section, (uint64_t)Addr);
  }
  else {
    // Even if we didn't load the section, we need to record an entry for it
    // to handle later processing (and by 'handle' I mean don't do anything
    // with these sections).
    Allocate = 0;
    Addr = 0;
    DEBUG(dbgs() << "emitSection SectionID: " << SectionID
                 << " Name: " << Name
                 << " obj addr: " << format("%p", data.data())
                 << " new addr: 0"
                 << " DataSize: " << DataSize
                 << " StubBufSize: " << StubBufSize
                 << " Allocate: " << Allocate
                 << "\n");
  }

  Sections.push_back(SectionEntry(Name, Addr, DataSize, (uintptr_t)pData));
  return SectionID;
}