2014-05-22 16:54:05 +08:00
|
|
|
//===---- 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"
|
2015-06-12 07:23:17 +08:00
|
|
|
#include "clang/AST/Attr.h"
|
|
|
|
#include "clang/Sema/LoopHint.h"
|
2014-05-22 16:54:05 +08:00
|
|
|
#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"
|
2015-06-09 07:27:35 +08:00
|
|
|
using namespace clang::CodeGen;
|
2014-05-22 16:54:05 +08:00
|
|
|
using namespace llvm;
|
|
|
|
|
|
|
|
static MDNode *createMetadata(LLVMContext &Ctx, const LoopAttributes &Attrs) {
|
|
|
|
|
2015-07-15 07:03:09 +08:00
|
|
|
if (!Attrs.IsParallel && Attrs.VectorizeWidth == 0 &&
|
|
|
|
Attrs.InterleaveCount == 0 &&
|
|
|
|
Attrs.VectorizeEnable == LoopAttributes::Unspecified)
|
2014-05-22 16:54:05 +08:00
|
|
|
return nullptr;
|
|
|
|
|
2014-12-10 02:39:32 +08:00
|
|
|
SmallVector<Metadata *, 4> Args;
|
2014-05-22 16:54:05 +08:00
|
|
|
// Reserve operand 0 for loop id self reference.
|
2015-01-20 05:30:48 +08:00
|
|
|
auto TempNode = MDNode::getTemporary(Ctx, None);
|
|
|
|
Args.push_back(TempNode.get());
|
2014-05-22 16:54:05 +08:00
|
|
|
|
2015-07-15 07:03:09 +08:00
|
|
|
// Setting vectorize.width
|
|
|
|
if (Attrs.VectorizeWidth > 0) {
|
2014-12-10 02:39:32 +08:00
|
|
|
Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.vectorize.width"),
|
|
|
|
ConstantAsMetadata::get(ConstantInt::get(
|
2015-07-15 07:03:09 +08:00
|
|
|
Type::getInt32Ty(Ctx), Attrs.VectorizeWidth))};
|
2014-05-22 16:54:05 +08:00
|
|
|
Args.push_back(MDNode::get(Ctx, Vals));
|
|
|
|
}
|
|
|
|
|
2015-07-15 07:03:09 +08:00
|
|
|
// Setting interleave.count
|
|
|
|
if (Attrs.InterleaveCount > 0) {
|
2014-12-10 02:39:32 +08:00
|
|
|
Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.interleave.count"),
|
|
|
|
ConstantAsMetadata::get(ConstantInt::get(
|
2015-07-15 07:03:09 +08:00
|
|
|
Type::getInt32Ty(Ctx), Attrs.InterleaveCount))};
|
2014-05-22 16:54:05 +08:00
|
|
|
Args.push_back(MDNode::get(Ctx, Vals));
|
|
|
|
}
|
|
|
|
|
2015-07-15 07:03:09 +08:00
|
|
|
// Setting vectorize.enable
|
|
|
|
if (Attrs.VectorizeEnable != LoopAttributes::Unspecified) {
|
|
|
|
Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.vectorize.enable"),
|
|
|
|
ConstantAsMetadata::get(ConstantInt::get(
|
|
|
|
Type::getInt1Ty(Ctx), (Attrs.VectorizeEnable ==
|
|
|
|
LoopAttributes::Enable)))};
|
2014-05-22 16:54:05 +08:00
|
|
|
Args.push_back(MDNode::get(Ctx, Vals));
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set the first operand to itself.
|
2014-12-10 02:39:32 +08:00
|
|
|
MDNode *LoopID = MDNode::get(Ctx, Args);
|
2014-05-22 16:54:05 +08:00
|
|
|
LoopID->replaceOperandWith(0, LoopID);
|
|
|
|
return LoopID;
|
|
|
|
}
|
|
|
|
|
|
|
|
LoopAttributes::LoopAttributes(bool IsParallel)
|
2015-07-15 07:03:09 +08:00
|
|
|
: IsParallel(IsParallel), VectorizeEnable(LoopAttributes::Unspecified),
|
|
|
|
VectorizeWidth(0), InterleaveCount(0) {}
|
2014-05-22 16:54:05 +08:00
|
|
|
|
|
|
|
void LoopAttributes::clear() {
|
|
|
|
IsParallel = false;
|
2015-07-15 07:03:09 +08:00
|
|
|
VectorizeWidth = 0;
|
|
|
|
InterleaveCount = 0;
|
|
|
|
VectorizeEnable = LoopAttributes::Unspecified;
|
2014-05-22 16:54:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
LoopInfo::LoopInfo(BasicBlock *Header, const LoopAttributes &Attrs)
|
|
|
|
: LoopID(nullptr), Header(Header), Attrs(Attrs) {
|
|
|
|
LoopID = createMetadata(Header->getContext(), Attrs);
|
|
|
|
}
|
|
|
|
|
2015-06-12 08:17:26 +08:00
|
|
|
void LoopInfoStack::push(BasicBlock *Header,
|
|
|
|
ArrayRef<const clang::Attr *> Attrs) {
|
2015-06-12 07:23:17 +08:00
|
|
|
for (const auto *Attr : Attrs) {
|
|
|
|
const LoopHintAttr *LH = dyn_cast<LoopHintAttr>(Attr);
|
|
|
|
|
|
|
|
// Skip non loop hint attributes
|
|
|
|
if (!LH)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
LoopHintAttr::OptionType Option = LH->getOption();
|
|
|
|
LoopHintAttr::LoopHintState State = LH->getState();
|
|
|
|
switch (Option) {
|
|
|
|
case LoopHintAttr::Vectorize:
|
|
|
|
case LoopHintAttr::Interleave:
|
|
|
|
if (State == LoopHintAttr::AssumeSafety) {
|
|
|
|
// Apply "llvm.mem.parallel_loop_access" metadata to load/stores.
|
|
|
|
setParallel(true);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case LoopHintAttr::VectorizeWidth:
|
|
|
|
case LoopHintAttr::InterleaveCount:
|
|
|
|
case LoopHintAttr::Unroll:
|
|
|
|
case LoopHintAttr::UnrollCount:
|
|
|
|
// Nothing to do here for these loop hints.
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-05-22 16:54:05 +08:00
|
|
|
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());
|
|
|
|
}
|