summaryrefslogtreecommitdiffstats
path: root/clang/lib/CodeGen
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/CodeGen')
-rw-r--r--clang/lib/CodeGen/CGLoopInfo.cpp129
-rw-r--r--clang/lib/CodeGen/CGLoopInfo.h24
-rw-r--r--clang/lib/CodeGen/CGStmt.cpp122
-rw-r--r--clang/lib/CodeGen/CodeGenFunction.h2
4 files changed, 143 insertions, 134 deletions
diff --git a/clang/lib/CodeGen/CGLoopInfo.cpp b/clang/lib/CodeGen/CGLoopInfo.cpp
index 63de2d98fd7..5bc08f7d52a 100644
--- a/clang/lib/CodeGen/CGLoopInfo.cpp
+++ b/clang/lib/CodeGen/CGLoopInfo.cpp
@@ -8,6 +8,7 @@
//===----------------------------------------------------------------------===//
#include "CGLoopInfo.h"
+#include "clang/AST/ASTContext.h"
#include "clang/AST/Attr.h"
#include "clang/Sema/LoopHint.h"
#include "llvm/IR/BasicBlock.h"
@@ -21,8 +22,9 @@ using namespace llvm;
static MDNode *createMetadata(LLVMContext &Ctx, const LoopAttributes &Attrs) {
if (!Attrs.IsParallel && Attrs.VectorizeWidth == 0 &&
- Attrs.InterleaveCount == 0 &&
- Attrs.VectorizeEnable == LoopAttributes::Unspecified)
+ Attrs.InterleaveCount == 0 && Attrs.UnrollCount == 0 &&
+ Attrs.VectorizeEnable == LoopAttributes::Unspecified &&
+ Attrs.UnrollEnable == LoopAttributes::Unspecified)
return nullptr;
SmallVector<Metadata *, 4> Args;
@@ -46,6 +48,14 @@ static MDNode *createMetadata(LLVMContext &Ctx, const LoopAttributes &Attrs) {
Args.push_back(MDNode::get(Ctx, Vals));
}
+ // Setting interleave.count
+ if (Attrs.UnrollCount > 0) {
+ Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.unroll.count"),
+ ConstantAsMetadata::get(ConstantInt::get(
+ Type::getInt32Ty(Ctx), Attrs.UnrollCount))};
+ Args.push_back(MDNode::get(Ctx, Vals));
+ }
+
// Setting vectorize.enable
if (Attrs.VectorizeEnable != LoopAttributes::Unspecified) {
Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.vectorize.enable"),
@@ -55,6 +65,15 @@ static MDNode *createMetadata(LLVMContext &Ctx, const LoopAttributes &Attrs) {
Args.push_back(MDNode::get(Ctx, Vals));
}
+ // Setting unroll.full or unroll.disable
+ if (Attrs.UnrollEnable != LoopAttributes::Unspecified) {
+ Metadata *Vals[] = {
+ MDString::get(Ctx, (Attrs.UnrollEnable == LoopAttributes::Enable
+ ? "llvm.loop.unroll.full"
+ : "llvm.loop.unroll.disable"))};
+ Args.push_back(MDNode::get(Ctx, Vals));
+ }
+
// Set the first operand to itself.
MDNode *LoopID = MDNode::get(Ctx, Args);
LoopID->replaceOperandWith(0, LoopID);
@@ -63,13 +82,16 @@ static MDNode *createMetadata(LLVMContext &Ctx, const LoopAttributes &Attrs) {
LoopAttributes::LoopAttributes(bool IsParallel)
: IsParallel(IsParallel), VectorizeEnable(LoopAttributes::Unspecified),
- VectorizeWidth(0), InterleaveCount(0) {}
+ UnrollEnable(LoopAttributes::Unspecified), VectorizeWidth(0),
+ InterleaveCount(0), UnrollCount(0) {}
void LoopAttributes::clear() {
IsParallel = false;
VectorizeWidth = 0;
InterleaveCount = 0;
+ UnrollCount = 0;
VectorizeEnable = LoopAttributes::Unspecified;
+ UnrollEnable = LoopAttributes::Unspecified;
}
LoopInfo::LoopInfo(BasicBlock *Header, const LoopAttributes &Attrs)
@@ -77,8 +99,16 @@ LoopInfo::LoopInfo(BasicBlock *Header, const LoopAttributes &Attrs)
LoopID = createMetadata(Header->getContext(), Attrs);
}
-void LoopInfoStack::push(BasicBlock *Header,
+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::push(BasicBlock *Header, clang::ASTContext &Ctx,
ArrayRef<const clang::Attr *> Attrs) {
+
+ // Identify loop hint attributes from Attrs.
for (const auto *Attr : Attrs) {
const LoopHintAttr *LH = dyn_cast<LoopHintAttr>(Attr);
@@ -86,28 +116,95 @@ void LoopInfoStack::push(BasicBlock *Header,
if (!LH)
continue;
+ auto *ValueExpr = LH->getValue();
+ unsigned ValueInt = 1;
+ if (ValueExpr) {
+ llvm::APSInt ValueAPS = ValueExpr->EvaluateKnownConstInt(Ctx);
+ ValueInt = ValueAPS.getSExtValue();
+ }
+
LoopHintAttr::OptionType Option = LH->getOption();
LoopHintAttr::LoopHintState State = LH->getState();
- switch (Option) {
- case LoopHintAttr::Vectorize:
- case LoopHintAttr::Interleave:
- if (State == LoopHintAttr::AssumeSafety) {
+ switch (State) {
+ case LoopHintAttr::Disable:
+ switch (Option) {
+ case LoopHintAttr::Vectorize:
+ // Disable vectorization by specifying a width of 1.
+ setVectorizeWidth(1);
+ break;
+ case LoopHintAttr::Interleave:
+ // Disable interleaving by speciyfing a count of 1.
+ setInterleaveCount(1);
+ break;
+ case LoopHintAttr::Unroll:
+ setUnrollEnable(false);
+ break;
+ case LoopHintAttr::UnrollCount:
+ case LoopHintAttr::VectorizeWidth:
+ case LoopHintAttr::InterleaveCount:
+ llvm_unreachable("Options cannot be disabled.");
+ break;
+ }
+ break;
+ case LoopHintAttr::Enable:
+ switch (Option) {
+ case LoopHintAttr::Vectorize:
+ case LoopHintAttr::Interleave:
+ setVectorizeEnable(true);
+ break;
+ case LoopHintAttr::Unroll:
+ setUnrollEnable(true);
+ break;
+ case LoopHintAttr::UnrollCount:
+ case LoopHintAttr::VectorizeWidth:
+ case LoopHintAttr::InterleaveCount:
+ llvm_unreachable("Options cannot enabled.");
+ break;
+ }
+ break;
+ case LoopHintAttr::AssumeSafety:
+ switch (Option) {
+ case LoopHintAttr::Vectorize:
+ case LoopHintAttr::Interleave:
// Apply "llvm.mem.parallel_loop_access" metadata to load/stores.
setParallel(true);
+ setVectorizeEnable(true);
+ break;
+ case LoopHintAttr::Unroll:
+ case LoopHintAttr::UnrollCount:
+ case LoopHintAttr::VectorizeWidth:
+ case LoopHintAttr::InterleaveCount:
+ llvm_unreachable("Options cannot be used to assume mem safety.");
+ break;
}
break;
- case LoopHintAttr::VectorizeWidth:
- case LoopHintAttr::InterleaveCount:
- case LoopHintAttr::Unroll:
- case LoopHintAttr::UnrollCount:
- // Nothing to do here for these loop hints.
+ case LoopHintAttr::Default:
+ switch (Option) {
+ case LoopHintAttr::VectorizeWidth:
+ setVectorizeWidth(ValueInt);
+ break;
+ case LoopHintAttr::InterleaveCount:
+ setInterleaveCount(ValueInt);
+ break;
+ case LoopHintAttr::UnrollCount:
+ setUnrollCount(ValueInt);
+ break;
+ case LoopHintAttr::Unroll:
+ // The default option is used when '#pragma unroll' is specified.
+ setUnrollEnable(true);
+ break;
+ case LoopHintAttr::Vectorize:
+ case LoopHintAttr::Interleave:
+ llvm_unreachable("Options cannot be assigned a value and do not have a "
+ "default value.");
+ break;
+ }
break;
}
}
- Active.push_back(LoopInfo(Header, StagedAttrs));
- // Clear the attributes so nested loops do not inherit them.
- StagedAttrs.clear();
+ /// Stage the attributes.
+ push(Header);
}
void LoopInfoStack::pop() {
diff --git a/clang/lib/CodeGen/CGLoopInfo.h b/clang/lib/CodeGen/CGLoopInfo.h
index 8822c22c91c..686a218c763 100644
--- a/clang/lib/CodeGen/CGLoopInfo.h
+++ b/clang/lib/CodeGen/CGLoopInfo.h
@@ -29,6 +29,7 @@ class MDNode;
namespace clang {
class Attr;
+class ASTContext;
namespace CodeGen {
/// \brief Attributes that may be specified on loops.
@@ -45,11 +46,17 @@ struct LoopAttributes {
/// \brief Value for llvm.loop.vectorize.enable metadata.
LVEnableState VectorizeEnable;
+ /// \brief Selects no metadata, llvm.unroll.full, or llvm.unroll.disable.
+ LVEnableState UnrollEnable;
+
/// \brief Value for llvm.loop.vectorize.width metadata.
unsigned VectorizeWidth;
/// \brief Value for llvm.loop.interleave.count metadata.
unsigned InterleaveCount;
+
+ /// \brief llvm.unroll.
+ unsigned UnrollCount;
};
/// \brief Information used when generating a structured loop.
@@ -88,8 +95,12 @@ public:
/// \brief Begin a new structured loop. The set of staged attributes will be
/// applied to the loop and then cleared.
- void push(llvm::BasicBlock *Header,
- llvm::ArrayRef<const Attr *> Attrs = llvm::None);
+ void push(llvm::BasicBlock *Header);
+
+ /// \brief Begin a new structured loop. Stage attributes from the Attrs list.
+ /// The staged attributes are applied to the loop and then cleared.
+ void push(llvm::BasicBlock *Header, clang::ASTContext &Ctx,
+ llvm::ArrayRef<const Attr *> Attrs);
/// \brief End the current loop.
void pop();
@@ -115,12 +126,21 @@ public:
Enable ? LoopAttributes::Enable : LoopAttributes::Disable;
}
+ /// \brief Set the next pushed loop unroll state.
+ void setUnrollEnable(bool Enable = true) {
+ StagedAttrs.UnrollEnable =
+ Enable ? LoopAttributes::Enable : LoopAttributes::Disable;
+ }
+
/// \brief Set the vectorize width for the next loop pushed.
void setVectorizeWidth(unsigned W) { StagedAttrs.VectorizeWidth = W; }
/// \brief Set the interleave count for the next loop pushed.
void setInterleaveCount(unsigned C) { StagedAttrs.InterleaveCount = C; }
+ /// \brief Set the unroll count for the next loop pushed.
+ void setUnrollCount(unsigned C) { StagedAttrs.UnrollCount = C; }
+
private:
/// \brief Returns true if there is LoopInfo on the stack.
bool hasInfo() const { return !Active.empty(); }
diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp
index d3fa7f27c5c..b9a176fe652 100644
--- a/clang/lib/CodeGen/CGStmt.cpp
+++ b/clang/lib/CodeGen/CGStmt.cpp
@@ -593,100 +593,6 @@ void CodeGenFunction::EmitIfStmt(const IfStmt &S) {
EmitBlock(ContBlock, true);
}
-void CodeGenFunction::EmitCondBrHints(llvm::LLVMContext &Context,
- llvm::BranchInst *CondBr,
- ArrayRef<const Attr *> Attrs) {
- // Return if there are no hints.
- if (Attrs.empty())
- return;
-
- // Add vectorize and unroll hints to the metadata on the conditional branch.
- //
- // FIXME: Should this really start with a size of 1?
- SmallVector<llvm::Metadata *, 2> Metadata(1);
- 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();
- const char *MetadataName;
- switch (Option) {
- case LoopHintAttr::Vectorize:
- case LoopHintAttr::VectorizeWidth:
- MetadataName = "llvm.loop.vectorize.width";
- break;
- case LoopHintAttr::Interleave:
- case LoopHintAttr::InterleaveCount:
- MetadataName = "llvm.loop.interleave.count";
- break;
- case LoopHintAttr::Unroll:
- // With the unroll loop hint, a non-zero value indicates full unrolling.
- MetadataName = State == LoopHintAttr::Disable ? "llvm.loop.unroll.disable"
- : "llvm.loop.unroll.full";
- break;
- case LoopHintAttr::UnrollCount:
- MetadataName = "llvm.loop.unroll.count";
- break;
- }
-
- Expr *ValueExpr = LH->getValue();
- int ValueInt = 1;
- if (ValueExpr) {
- llvm::APSInt ValueAPS =
- ValueExpr->EvaluateKnownConstInt(CGM.getContext());
- ValueInt = static_cast<int>(ValueAPS.getSExtValue());
- }
-
- llvm::Constant *Value;
- llvm::MDString *Name;
- switch (Option) {
- case LoopHintAttr::Vectorize:
- case LoopHintAttr::Interleave:
- if (State != LoopHintAttr::Disable) {
- // FIXME: In the future I will modifiy the behavior of the metadata
- // so we can enable/disable vectorization and interleaving separately.
- Name = llvm::MDString::get(Context, "llvm.loop.vectorize.enable");
- Value = Builder.getTrue();
- break;
- }
- // Vectorization/interleaving is disabled, set width/count to 1.
- ValueInt = 1;
- // Fallthrough.
- case LoopHintAttr::VectorizeWidth:
- case LoopHintAttr::InterleaveCount:
- case LoopHintAttr::UnrollCount:
- Name = llvm::MDString::get(Context, MetadataName);
- Value = llvm::ConstantInt::get(Int32Ty, ValueInt);
- break;
- case LoopHintAttr::Unroll:
- Name = llvm::MDString::get(Context, MetadataName);
- Value = nullptr;
- break;
- }
-
- SmallVector<llvm::Metadata *, 2> OpValues;
- OpValues.push_back(Name);
- if (Value)
- OpValues.push_back(llvm::ConstantAsMetadata::get(Value));
-
- // Set or overwrite metadata indicated by Name.
- Metadata.push_back(llvm::MDNode::get(Context, OpValues));
- }
-
- // FIXME: This condition is never false. Should it be an assert?
- if (!Metadata.empty()) {
- // Add llvm.loop MDNode to CondBr.
- llvm::MDNode *LoopID = llvm::MDNode::get(Context, Metadata);
- LoopID->replaceOperandWith(0, LoopID); // First op points to itself.
-
- CondBr->setMetadata("llvm.loop", LoopID);
- }
-}
-
void CodeGenFunction::EmitWhileStmt(const WhileStmt &S,
ArrayRef<const Attr *> WhileAttrs) {
// Emit the header for the loop, which will also become
@@ -694,7 +600,7 @@ void CodeGenFunction::EmitWhileStmt(const WhileStmt &S,
JumpDest LoopHeader = getJumpDestInCurrentScope("while.cond");
EmitBlock(LoopHeader.getBlock());
- LoopStack.push(LoopHeader.getBlock(), WhileAttrs);
+ LoopStack.push(LoopHeader.getBlock(), CGM.getContext(), WhileAttrs);
// Create an exit block for when the condition fails, which will
// also become the break target.
@@ -733,7 +639,7 @@ void CodeGenFunction::EmitWhileStmt(const WhileStmt &S,
llvm::BasicBlock *ExitBlock = LoopExit.getBlock();
if (ConditionScope.requiresCleanups())
ExitBlock = createBasicBlock("while.exit");
- llvm::BranchInst *CondBr = Builder.CreateCondBr(
+ Builder.CreateCondBr(
BoolCondVal, LoopBody, ExitBlock,
createProfileWeightsForLoop(S.getCond(), getProfileCount(S.getBody())));
@@ -741,9 +647,6 @@ void CodeGenFunction::EmitWhileStmt(const WhileStmt &S,
EmitBlock(ExitBlock);
EmitBranchThroughCleanup(LoopExit);
}
-
- // Attach metadata to loop body conditional branch.
- EmitCondBrHints(LoopBody->getContext(), CondBr, WhileAttrs);
}
// Emit the loop body. We have to emit this in a cleanup scope
@@ -788,7 +691,7 @@ void CodeGenFunction::EmitDoStmt(const DoStmt &S,
// Emit the body of the loop.
llvm::BasicBlock *LoopBody = createBasicBlock("do.body");
- LoopStack.push(LoopBody, DoAttrs);
+ LoopStack.push(LoopBody, CGM.getContext(), DoAttrs);
EmitBlockWithFallThrough(LoopBody, &S);
{
@@ -818,12 +721,9 @@ void CodeGenFunction::EmitDoStmt(const DoStmt &S,
// As long as the condition is true, iterate the loop.
if (EmitBoolCondBranch) {
uint64_t BackedgeCount = getProfileCount(S.getBody()) - ParentCount;
- llvm::BranchInst *CondBr = Builder.CreateCondBr(
+ Builder.CreateCondBr(
BoolCondVal, LoopBody, LoopExit.getBlock(),
createProfileWeightsForLoop(S.getCond(), BackedgeCount));
-
- // Attach metadata to loop body conditional branch.
- EmitCondBrHints(LoopBody->getContext(), CondBr, DoAttrs);
}
LoopStack.pop();
@@ -854,7 +754,7 @@ void CodeGenFunction::EmitForStmt(const ForStmt &S,
llvm::BasicBlock *CondBlock = Continue.getBlock();
EmitBlock(CondBlock);
- LoopStack.push(CondBlock, ForAttrs);
+ LoopStack.push(CondBlock, CGM.getContext(), ForAttrs);
// If the for loop doesn't have an increment we can just use the
// condition as the continue block. Otherwise we'll need to create
@@ -888,13 +788,10 @@ void CodeGenFunction::EmitForStmt(const ForStmt &S,
// C99 6.8.5p2/p4: The first substatement is executed if the expression
// compares unequal to 0. The condition must be a scalar type.
llvm::Value *BoolCondVal = EvaluateExprAsBool(S.getCond());
- llvm::BranchInst *CondBr = Builder.CreateCondBr(
+ Builder.CreateCondBr(
BoolCondVal, ForBody, ExitBlock,
createProfileWeightsForLoop(S.getCond(), getProfileCount(S.getBody())));
- // Attach metadata to loop body conditional branch.
- EmitCondBrHints(ForBody->getContext(), CondBr, ForAttrs);
-
if (ExitBlock != LoopExit.getBlock()) {
EmitBlock(ExitBlock);
EmitBranchThroughCleanup(LoopExit);
@@ -952,7 +849,7 @@ CodeGenFunction::EmitCXXForRangeStmt(const CXXForRangeStmt &S,
llvm::BasicBlock *CondBlock = createBasicBlock("for.cond");
EmitBlock(CondBlock);
- LoopStack.push(CondBlock, ForAttrs);
+ LoopStack.push(CondBlock, CGM.getContext(), ForAttrs);
// If there are any cleanups between here and the loop-exit scope,
// create a block to stage a loop exit along.
@@ -966,13 +863,10 @@ CodeGenFunction::EmitCXXForRangeStmt(const CXXForRangeStmt &S,
// The body is executed if the expression, contextually converted
// to bool, is true.
llvm::Value *BoolCondVal = EvaluateExprAsBool(S.getCond());
- llvm::BranchInst *CondBr = Builder.CreateCondBr(
+ Builder.CreateCondBr(
BoolCondVal, ForBody, ExitBlock,
createProfileWeightsForLoop(S.getCond(), getProfileCount(S.getBody())));
- // Attach metadata to loop body conditional branch.
- EmitCondBrHints(ForBody->getContext(), CondBr, ForAttrs);
-
if (ExitBlock != LoopExit.getBlock()) {
EmitBlock(ExitBlock);
EmitBranchThroughCleanup(LoopExit);
diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index 80929ab55c6..b7d6bbd93d2 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -2018,8 +2018,6 @@ public:
void EmitIndirectGotoStmt(const IndirectGotoStmt &S);
void EmitIfStmt(const IfStmt &S);
- void EmitCondBrHints(llvm::LLVMContext &Context, llvm::BranchInst *CondBr,
- ArrayRef<const Attr *> Attrs);
void EmitWhileStmt(const WhileStmt &S,
ArrayRef<const Attr *> Attrs = None);
void EmitDoStmt(const DoStmt &S, ArrayRef<const Attr *> Attrs = None);
OpenPOWER on IntegriCloud