r243315 - Use CGLoopInfo to emit metadata for loop hint pragmas.
Tyler Nowicki
tyler.nowicki at gmail.com
Mon Jul 27 13:10:20 PDT 2015
Author: tnowicki
Date: Mon Jul 27 15:10:20 2015
New Revision: 243315
URL: http://llvm.org/viewvc/llvm-project?rev=243315&view=rev
Log:
Use CGLoopInfo to emit metadata for loop hint pragmas.
When ‘#pragma clang loop vectorize(assume_safety)’ was specified on a loop other loop hints were lost. The problem is that CGLoopInfo attaches metadata differently than EmitCondBrHints in CGStmt. For do-loops CGLoopInfo attaches metadata to the br in the body block and for while and for loops, the inc block. EmitCondBrHints on the other hand always attaches data to the br in the cond block. When specifying assume_safety CGLoopInfo emits an empty llvm.loop metadata shadowing the metadata in the cond block. Loop transformations like rotate and unswitch would then eliminate the cond block and its non-empty metadata.
This patch unifies both approaches for adding metadata and modifies the existing safety tests to include non-assume_safety loop hints.
Modified:
cfe/trunk/lib/CodeGen/CGLoopInfo.cpp
cfe/trunk/lib/CodeGen/CGLoopInfo.h
cfe/trunk/lib/CodeGen/CGStmt.cpp
cfe/trunk/lib/CodeGen/CodeGenFunction.h
cfe/trunk/test/CodeGenCXX/pragma-loop-safety.cpp
cfe/trunk/test/CodeGenCXX/pragma-loop.cpp
cfe/trunk/test/CodeGenCXX/pragma-unroll.cpp
Modified: cfe/trunk/lib/CodeGen/CGLoopInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGLoopInfo.cpp?rev=243315&r1=243314&r2=243315&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGLoopInfo.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGLoopInfo.cpp Mon Jul 27 15:10:20 2015
@@ -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(LLVMContex
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(LLVMContex
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(LLVMContex
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, c
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 *Hea
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() {
Modified: cfe/trunk/lib/CodeGen/CGLoopInfo.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGLoopInfo.h?rev=243315&r1=243314&r2=243315&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGLoopInfo.h (original)
+++ cfe/trunk/lib/CodeGen/CGLoopInfo.h Mon Jul 27 15:10:20 2015
@@ -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(); }
Modified: cfe/trunk/lib/CodeGen/CGStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGStmt.cpp?rev=243315&r1=243314&r2=243315&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGStmt.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGStmt.cpp Mon Jul 27 15:10:20 2015
@@ -593,100 +593,6 @@ void CodeGenFunction::EmitIfStmt(const I
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(cons
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(cons
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(cons
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 D
// 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 D
// 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
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
// 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(con
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(con
// 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);
Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.h?rev=243315&r1=243314&r2=243315&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenFunction.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.h Mon Jul 27 15:10:20 2015
@@ -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);
Modified: cfe/trunk/test/CodeGenCXX/pragma-loop-safety.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/pragma-loop-safety.cpp?rev=243315&r1=243314&r2=243315&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/pragma-loop-safety.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/pragma-loop-safety.cpp Mon Jul 27 15:10:20 2015
@@ -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}
Modified: cfe/trunk/test/CodeGenCXX/pragma-loop.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/pragma-loop.cpp?rev=243315&r1=243314&r2=243315&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/pragma-loop.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/pragma-loop.cpp Mon Jul 27 15:10:20 2015
@@ -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 Leng
#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 Leng
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, i
#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
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 Len
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}
Modified: cfe/trunk/test/CodeGenCXX/pragma-unroll.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/pragma-unroll.cpp?rev=243315&r1=243314&r2=243315&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/pragma-unroll.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/pragma-unroll.cpp Mon Jul 27 15:10:20 2015
@@ -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 Leng
// 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 Leng
// 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;
}
}
More information about the cfe-commits
mailing list