diff options
Diffstat (limited to 'clang/lib/CodeGen')
-rw-r--r-- | clang/lib/CodeGen/CGLoopInfo.cpp | 129 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGLoopInfo.h | 24 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGStmt.cpp | 122 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenFunction.h | 2 |
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); |