summaryrefslogtreecommitdiffstats
path: root/clang/lib/CodeGen
diff options
context:
space:
mode:
authorAaron Ballman <aaron@aaronballman.com>2014-06-06 12:40:24 +0000
committerAaron Ballman <aaron@aaronballman.com>2014-06-06 12:40:24 +0000
commitb06b15aa28d0b2efce5a2eb58ae0a73fa1ffe94d (patch)
treee0d0c2cd0c6a64f5cb212503bf62f3062c9e0ff9 /clang/lib/CodeGen
parent909b7490a338fac18c59317c48d970c50bcb6552 (diff)
downloadbcm5719-llvm-b06b15aa28d0b2efce5a2eb58ae0a73fa1ffe94d.tar.gz
bcm5719-llvm-b06b15aa28d0b2efce5a2eb58ae0a73fa1ffe94d.zip
Adding a new #pragma for the vectorize and interleave optimization hints.
Patch thanks to Tyler Nowicki! llvm-svn: 210330
Diffstat (limited to 'clang/lib/CodeGen')
-rw-r--r--clang/lib/CodeGen/CGStmt.cpp136
-rw-r--r--clang/lib/CodeGen/CodeGenFunction.h14
2 files changed, 132 insertions, 18 deletions
diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp
index 534c16deeea..cca16249000 100644
--- a/clang/lib/CodeGen/CGStmt.cpp
+++ b/clang/lib/CodeGen/CGStmt.cpp
@@ -18,6 +18,7 @@
#include "clang/AST/StmtVisitor.h"
#include "clang/Basic/PrettyStackTrace.h"
#include "clang/Basic/TargetInfo.h"
+#include "clang/Sema/LoopHint.h"
#include "clang/Sema/SemaDiagnostic.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/IR/CallSite.h"
@@ -398,7 +399,23 @@ void CodeGenFunction::EmitLabelStmt(const LabelStmt &S) {
}
void CodeGenFunction::EmitAttributedStmt(const AttributedStmt &S) {
- EmitStmt(S.getSubStmt());
+ const Stmt *SubStmt = S.getSubStmt();
+ switch (SubStmt->getStmtClass()) {
+ case Stmt::DoStmtClass:
+ EmitDoStmt(cast<DoStmt>(*SubStmt), S.getAttrs());
+ break;
+ case Stmt::ForStmtClass:
+ EmitForStmt(cast<ForStmt>(*SubStmt), S.getAttrs());
+ break;
+ case Stmt::WhileStmtClass:
+ EmitWhileStmt(cast<WhileStmt>(*SubStmt), S.getAttrs());
+ break;
+ case Stmt::CXXForRangeStmtClass:
+ EmitCXXForRangeStmt(cast<CXXForRangeStmt>(*SubStmt), S.getAttrs());
+ break;
+ default:
+ EmitStmt(SubStmt);
+ }
}
void CodeGenFunction::EmitGotoStmt(const GotoStmt &S) {
@@ -504,7 +521,78 @@ void CodeGenFunction::EmitIfStmt(const IfStmt &S) {
EmitBlock(ContBlock, true);
}
-void CodeGenFunction::EmitWhileStmt(const WhileStmt &S) {
+void CodeGenFunction::EmitCondBrHints(llvm::LLVMContext &Context,
+ llvm::BranchInst *CondBr,
+ const ArrayRef<const Attr *> &Attrs) {
+ // Return if there are no hints.
+ if (Attrs.empty())
+ return;
+
+ // Add vectorize hints to the metadata on the conditional branch.
+ SmallVector<llvm::Value *, 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();
+ int ValueInt = LH->getValue();
+
+ const char *MetadataName;
+ switch (Option) {
+ case LoopHintAttr::Vectorize:
+ case LoopHintAttr::VectorizeWidth:
+ MetadataName = "llvm.vectorizer.width";
+ break;
+ case LoopHintAttr::Interleave:
+ case LoopHintAttr::InterleaveCount:
+ MetadataName = "llvm.vectorizer.unroll";
+ break;
+ }
+
+ llvm::Value *Value;
+ llvm::MDString *Name;
+ switch (Option) {
+ case LoopHintAttr::Vectorize:
+ case LoopHintAttr::Interleave:
+ if (ValueInt == 1) {
+ // 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.vectorizer.enable");
+ Value = Builder.getTrue();
+ break;
+ }
+ // Vectorization/interleaving is disabled, set width/count to 1.
+ ValueInt = 1;
+ // Fallthrough.
+ case LoopHintAttr::VectorizeWidth:
+ case LoopHintAttr::InterleaveCount:
+ Name = llvm::MDString::get(Context, MetadataName);
+ Value = llvm::ConstantInt::get(Int32Ty, ValueInt);
+ break;
+ }
+
+ SmallVector<llvm::Value *, 2> OpValues;
+ OpValues.push_back(Name);
+ OpValues.push_back(Value);
+
+ // Set or overwrite metadata indicated by Name.
+ Metadata.push_back(llvm::MDNode::get(Context, OpValues));
+ }
+
+ 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,
+ const ArrayRef<const Attr *> &WhileAttrs) {
RegionCounter Cnt = getPGORegionCounter(&S);
// Emit the header for the loop, which will also become
@@ -551,13 +639,17 @@ void CodeGenFunction::EmitWhileStmt(const WhileStmt &S) {
llvm::BasicBlock *ExitBlock = LoopExit.getBlock();
if (ConditionScope.requiresCleanups())
ExitBlock = createBasicBlock("while.exit");
- Builder.CreateCondBr(BoolCondVal, LoopBody, ExitBlock,
- PGO.createLoopWeights(S.getCond(), Cnt));
+ llvm::BranchInst *CondBr =
+ Builder.CreateCondBr(BoolCondVal, LoopBody, ExitBlock,
+ PGO.createLoopWeights(S.getCond(), Cnt));
if (ExitBlock != LoopExit.getBlock()) {
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
@@ -588,7 +680,8 @@ void CodeGenFunction::EmitWhileStmt(const WhileStmt &S) {
SimplifyForwardingBlocks(LoopHeader.getBlock());
}
-void CodeGenFunction::EmitDoStmt(const DoStmt &S) {
+void CodeGenFunction::EmitDoStmt(const DoStmt &S,
+ const ArrayRef<const Attr *> &DoAttrs) {
JumpDest LoopExit = getJumpDestInCurrentScope("do.end");
JumpDest LoopCond = getJumpDestInCurrentScope("do.cond");
@@ -628,9 +721,14 @@ void CodeGenFunction::EmitDoStmt(const DoStmt &S) {
EmitBoolCondBranch = false;
// As long as the condition is true, iterate the loop.
- if (EmitBoolCondBranch)
- Builder.CreateCondBr(BoolCondVal, LoopBody, LoopExit.getBlock(),
- PGO.createLoopWeights(S.getCond(), Cnt));
+ if (EmitBoolCondBranch) {
+ llvm::BranchInst *CondBr =
+ Builder.CreateCondBr(BoolCondVal, LoopBody, LoopExit.getBlock(),
+ PGO.createLoopWeights(S.getCond(), Cnt));
+
+ // Attach metadata to loop body conditional branch.
+ EmitCondBrHints(LoopBody->getContext(), CondBr, DoAttrs);
+ }
LoopStack.pop();
@@ -643,7 +741,8 @@ void CodeGenFunction::EmitDoStmt(const DoStmt &S) {
SimplifyForwardingBlocks(LoopCond.getBlock());
}
-void CodeGenFunction::EmitForStmt(const ForStmt &S) {
+void CodeGenFunction::EmitForStmt(const ForStmt &S,
+ const ArrayRef<const Attr *> &ForAttrs) {
JumpDest LoopExit = getJumpDestInCurrentScope("for.end");
RunCleanupsScope ForScope(*this);
@@ -699,8 +798,12 @@ 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());
- Builder.CreateCondBr(BoolCondVal, ForBody, ExitBlock,
- PGO.createLoopWeights(S.getCond(), Cnt));
+ llvm::BranchInst *CondBr =
+ Builder.CreateCondBr(BoolCondVal, ForBody, ExitBlock,
+ PGO.createLoopWeights(S.getCond(), Cnt));
+
+ // Attach metadata to loop body conditional branch.
+ EmitCondBrHints(ForBody->getContext(), CondBr, ForAttrs);
if (ExitBlock != LoopExit.getBlock()) {
EmitBlock(ExitBlock);
@@ -743,7 +846,9 @@ void CodeGenFunction::EmitForStmt(const ForStmt &S) {
EmitBlock(LoopExit.getBlock(), true);
}
-void CodeGenFunction::EmitCXXForRangeStmt(const CXXForRangeStmt &S) {
+void
+CodeGenFunction::EmitCXXForRangeStmt(const CXXForRangeStmt &S,
+ const ArrayRef<const Attr *> &ForAttrs) {
JumpDest LoopExit = getJumpDestInCurrentScope("for.end");
RunCleanupsScope ForScope(*this);
@@ -778,8 +883,11 @@ void CodeGenFunction::EmitCXXForRangeStmt(const CXXForRangeStmt &S) {
// The body is executed if the expression, contextually converted
// to bool, is true.
llvm::Value *BoolCondVal = EvaluateExprAsBool(S.getCond());
- Builder.CreateCondBr(BoolCondVal, ForBody, ExitBlock,
- PGO.createLoopWeights(S.getCond(), Cnt));
+ llvm::BranchInst *CondBr = Builder.CreateCondBr(
+ BoolCondVal, ForBody, ExitBlock, PGO.createLoopWeights(S.getCond(), Cnt));
+
+ // Attach metadata to loop body conditional branch.
+ EmitCondBrHints(ForBody->getContext(), CondBr, ForAttrs);
if (ExitBlock != LoopExit.getBlock()) {
EmitBlock(ExitBlock);
diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index b6c58e0ee16..570e1a89eb0 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -1860,9 +1860,14 @@ public:
void EmitGotoStmt(const GotoStmt &S);
void EmitIndirectGotoStmt(const IndirectGotoStmt &S);
void EmitIfStmt(const IfStmt &S);
- void EmitWhileStmt(const WhileStmt &S);
- void EmitDoStmt(const DoStmt &S);
- void EmitForStmt(const ForStmt &S);
+
+ void EmitCondBrHints(llvm::LLVMContext &Context, llvm::BranchInst *CondBr,
+ const ArrayRef<const Attr *> &Attrs);
+ void EmitWhileStmt(const WhileStmt &S,
+ const ArrayRef<const Attr *> &Attrs = None);
+ void EmitDoStmt(const DoStmt &S, const ArrayRef<const Attr *> &Attrs = None);
+ void EmitForStmt(const ForStmt &S,
+ const ArrayRef<const Attr *> &Attrs = None);
void EmitReturnStmt(const ReturnStmt &S);
void EmitDeclStmt(const DeclStmt &S);
void EmitBreakStmt(const BreakStmt &S);
@@ -1886,7 +1891,8 @@ public:
void EmitCXXTryStmt(const CXXTryStmt &S);
void EmitSEHTryStmt(const SEHTryStmt &S);
- void EmitCXXForRangeStmt(const CXXForRangeStmt &S);
+ void EmitCXXForRangeStmt(const CXXForRangeStmt &S,
+ const ArrayRef<const Attr *> &Attrs = None);
llvm::Function *EmitCapturedStmt(const CapturedStmt &S, CapturedRegionKind K);
llvm::Function *GenerateCapturedStmtFunction(const CapturedDecl *CD,
OpenPOWER on IntegriCloud