diff options
author | Aaron Ballman <aaron@aaronballman.com> | 2014-06-06 12:40:24 +0000 |
---|---|---|
committer | Aaron Ballman <aaron@aaronballman.com> | 2014-06-06 12:40:24 +0000 |
commit | b06b15aa28d0b2efce5a2eb58ae0a73fa1ffe94d (patch) | |
tree | e0d0c2cd0c6a64f5cb212503bf62f3062c9e0ff9 /clang/lib/CodeGen | |
parent | 909b7490a338fac18c59317c48d970c50bcb6552 (diff) | |
download | bcm5719-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.cpp | 136 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenFunction.h | 14 |
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, |