diff options
-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 | ||||
-rw-r--r-- | clang/test/CodeGenCXX/pragma-loop-safety.cpp | 33 | ||||
-rw-r--r-- | clang/test/CodeGenCXX/pragma-loop.cpp | 60 | ||||
-rw-r--r-- | clang/test/CodeGenCXX/pragma-unroll.cpp | 19 |
7 files changed, 205 insertions, 184 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); diff --git a/clang/test/CodeGenCXX/pragma-loop-safety.cpp b/clang/test/CodeGenCXX/pragma-loop-safety.cpp index d12e4127491..393f0a3e43f 100644 --- a/clang/test/CodeGenCXX/pragma-loop-safety.cpp +++ b/clang/test/CodeGenCXX/pragma-loop-safety.cpp @@ -2,48 +2,53 @@ // Verify assume_safety vectorization is recognized. void vectorize_test(int *List, int Length) { -// CHECK: define {{.*}} @_Z14vectorize_testPii +// CHECK: define {{.*}} @_Z14vectorize_test // CHECK: [[LOAD1_IV:.+]] = load i32, i32* [[IV1:[^,]+]], {{.*}}!llvm.mem.parallel_loop_access ![[LOOP1_ID:[0-9]+]] // CHECK-NEXT: [[LOAD1_LEN:.+]] = load i32, i32* [[LEN1:.+]], {{.*}}!llvm.mem.parallel_loop_access ![[LOOP1_ID]] // CHECK-NEXT: [[CMP1:.+]] = icmp slt i32[[LOAD1_IV]],[[LOAD1_LEN]] -// CHECK-NEXT: br i1[[CMP1]], label %[[LOOP1_BODY:[^,]+]], label %[[LOOP1_END:[^,]+]], !llvm.loop ![[LOOP1_HINTS:[0-9]+]] -#pragma clang loop vectorize(assume_safety) +// CHECK-NEXT: br i1[[CMP1]], label %[[LOOP1_BODY:[^,]+]], label %[[LOOP1_END:[^,]+]] +#pragma clang loop vectorize(assume_safety) interleave(disable) unroll(disable) for (int i = 0; i < Length; i++) { - // CHECK: [[LOOP1_BODY]] - // CHECK-NEXT: [[RHIV1:.+]] = load i32, i32* [[IV1]], {{.*}}!llvm.mem.parallel_loop_access ![[LOOP1_ID]] + // CHECK: [[RHIV1:.+]] = load i32, i32* [[IV1]], {{.*}}!llvm.mem.parallel_loop_access ![[LOOP1_ID]] // CHECK-NEXT: [[CALC1:.+]] = mul nsw i32[[RHIV1]], 2 // CHECK-NEXT: [[SIV1:.+]] = load i32, i32* [[IV1]]{{.*}}!llvm.mem.parallel_loop_access ![[LOOP1_ID]] // CHECK-NEXT: [[INDEX1:.+]] = sext i32[[SIV1]] to i64 // CHECK-NEXT: [[ARRAY1:.+]] = load i32*, i32** [[LIST1:.*]], {{.*}}!llvm.mem.parallel_loop_access ![[LOOP1_ID]] // CHECK-NEXT: [[PTR1:.+]] = getelementptr inbounds i32, i32*[[ARRAY1]], i64[[INDEX1]] // CHECK-NEXT: store i32[[CALC1]], i32*[[PTR1]], {{.*}}!llvm.mem.parallel_loop_access ![[LOOP1_ID]] + // CHECK-NEXT: br label [[LOOP1_INC:[^,]+]] List[i] = i * 2; + + // CHECK: br label [[LOOP1_COND:[^,]+]], !llvm.loop ![[LOOP1_HINTS:[0-9]+]] } - // CHECK: [[LOOP1_END]] } // Verify assume_safety interleaving is recognized. void interleave_test(int *List, int Length) { -// CHECK: define {{.*}} @_Z15interleave_testPii +// CHECK: define {{.*}} @_Z15interleave_test // CHECK: [[LOAD2_IV:.+]] = load i32, i32* [[IV2:[^,]+]], {{.*}}!llvm.mem.parallel_loop_access ![[LOOP2_ID:[0-9]+]] // CHECK-NEXT: [[LOAD2_LEN:.+]] = load i32, i32* [[LEN2:.+]], {{.*}}!llvm.mem.parallel_loop_access ![[LOOP2_ID]] // CHECK-NEXT: [[CMP2:.+]] = icmp slt i32[[LOAD2_IV]],[[LOAD2_LEN]] -// CHECK-NEXT: br i1[[CMP2]], label %[[LOOP2_BODY:[^,]+]], label %[[LOOP2_END:[^,]+]], !llvm.loop ![[LOOP2_HINTS:[0-9]+]] -#pragma clang loop interleave(assume_safety) +// CHECK-NEXT: br i1[[CMP2]], label %[[LOOP2_BODY:[^,]+]], label %[[LOOP2_END:[^,]+]] +#pragma clang loop interleave(assume_safety) vectorize(disable) unroll(disable) for (int i = 0; i < Length; i++) { - // CHECK: [[LOOP2_BODY]] - // CHECK-NEXT: [[RHIV2:.+]] = load i32, i32* [[IV2]], {{.*}}!llvm.mem.parallel_loop_access ![[LOOP2_ID]] + // CHECK: [[RHIV2:.+]] = load i32, i32* [[IV2]], {{.*}}!llvm.mem.parallel_loop_access ![[LOOP2_ID]] // CHECK-NEXT: [[CALC2:.+]] = mul nsw i32[[RHIV2]], 2 // CHECK-NEXT: [[SIV2:.+]] = load i32, i32* [[IV2]]{{.*}}!llvm.mem.parallel_loop_access ![[LOOP2_ID]] // CHECK-NEXT: [[INDEX2:.+]] = sext i32[[SIV2]] to i64 // CHECK-NEXT: [[ARRAY2:.+]] = load i32*, i32** [[LIST2:.*]], {{.*}}!llvm.mem.parallel_loop_access ![[LOOP2_ID]] // CHECK-NEXT: [[PTR2:.+]] = getelementptr inbounds i32, i32*[[ARRAY2]], i64[[INDEX2]] // CHECK-NEXT: store i32[[CALC2]], i32*[[PTR2]], {{.*}}!llvm.mem.parallel_loop_access ![[LOOP2_ID]] + // CHECK-NEXT: br label [[LOOP2_INC:[^,]+]] List[i] = i * 2; + + // CHECK: br label [[LOOP2_COND:[^,]+]], !llvm.loop ![[LOOP2_HINTS:[0-9]+]] } - // CHECK: [[LOOP2_END]] } -// CHECK: ![[LOOP1_HINTS]] = distinct !{![[LOOP1_HINTS]], ![[INTENABLE_1:.*]]} +// CHECK: ![[LOOP1_HINTS]] = distinct !{![[LOOP1_HINTS]], ![[INTERLEAVE_1:[0-9]+]], ![[INTENABLE_1:[0-9]+]], ![[UNROLL_DISABLE:[0-9]+]]} +// CHECK: ![[INTERLEAVE_1]] = !{!"llvm.loop.interleave.count", i32 1} // CHCCK: ![[INTENABLE_1]] = !{!"llvm.loop.vectorize.enable", i1 true} -// CHECK: ![[LOOP2_HINTS]] = distinct !{![[LOOP2_HINTS]], ![[INTENABLE_1:.*]]} +// CHECK: ![[UNROLL_DISABLE]] = !{!"llvm.loop.unroll.disable"} +// CHECK: ![[LOOP2_HINTS]] = distinct !{![[LOOP2_HINTS]], ![[WIDTH_1:[0-9]+]], ![[INTENABLE_1]], ![[UNROLL_DISABLE]]} +// CHECK: ![[WIDTH_1]] = !{!"llvm.loop.vectorize.width", i32 1} diff --git a/clang/test/CodeGenCXX/pragma-loop.cpp b/clang/test/CodeGenCXX/pragma-loop.cpp index dd40c1d7260..b85e0b49b9d 100644 --- a/clang/test/CodeGenCXX/pragma-loop.cpp +++ b/clang/test/CodeGenCXX/pragma-loop.cpp @@ -10,7 +10,7 @@ void while_test(int *List, int Length) { #pragma clang loop vectorize_width(4) #pragma clang loop unroll(full) while (i < Length) { - // CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !llvm.loop ![[LOOP_1:.*]] + // CHECK: br label {{.*}}, !llvm.loop ![[LOOP_1:.*]] List[i] = i * 2; i++; } @@ -36,7 +36,7 @@ void for_test(int *List, int Length) { #pragma clang loop interleave_count(static_cast<int>(Tuner::Interleave)) #pragma clang loop unroll_count(static_cast<int>(Tuner::Unroll)) for (int i = 0; i < Length; i++) { - // CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !llvm.loop ![[LOOP_3:.*]] + // CHECK: br label {{.*}}, !llvm.loop ![[LOOP_3:.*]] List[i] = i * 2; } } @@ -48,7 +48,7 @@ void for_range_test() { #pragma clang loop vectorize_width(2) interleave_count(2) for (int i : List) { - // CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !llvm.loop ![[LOOP_4:.*]] + // CHECK: br label {{.*}}, !llvm.loop ![[LOOP_4:.*]] List[i] = i; } } @@ -57,7 +57,7 @@ void for_range_test() { void disable_test(int *List, int Length) { #pragma clang loop vectorize(disable) unroll(disable) for (int i = 0; i < Length; i++) { - // CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !llvm.loop ![[LOOP_5:.*]] + // CHECK: br label {{.*}}, !llvm.loop ![[LOOP_5:.*]] List[i] = i * 2; } } @@ -71,7 +71,7 @@ void for_define_test(int *List, int Length, int Value) { #pragma clang loop vectorize_width(VECWIDTH) interleave_count(INTCOUNT) #pragma clang loop unroll_count(UNROLLCOUNT) for (int i = 0; i < Length; i++) { - // CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !llvm.loop ![[LOOP_6:.*]] + // CHECK: br label {{.*}}, !llvm.loop ![[LOOP_6:.*]] List[i] = i * Value; } } @@ -80,13 +80,13 @@ void for_define_test(int *List, int Length, int Value) { void for_contant_expression_test(int *List, int Length) { #pragma clang loop vectorize_width(1 + 4) for (int i = 0; i < Length; i++) { - // CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !llvm.loop ![[LOOP_7:.*]] + // CHECK: br label {{.*}}, !llvm.loop ![[LOOP_7:.*]] List[i] = i; } #pragma clang loop vectorize_width(3 + VECWIDTH) for (int i = 0; i < Length; i++) { - // CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !llvm.loop ![[LOOP_8:.*]] + // CHECK: br label {{.*}}, !llvm.loop ![[LOOP_8:.*]] List[i] += i; } } @@ -96,7 +96,7 @@ template <typename A> void for_template_test(A *List, int Length, A Value) { #pragma clang loop vectorize_width(8) interleave_count(8) unroll_count(8) for (int i = 0; i < Length; i++) { - // CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !llvm.loop ![[LOOP_9:.*]] + // CHECK: br label {{.*}}, !llvm.loop ![[LOOP_9:.*]] List[i] = i * Value; } } @@ -110,7 +110,7 @@ void for_template_define_test(A *List, int Length, A Value) { #pragma clang loop vectorize_width(VWidth) interleave_count(ICount) #pragma clang loop unroll_count(UCount) for (int i = 0; i < Length; i++) { - // CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !llvm.loop ![[LOOP_10:.*]] + // CHECK: br label {{.*}}, !llvm.loop ![[LOOP_10:.*]] List[i] = i * Value; } } @@ -120,26 +120,26 @@ template <typename A, int V, int I, int U> void for_template_constant_expression_test(A *List, int Length) { #pragma clang loop vectorize_width(V) interleave_count(I) unroll_count(U) for (int i = 0; i < Length; i++) { - // CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !llvm.loop ![[LOOP_11:.*]] + // CHECK: br label {{.*}}, !llvm.loop ![[LOOP_11:.*]] List[i] = i; } #pragma clang loop vectorize_width(V * 2 + VECWIDTH) interleave_count(I * 2 + INTCOUNT) unroll_count(U * 2 + UNROLLCOUNT) for (int i = 0; i < Length; i++) { - // CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !llvm.loop ![[LOOP_12:.*]] + // CHECK: br label {{.*}}, !llvm.loop ![[LOOP_12:.*]] List[i] += i; } const int Scale = 4; #pragma clang loop vectorize_width(Scale * V) interleave_count(Scale * I) unroll_count(Scale * U) for (int i = 0; i < Length; i++) { - // CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !llvm.loop ![[LOOP_13:.*]] + // CHECK: br label {{.*}}, !llvm.loop ![[LOOP_13:.*]] List[i] += i; } #pragma clang loop vectorize_width((Scale * V) + 2) for (int i = 0; i < Length; i++) { - // CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !llvm.loop ![[LOOP_14:.*]] + // CHECK: br label {{.*}}, !llvm.loop ![[LOOP_14:.*]] List[i] += i; } } @@ -157,35 +157,35 @@ void template_test(double *List, int Length) { for_template_constant_expression_test<double, 2, 4, 8>(List, Length); } -// CHECK: ![[LOOP_1]] = distinct !{![[LOOP_1]], ![[UNROLL_FULL:.*]], ![[WIDTH_4:.*]], ![[INTERLEAVE_4:.*]], ![[INTENABLE_1:.*]]} -// CHECK: ![[UNROLL_FULL]] = !{!"llvm.loop.unroll.full"} +// CHECK: ![[LOOP_1]] = distinct !{![[LOOP_1]], ![[WIDTH_4:.*]], ![[INTERLEAVE_4:.*]], ![[INTENABLE_1:.*]], ![[UNROLL_FULL:.*]]} // CHECK: ![[WIDTH_4]] = !{!"llvm.loop.vectorize.width", i32 4} // CHECK: ![[INTERLEAVE_4]] = !{!"llvm.loop.interleave.count", i32 4} // CHECK: ![[INTENABLE_1]] = !{!"llvm.loop.vectorize.enable", i1 true} -// CHECK: ![[LOOP_2]] = distinct !{![[LOOP_2:.*]], ![[UNROLL_DISABLE:.*]], ![[INTERLEAVE_4:.*]], ![[WIDTH_8:.*]]} -// CHECK: ![[UNROLL_DISABLE]] = !{!"llvm.loop.unroll.disable"} +// CHECK: ![[UNROLL_FULL]] = !{!"llvm.loop.unroll.full"} +// CHECK: ![[LOOP_2]] = distinct !{![[LOOP_2:.*]], ![[WIDTH_8:.*]], ![[INTERLEAVE_4:.*]], ![[UNROLL_DISABLE:.*]]} // CHECK: ![[WIDTH_8]] = !{!"llvm.loop.vectorize.width", i32 8} -// CHECK: ![[LOOP_3]] = distinct !{![[LOOP_3]], ![[UNROLL_8:.*]], ![[INTERLEAVE_4:.*]], ![[ENABLE_1:.*]]} +// CHECK: ![[UNROLL_DISABLE]] = !{!"llvm.loop.unroll.disable"} +// CHECK: ![[LOOP_3]] = distinct !{![[LOOP_3]], ![[INTERLEAVE_4:.*]], ![[UNROLL_8:.*]], ![[INTENABLE_1:.*]]} // CHECK: ![[UNROLL_8]] = !{!"llvm.loop.unroll.count", i32 8} -// CHECK: ![[LOOP_4]] = distinct !{![[LOOP_4]], ![[INTERLEAVE_2:.*]], ![[WIDTH_2:.*]]} -// CHECK: ![[INTERLEAVE_2]] = !{!"llvm.loop.interleave.count", i32 2} +// CHECK: ![[LOOP_4]] = distinct !{![[LOOP_4]], ![[WIDTH_2:.*]], ![[INTERLEAVE_2:.*]]} // CHECK: ![[WIDTH_2]] = !{!"llvm.loop.vectorize.width", i32 2} -// CHECK: ![[LOOP_5]] = distinct !{![[LOOP_5]], ![[UNROLL_DISABLE:.*]], ![[WIDTH_1:.*]]} +// CHECK: ![[INTERLEAVE_2]] = !{!"llvm.loop.interleave.count", i32 2} +// CHECK: ![[LOOP_5]] = distinct !{![[LOOP_5]], ![[WIDTH_1:.*]], ![[UNROLL_DISABLE:.*]]} // CHECK: ![[WIDTH_1]] = !{!"llvm.loop.vectorize.width", i32 1} -// CHECK: ![[LOOP_6]] = distinct !{![[LOOP_6]], ![[UNROLL_8:.*]], ![[INTERLEAVE_2:.*]], ![[WIDTH_2:.*]]} +// CHECK: ![[LOOP_6]] = distinct !{![[LOOP_6]], ![[WIDTH_2:.*]], ![[INTERLEAVE_2:.*]], ![[UNROLL_8:.*]]} // CHECK: ![[LOOP_7]] = distinct !{![[LOOP_7]], ![[WIDTH_5:.*]]} // CHECK: ![[WIDTH_5]] = !{!"llvm.loop.vectorize.width", i32 5} // CHECK: ![[LOOP_8]] = distinct !{![[LOOP_8]], ![[WIDTH_5:.*]]} -// CHECK: ![[LOOP_9]] = distinct !{![[LOOP_9]], ![[UNROLL_8:.*]], ![[INTERLEAVE_8:.*]], ![[WIDTH_8:.*]]} +// CHECK: ![[LOOP_9]] = distinct !{![[LOOP_9]], ![[WIDTH_8:.*]], ![[INTERLEAVE_8:.*]], ![[UNROLL_8:.*]]} // CHECK: ![[INTERLEAVE_8]] = !{!"llvm.loop.interleave.count", i32 8} -// CHECK: ![[LOOP_10]] = distinct !{![[LOOP_10]], ![[UNROLL_8:.*]], ![[INTERLEAVE_2:.*]], ![[WIDTH_2:.*]]} -// CHECK: ![[LOOP_11]] = distinct !{![[LOOP_11]], ![[UNROLL_8:.*]], ![[INTERLEAVE_4:.*]], ![[WIDTH_2:.*]]} -// CHECK: ![[LOOP_12]] = distinct !{![[LOOP_12]], ![[UNROLL_24:.*]], ![[INTERLEAVE_10:.*]], ![[WIDTH_6:.*]]} -// CHECK: ![[UNROLL_24]] = !{!"llvm.loop.unroll.count", i32 24} -// CHECK: ![[INTERLEAVE_10]] = !{!"llvm.loop.interleave.count", i32 10} +// CHECK: ![[LOOP_10]] = distinct !{![[LOOP_10]], ![[WIDTH_2:.*]], ![[INTERLEAVE_2:.*]], ![[UNROLL_8:.*]]} +// CHECK: ![[LOOP_11]] = distinct !{![[LOOP_11]], ![[WIDTH_2:.*]], ![[INTERLEAVE_4:.*]], ![[UNROLL_8:.*]]} +// CHECK: ![[LOOP_12]] = distinct !{![[LOOP_12]], ![[WIDTH_6:.*]], ![[INTERLEAVE_10:.*]], ![[UNROLL_24:.*]]} // CHECK: ![[WIDTH_6]] = !{!"llvm.loop.vectorize.width", i32 6} -// CHECK: ![[LOOP_13]] = distinct !{![[LOOP_13]], ![[UNROLL_32:.*]], ![[INTERLEAVE_16:.*]], ![[WIDTH_8:.*]]} -// CHECK: ![[UNROLL_32]] = !{!"llvm.loop.unroll.count", i32 32} +// CHECK: ![[INTERLEAVE_10]] = !{!"llvm.loop.interleave.count", i32 10} +// CHECK: ![[UNROLL_24]] = !{!"llvm.loop.unroll.count", i32 24} +// CHECK: ![[LOOP_13]] = distinct !{![[LOOP_13]], ![[WIDTH_8:.*]], ![[INTERLEAVE_16:.*]], ![[UNROLL_32:.*]]} // CHECK: ![[INTERLEAVE_16]] = !{!"llvm.loop.interleave.count", i32 16} +// CHECK: ![[UNROLL_32]] = !{!"llvm.loop.unroll.count", i32 32} // CHECK: ![[LOOP_14]] = distinct !{![[LOOP_14]], ![[WIDTH_10:.*]]} // CHECK: ![[WIDTH_10]] = !{!"llvm.loop.vectorize.width", i32 10} diff --git a/clang/test/CodeGenCXX/pragma-unroll.cpp b/clang/test/CodeGenCXX/pragma-unroll.cpp index 8b73fa6c8aa..0b13bde0fa0 100644 --- a/clang/test/CodeGenCXX/pragma-unroll.cpp +++ b/clang/test/CodeGenCXX/pragma-unroll.cpp @@ -7,7 +7,7 @@ void while_test(int *List, int Length) { #pragma unroll while (i < Length) { - // CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !llvm.loop ![[LOOP_1:.*]] + // CHECK: br label {{.*}}, !llvm.loop ![[LOOP_1:.*]] List[i] = i * 2; i++; } @@ -15,6 +15,7 @@ void while_test(int *List, int Length) { // Verify do loop is recognized after multi-option pragma clang loop directive. void do_test(int *List, int Length) { + // CHECK: define {{.*}} @_Z7do_test int i = 0; #pragma nounroll @@ -27,20 +28,22 @@ void do_test(int *List, int Length) { // Verify for loop is recognized after unroll pragma. void for_test(int *List, int Length) { +// CHECK: define {{.*}} @_Z8for_test #pragma unroll 8 for (int i = 0; i < Length; i++) { - // CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !llvm.loop ![[LOOP_3:.*]] + // CHECK: br label {{.*}}, !llvm.loop ![[LOOP_3:.*]] List[i] = i * 2; } } // Verify c++11 for range loop is recognized after unroll pragma. void for_range_test() { + // CHECK: define {{.*}} @_Z14for_range_test double List[100]; #pragma unroll(4) for (int i : List) { - // CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !llvm.loop ![[LOOP_4:.*]] + // CHECK: br label {{.*}}, !llvm.loop ![[LOOP_4:.*]] List[i] = i; } } @@ -49,9 +52,10 @@ void for_range_test() { // Verify defines are correctly resolved in unroll pragmas. void for_define_test(int *List, int Length, int Value) { +// CHECK: define {{.*}} @_Z15for_define_test #pragma unroll(UNROLLCOUNT) for (int i = 0; i < Length; i++) { - // CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !llvm.loop ![[LOOP_5:.*]] + // CHECK: br label {{.*}}, !llvm.loop ![[LOOP_5:.*]] List[i] = i * Value; } } @@ -59,9 +63,10 @@ void for_define_test(int *List, int Length, int Value) { // Verify metadata is generated when template is used. template <typename A> void for_template_test(A *List, int Length, A Value) { +// CHECK: define {{.*}} @_Z13template_test #pragma unroll 8 for (int i = 0; i < Length; i++) { - // CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !llvm.loop ![[LOOP_6:.*]] + // CHECK: br label {{.*}}, !llvm.loop ![[LOOP_6:.*]] List[i] = i * Value; } } @@ -69,9 +74,11 @@ void for_template_test(A *List, int Length, A Value) { // Verify define is resolved correctly when template is used. template <typename A> void for_template_define_test(A *List, int Length, A Value) { +// CHECK: define {{.*}} @_Z24for_template_define_test + #pragma unroll(UNROLLCOUNT) for (int i = 0; i < Length; i++) { - // CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !llvm.loop ![[LOOP_7:.*]] + // CHECK: br label {{.*}}, !llvm.loop ![[LOOP_7:.*]] List[i] = i * Value; } } |