forked from OSchip/llvm-project
				
			
		
			
				
	
	
		
			156 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			156 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			C++
		
	
	
	
//===------ PollyIRBuilder.cpp --------------------------------------------===//
 | 
						|
//
 | 
						|
//                     The LLVM Compiler Infrastructure
 | 
						|
//
 | 
						|
// This file is distributed under the University of Illinois Open Source
 | 
						|
// License. See LICENSE.TXT for details.
 | 
						|
//
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
//
 | 
						|
// The Polly IRBuilder file contains Polly specific extensions for the IRBuilder
 | 
						|
// that are used e.g. to emit the llvm.loop.parallel metadata.
 | 
						|
//
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
 | 
						|
#include "polly/CodeGen/IRBuilder.h"
 | 
						|
#include "polly/ScopInfo.h"
 | 
						|
#include "polly/Support/ScopHelper.h"
 | 
						|
#include "llvm/IR/Metadata.h"
 | 
						|
#include "llvm/Support/Debug.h"
 | 
						|
 | 
						|
using namespace llvm;
 | 
						|
using namespace polly;
 | 
						|
 | 
						|
/// @brief Get a self referencing id metadata node.
 | 
						|
///
 | 
						|
/// The MDNode looks like this (if arg0/arg1 are not null):
 | 
						|
///
 | 
						|
///    '!n = metadata !{metadata !n, arg0, arg1}'
 | 
						|
///
 | 
						|
/// @return The self referencing id metadata node.
 | 
						|
static MDNode *getID(LLVMContext &Ctx, Metadata *arg0 = nullptr,
 | 
						|
                     Metadata *arg1 = nullptr) {
 | 
						|
  MDNode *ID;
 | 
						|
  SmallVector<Metadata *, 3> Args;
 | 
						|
  // Use a temporary node to safely create a unique pointer for the first arg.
 | 
						|
  auto TempNode = MDNode::getTemporary(Ctx, None);
 | 
						|
  // Reserve operand 0 for loop id self reference.
 | 
						|
  Args.push_back(TempNode.get());
 | 
						|
 | 
						|
  if (arg0)
 | 
						|
    Args.push_back(arg0);
 | 
						|
  if (arg1)
 | 
						|
    Args.push_back(arg1);
 | 
						|
 | 
						|
  ID = MDNode::get(Ctx, Args);
 | 
						|
  ID->replaceOperandWith(0, ID);
 | 
						|
  return ID;
 | 
						|
}
 | 
						|
 | 
						|
ScopAnnotator::ScopAnnotator() : SE(nullptr), AliasScopeDomain(nullptr) {}
 | 
						|
 | 
						|
