forked from OSchip/llvm-project
113 lines
3.6 KiB
C++
113 lines
3.6 KiB
C++
//===---- CGLoopInfo.cpp - LLVM CodeGen for loop metadata -*- C++ -*-------===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "CGLoopInfo.h"
|
|
#include "llvm/IR/BasicBlock.h"
|
|
#include "llvm/IR/Constants.h"
|
|
#include "llvm/IR/InstrTypes.h"
|
|
#include "llvm/IR/Instructions.h"
|
|
#include "llvm/IR/Metadata.h"
|
|
using namespace clang;
|
|
using namespace CodeGen;
|
|
using namespace llvm;
|
|
|
|
static MDNode *createMetadata(LLVMContext &Ctx, const LoopAttributes &Attrs) {
|
|
|
|
if (!Attrs.IsParallel && Attrs.VectorizerWidth == 0 &&
|
|
Attrs.VectorizerUnroll == 0 &&
|
|
Attrs.VectorizerEnable == LoopAttributes::VecUnspecified)
|
|
return nullptr;
|
|
|
|
SmallVector<Value *, 4> Args;
|
|
// Reserve operand 0 for loop id self reference.
|
|
MDNode *TempNode = MDNode::getTemporary(Ctx, None);
|
|
Args.push_back(TempNode);
|
|
|
|
// Setting vectorizer.width
|
|
if (Attrs.VectorizerWidth > 0) {
|
|
Value *Vals[] = { MDString::get(Ctx, "llvm.loop.vectorize.width"),
|
|
ConstantInt::get(Type::getInt32Ty(Ctx),
|
|
Attrs.VectorizerWidth) };
|
|
Args.push_back(MDNode::get(Ctx, Vals));
|
|
}
|
|
|
|
// Setting vectorizer.unroll
|
|
if (Attrs.VectorizerUnroll > 0) {
|
|
Value *Vals[] = { MDString::get(Ctx, "llvm.loop.interleave.count"),
|
|
ConstantInt::get(Type::getInt32Ty(Ctx),
|
|
Attrs.VectorizerUnroll) };
|
|
Args.push_back(MDNode::get(Ctx, Vals));
|
|
}
|
|
|
|
// Setting vectorizer.enable
|
|
if (Attrs.VectorizerEnable != LoopAttributes::VecUnspecified) {
|
|
Value *Vals[] = { MDString::get(Ctx, "llvm.loop.vectorize.enable"),
|
|
ConstantInt::get(Type::getInt1Ty(Ctx),
|
|
(Attrs.VectorizerEnable ==
|
|
LoopAttributes::VecEnable)) };
|
|
Args.push_back(MDNode::get(Ctx, Vals));
|
|
}
|
|
|
|
MDNode *LoopID = MDNode::get(Ctx, Args);
|
|
assert(LoopID->use_empty() && "LoopID should not be used");
|
|
|
|
// Set the first operand to itself.
|
|
LoopID->replaceOperandWith(0, LoopID);
|
|
MDNode::deleteTemporary(TempNode);
|
|
return LoopID;
|
|
}
|
|
|
|
LoopAttributes::LoopAttributes(bool IsParallel)
|
|
: IsParallel(IsParallel), VectorizerEnable(LoopAttributes::VecUnspecified),
|
|
VectorizerWidth(0), VectorizerUnroll(0) {}
|
|
|
|
void LoopAttributes::clear() {
|
|
IsParallel = false;
|
|
VectorizerWidth = 0;
|
|
VectorizerUnroll = 0;
|
|
VectorizerEnable = LoopAttributes::VecUnspecified;
|
|
}
|
|
|
|
LoopInfo::LoopInfo(BasicBlock *Header, const LoopAttributes &Attrs)
|
|
: LoopID(nullptr), Header(Header), Attrs(Attrs) {
|
|
LoopID = createMetadata(Header->getContext(), Attrs);
|
|
}
|
|
|
|
void LoopInfoStack::push(BasicBlock *Header) {
|
|
Active.push_back(LoopInfo(Header, StagedAttrs));
|
|
// Clear the attributes so nested loops do not inherit them.
|
|
StagedAttrs.clear();
|
|
}
|
|
|
|
void LoopInfoStack::pop() {
|
|
assert(!Active.empty() && "No active loops to pop");
|
|
Active.pop_back();
|
|
}
|
|
|
|
void LoopInfoStack::InsertHelper(Instruction *I) const {
|
|
if (!hasInfo())
|
|
return;
|
|
|
|
const LoopInfo &L = getInfo();
|
|
if (!L.getLoopID())
|
|
return;
|
|
|
|
if (TerminatorInst *TI = dyn_cast<TerminatorInst>(I)) {
|
|
for (unsigned i = 0, ie = TI->getNumSuccessors(); i < ie; ++i)
|
|
if (TI->getSuccessor(i) == L.getHeader()) {
|
|
TI->setMetadata("llvm.loop", L.getLoopID());
|
|
break;
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (L.getAttributes().IsParallel && I->mayReadOrWriteMemory())
|
|
I->setMetadata("llvm.mem.parallel_loop_access", L.getLoopID());
|
|
}
|