void ScopAnnotator::buildAliasScopes(Scop &S) {
 | 
						|
  SE = S.getSE();
 | 
						|
 | 
						|
  LLVMContext &Ctx = SE->getContext();
 | 
						|
  AliasScopeDomain = getID(Ctx, MDString::get(Ctx, "polly.alias.scope.domain"));
 | 
						|
 | 
						|
  AliasScopeMap.clear();
 | 
						|
  OtherAliasScopeListMap.clear();
 | 
						|
 | 
						|
  SetVector<Value *> BasePtrs;
 | 
						|
  for (ScopStmt &Stmt : S)
 | 
						|
    for (MemoryAccess *MA : Stmt)
 | 
						|
      BasePtrs.insert(MA->getBaseAddr());
 | 
						|
 | 
						|
  std::string AliasScopeStr = "polly.alias.scope.";
 | 
						|
  for (Value *BasePtr : BasePtrs)
 | 
						|
    AliasScopeMap[BasePtr] = getID(
 | 
						|
        Ctx, AliasScopeDomain,
 | 
						|
        MDString::get(Ctx, (AliasScopeStr + BasePtr->getName()).str().c_str()));
 | 
						|
 | 
						|
  for (Value *BasePtr : BasePtrs) {
 | 
						|
    MDNode *AliasScopeList = MDNode::get(Ctx, {});
 | 
						|
    for (const auto &AliasScopePair : AliasScopeMap) {
 | 
						|
      if (BasePtr == AliasScopePair.first)
 | 
						|
        continue;
 | 
						|
 | 
						|
      Metadata *Args = {AliasScopePair.second};
 | 
						|
      AliasScopeList =
 | 
						|
          MDNode::concatenate(AliasScopeList, MDNode::get(Ctx, Args));
 | 
						|
    }
 | 
						|
 | 
						|
    OtherAliasScopeListMap[BasePtr] = AliasScopeList;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void ScopAnnotator::pushLoop(Loop *L, bool IsParallel) {
 | 
						|
 | 
						|
  ActiveLoops.push_back(L);
 | 
						|
  if (!IsParallel)
 | 
						|
    return;
 | 
						|
 | 
						|
  BasicBlock *Header = L->getHeader();
 | 
						|
  MDNode *Id = getID(Header->getContext());
 | 
						|
  assert(Id->getOperand(0) == Id && "Expected Id to be a self-reference");
 | 
						|
  assert(Id->getNumOperands() == 1 && "Unexpected extra operands in Id");
 | 
						|
  MDNode *Ids = ParallelLoops.empty()
 | 
						|
                    ? Id
 | 
						|
                    : MDNode::concatenate(ParallelLoops.back(), Id);
 | 
						|
  ParallelLoops.push_back(Ids);
 | 
						|
}
 | 
						|
 | 
						|
void ScopAnnotator::popLoop(bool IsParallel) {
 | 
						|
  ActiveLoops.pop_back();
 | 
						|
  if (!IsParallel)
 | 
						|
    return;
 | 
						|
 | 
						|
  assert(!ParallelLoops.empty() && "Expected a parallel loop to pop");
 | 
						|
  ParallelLoops.pop_back();
 | 
						|
}
 | 
						|
 | 
						|
void ScopAnnotator::annotateLoopLatch(BranchInst *B, Loop *L,
 | 
						|
                                      bool IsParallel) const {
 | 
						|
  if (!IsParallel)
 | 
						|
    return;
 | 
						|
 | 
						|
  assert(!ParallelLoops.empty() && "Expected a parallel loop to annotate");
 | 
						|
  MDNode *Ids = ParallelLoops.back();
 | 
						|
  MDNode *Id = cast<MDNode>(Ids->getOperand(Ids->getNumOperands() - 1));
 | 
						|
  B->setMetadata("llvm.loop", Id);
 | 
						|
}
 | 
						|
 | 
						|
void ScopAnnotator::annotate(Instruction *Inst) {
 | 
						|
  if (!Inst->mayReadOrWriteMemory())
 | 
						|
    return;
 | 
						|
 | 
						|
  // TODO: Use the ScopArrayInfo once available here.
 | 
						|
  if (AliasScopeDomain) {
 | 
						|
    Value *BasePtr = nullptr;
 | 
						|
    if (isa<StoreInst>(Inst) || isa<LoadInst>(Inst)) {
 | 
						|
      const SCEV *PtrSCEV = SE->getSCEV(getPointerOperand(*Inst));
 | 
						|
      const SCEV *BaseSCEV = SE->getPointerBase(PtrSCEV);
 | 
						|
      if (const SCEVUnknown *SU = dyn_cast<SCEVUnknown>(BaseSCEV))
 | 
						|
        BasePtr = SU->getValue();
 | 
						|
    }
 | 
						|
 | 
						|
    if (BasePtr) {
 | 
						|
      auto *AliasScope = AliasScopeMap[BasePtr];
 | 
						|
 | 
						|
      if (!AliasScope)
 | 
						|
        BasePtr = AlternativeAliasBases[BasePtr];
 | 
						|
 | 
						|
      AliasScope = AliasScopeMap[BasePtr];
 | 
						|
      auto *OtherAliasScopeList = OtherAliasScopeListMap[BasePtr];
 | 
						|
 | 
						|
      Inst->setMetadata("alias.scope", AliasScope);
 | 
						|
      Inst->setMetadata("noalias", OtherAliasScopeList);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  if (ParallelLoops.empty())
 | 
						|
    return;
 | 
						|
 | 
						|
  Inst->setMetadata("llvm.mem.parallel_loop_access", ParallelLoops.back());
 | 
						|
}
 |