forked from OSchip/llvm-project
Add loop pragma for Loop Distribution
Summary: This is similar to other loop pragmas like 'vectorize'. Currently it only has state values: distribute(enable) and distribute(disable). When one of these is specified the corresponding loop metadata is generated: !{!"llvm.loop.distribute.enable", i1 true/false} As a result, loop distribution will be attempted on the loop even if Loop Distribution in not enabled globally. Analogously, with 'disable' distribution can be turned off for an individual loop even when the pass is otherwise enabled. There are some slight differences compared to the existing loop pragmas. 1. There is no 'assume_safety' variant which makes its handling slightly different from 'vectorize'/'interleave'. 2. Unlike the existing loop pragmas, it does not have a corresponding numeric pragma like 'vectorize' -> 'vectorize_width'. So for the consistency checks in CheckForIncompatibleAttributes we don't need to check it against other pragmas. We just need to check for duplicates of the same pragma. Reviewers: rsmith, dexonsmith, aaron.ballman Subscribers: bob.wilson, cfe-commits, hfinkel Differential Revision: http://reviews.llvm.org/D19403 llvm-svn: 272656
This commit is contained in:
parent
4fbf76f7c3
commit
2de463ece3
|
@ -2050,9 +2050,9 @@ Extensions for loop hint optimizations
|
||||||
|
|
||||||
The ``#pragma clang loop`` directive is used to specify hints for optimizing the
|
The ``#pragma clang loop`` directive is used to specify hints for optimizing the
|
||||||
subsequent for, while, do-while, or c++11 range-based for loop. The directive
|
subsequent for, while, do-while, or c++11 range-based for loop. The directive
|
||||||
provides options for vectorization, interleaving, and unrolling. Loop hints can
|
provides options for vectorization, interleaving, unrolling and
|
||||||
be specified before any loop and will be ignored if the optimization is not safe
|
distribution. Loop hints can be specified before any loop and will be ignored if
|
||||||
to apply.
|
the optimization is not safe to apply.
|
||||||
|
|
||||||
Vectorization and Interleaving
|
Vectorization and Interleaving
|
||||||
------------------------------
|
------------------------------
|
||||||
|
@ -2147,6 +2147,38 @@ to the same code size limit as with ``unroll(enable)``.
|
||||||
|
|
||||||
Unrolling of a loop can be prevented by specifying ``unroll(disable)``.
|
Unrolling of a loop can be prevented by specifying ``unroll(disable)``.
|
||||||
|
|
||||||
|
Loop Distribution
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
Loop Distribution allows splitting a loop into multiple loops. This is
|
||||||
|
beneficial for example when the entire loop cannot be vectorized but some of the
|
||||||
|
resulting loops can.
|
||||||
|
|
||||||
|
If ``distribute(enable))'' is specified and the loop has memory dependencies
|
||||||
|
that inhibit vectorization, the compiler will attempt to isolate the offending
|
||||||
|
operations into a new loop. This optimization is not enabled by default, only
|
||||||
|
loops marked with the pragma are considered.
|
||||||
|
|
||||||
|
.. code-block:: c++
|
||||||
|
|
||||||
|
#pragma clang loop distribute(enable)
|
||||||
|
for (i = 0; i < N; ++i) {
|
||||||
|
S1: A[i + 1] = A[i] + B[i];
|
||||||
|
S2: C[i] = D[i] * E[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
This loop will be split into two loops between statements S1 and S2. The
|
||||||
|
second loop containing S2 will be vectorized.
|
||||||
|
|
||||||
|
Loop Distribution is currently not enabled by default in the optimizer because
|
||||||
|
it can hurt performance in some cases. For example, instruction-level
|
||||||
|
parallelism could be reduced by sequentializing the execution of the
|
||||||
|
statements S1 and S2 above.
|
||||||
|
|
||||||
|
If Loop Distribution is turned on globally with
|
||||||
|
``-mllvm -enable-loop-distribution``, specifying ``distribute(disable)`` can
|
||||||
|
be used the disable it on a per-loop basis.
|
||||||
|
|
||||||
Additional Information
|
Additional Information
|
||||||
----------------------
|
----------------------
|
||||||
|
|
||||||
|
|
|
@ -2186,6 +2186,7 @@ def LoopHint : Attr {
|
||||||
/// interleave_count: interleaves 'Value' loop interations.
|
/// interleave_count: interleaves 'Value' loop interations.
|
||||||
/// unroll: fully unroll loop if State == Enable.
|
/// unroll: fully unroll loop if State == Enable.
|
||||||
/// unroll_count: unrolls loop 'Value' times.
|
/// unroll_count: unrolls loop 'Value' times.
|
||||||
|
/// distribute: attempt to distribute loop if State == Enable
|
||||||
|
|
||||||
/// #pragma unroll <argument> directive
|
/// #pragma unroll <argument> directive
|
||||||
/// <no arg>: fully unrolls loop.
|
/// <no arg>: fully unrolls loop.
|
||||||
|
@ -2198,9 +2199,9 @@ def LoopHint : Attr {
|
||||||
/// State of the loop optimization specified by the spelling.
|
/// State of the loop optimization specified by the spelling.
|
||||||
let Args = [EnumArgument<"Option", "OptionType",
|
let Args = [EnumArgument<"Option", "OptionType",
|
||||||
["vectorize", "vectorize_width", "interleave", "interleave_count",
|
["vectorize", "vectorize_width", "interleave", "interleave_count",
|
||||||
"unroll", "unroll_count"],
|
"unroll", "unroll_count", "distribute"],
|
||||||
["Vectorize", "VectorizeWidth", "Interleave", "InterleaveCount",
|
["Vectorize", "VectorizeWidth", "Interleave", "InterleaveCount",
|
||||||
"Unroll", "UnrollCount"]>,
|
"Unroll", "UnrollCount", "Distribute"]>,
|
||||||
EnumArgument<"State", "LoopHintState",
|
EnumArgument<"State", "LoopHintState",
|
||||||
["enable", "disable", "numeric", "assume_safety", "full"],
|
["enable", "disable", "numeric", "assume_safety", "full"],
|
||||||
["Enable", "Disable", "Numeric", "AssumeSafety", "Full"]>,
|
["Enable", "Disable", "Numeric", "AssumeSafety", "Full"]>,
|
||||||
|
@ -2215,6 +2216,7 @@ def LoopHint : Attr {
|
||||||
case InterleaveCount: return "interleave_count";
|
case InterleaveCount: return "interleave_count";
|
||||||
case Unroll: return "unroll";
|
case Unroll: return "unroll";
|
||||||
case UnrollCount: return "unroll_count";
|
case UnrollCount: return "unroll_count";
|
||||||
|
case Distribute: return "distribute";
|
||||||
}
|
}
|
||||||
llvm_unreachable("Unhandled LoopHint option.");
|
llvm_unreachable("Unhandled LoopHint option.");
|
||||||
}
|
}
|
||||||
|
|
|
@ -977,12 +977,12 @@ def err_omp_declare_target_unexpected_clause: Error<
|
||||||
// Pragma loop support.
|
// Pragma loop support.
|
||||||
def err_pragma_loop_missing_argument : Error<
|
def err_pragma_loop_missing_argument : Error<
|
||||||
"missing argument; expected %select{an integer value|"
|
"missing argument; expected %select{an integer value|"
|
||||||
"'enable', %select{'assume_safety'|'full'}1 or 'disable'}0">;
|
"'enable'%select{|, 'full'}1%select{|, 'assume_safety'}2 or 'disable'}0">;
|
||||||
def err_pragma_loop_invalid_option : Error<
|
def err_pragma_loop_invalid_option : Error<
|
||||||
"%select{invalid|missing}0 option%select{ %1|}0; expected vectorize, "
|
"%select{invalid|missing}0 option%select{ %1|}0; expected vectorize, "
|
||||||
"vectorize_width, interleave, interleave_count, unroll, or unroll_count">;
|
"vectorize_width, interleave, interleave_count, unroll, unroll_count, or distribute">;
|
||||||
def err_pragma_invalid_keyword : Error<
|
def err_pragma_invalid_keyword : Error<
|
||||||
"invalid argument; expected 'enable', %select{'assume_safety'|'full'}0 or 'disable'">;
|
"invalid argument; expected 'enable'%select{|, 'full'}0%select{|, 'assume_safety'}1 or 'disable'">;
|
||||||
|
|
||||||
// Pragma unroll support.
|
// Pragma unroll support.
|
||||||
def warn_pragma_unroll_cuda_value_in_parens : Warning<
|
def warn_pragma_unroll_cuda_value_in_parens : Warning<
|
||||||
|
|
|
@ -26,6 +26,7 @@ static MDNode *createMetadata(LLVMContext &Ctx, const LoopAttributes &Attrs,
|
||||||
Attrs.InterleaveCount == 0 && Attrs.UnrollCount == 0 &&
|
Attrs.InterleaveCount == 0 && Attrs.UnrollCount == 0 &&
|
||||||
Attrs.VectorizeEnable == LoopAttributes::Unspecified &&
|
Attrs.VectorizeEnable == LoopAttributes::Unspecified &&
|
||||||
Attrs.UnrollEnable == LoopAttributes::Unspecified &&
|
Attrs.UnrollEnable == LoopAttributes::Unspecified &&
|
||||||
|
Attrs.DistributeEnable == LoopAttributes::Unspecified &&
|
||||||
!Location)
|
!Location)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
|
@ -84,6 +85,14 @@ static MDNode *createMetadata(LLVMContext &Ctx, const LoopAttributes &Attrs,
|
||||||
Args.push_back(MDNode::get(Ctx, Vals));
|
Args.push_back(MDNode::get(Ctx, Vals));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Attrs.DistributeEnable != LoopAttributes::Unspecified) {
|
||||||
|
Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.distribute.enable"),
|
||||||
|
ConstantAsMetadata::get(ConstantInt::get(
|
||||||
|
Type::getInt1Ty(Ctx), (Attrs.DistributeEnable ==
|
||||||
|
LoopAttributes::Enable)))};
|
||||||
|
Args.push_back(MDNode::get(Ctx, Vals));
|
||||||
|
}
|
||||||
|
|
||||||
// Set the first operand to itself.
|
// Set the first operand to itself.
|
||||||
MDNode *LoopID = MDNode::get(Ctx, Args);
|
MDNode *LoopID = MDNode::get(Ctx, Args);
|
||||||
LoopID->replaceOperandWith(0, LoopID);
|
LoopID->replaceOperandWith(0, LoopID);
|
||||||
|
@ -93,7 +102,8 @@ static MDNode *createMetadata(LLVMContext &Ctx, const LoopAttributes &Attrs,
|
||||||
LoopAttributes::LoopAttributes(bool IsParallel)
|
LoopAttributes::LoopAttributes(bool IsParallel)
|
||||||
: IsParallel(IsParallel), VectorizeEnable(LoopAttributes::Unspecified),
|
: IsParallel(IsParallel), VectorizeEnable(LoopAttributes::Unspecified),
|
||||||
UnrollEnable(LoopAttributes::Unspecified), VectorizeWidth(0),
|
UnrollEnable(LoopAttributes::Unspecified), VectorizeWidth(0),
|
||||||
InterleaveCount(0), UnrollCount(0) {}
|
InterleaveCount(0), UnrollCount(0),
|
||||||
|
DistributeEnable(LoopAttributes::Unspecified) {}
|
||||||
|
|
||||||
void LoopAttributes::clear() {
|
void LoopAttributes::clear() {
|
||||||
IsParallel = false;
|
IsParallel = false;
|
||||||
|
@ -172,6 +182,9 @@ void LoopInfoStack::push(BasicBlock *Header, clang::ASTContext &Ctx,
|
||||||
case LoopHintAttr::Unroll:
|
case LoopHintAttr::Unroll:
|
||||||
setUnrollState(LoopAttributes::Disable);
|
setUnrollState(LoopAttributes::Disable);
|
||||||
break;
|
break;
|
||||||
|
case LoopHintAttr::Distribute:
|
||||||
|
setDistributeState(false);
|
||||||
|
break;
|
||||||
case LoopHintAttr::UnrollCount:
|
case LoopHintAttr::UnrollCount:
|
||||||
case LoopHintAttr::VectorizeWidth:
|
case LoopHintAttr::VectorizeWidth:
|
||||||
case LoopHintAttr::InterleaveCount:
|
case LoopHintAttr::InterleaveCount:
|
||||||
|
@ -188,6 +201,9 @@ void LoopInfoStack::push(BasicBlock *Header, clang::ASTContext &Ctx,
|
||||||
case LoopHintAttr::Unroll:
|
case LoopHintAttr::Unroll:
|
||||||
setUnrollState(LoopAttributes::Enable);
|
setUnrollState(LoopAttributes::Enable);
|
||||||
break;
|
break;
|
||||||
|
case LoopHintAttr::Distribute:
|
||||||
|
setDistributeState(true);
|
||||||
|
break;
|
||||||
case LoopHintAttr::UnrollCount:
|
case LoopHintAttr::UnrollCount:
|
||||||
case LoopHintAttr::VectorizeWidth:
|
case LoopHintAttr::VectorizeWidth:
|
||||||
case LoopHintAttr::InterleaveCount:
|
case LoopHintAttr::InterleaveCount:
|
||||||
|
@ -207,6 +223,7 @@ void LoopInfoStack::push(BasicBlock *Header, clang::ASTContext &Ctx,
|
||||||
case LoopHintAttr::UnrollCount:
|
case LoopHintAttr::UnrollCount:
|
||||||
case LoopHintAttr::VectorizeWidth:
|
case LoopHintAttr::VectorizeWidth:
|
||||||
case LoopHintAttr::InterleaveCount:
|
case LoopHintAttr::InterleaveCount:
|
||||||
|
case LoopHintAttr::Distribute:
|
||||||
llvm_unreachable("Options cannot be used to assume mem safety.");
|
llvm_unreachable("Options cannot be used to assume mem safety.");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -221,6 +238,7 @@ void LoopInfoStack::push(BasicBlock *Header, clang::ASTContext &Ctx,
|
||||||
case LoopHintAttr::UnrollCount:
|
case LoopHintAttr::UnrollCount:
|
||||||
case LoopHintAttr::VectorizeWidth:
|
case LoopHintAttr::VectorizeWidth:
|
||||||
case LoopHintAttr::InterleaveCount:
|
case LoopHintAttr::InterleaveCount:
|
||||||
|
case LoopHintAttr::Distribute:
|
||||||
llvm_unreachable("Options cannot be used with 'full' hint.");
|
llvm_unreachable("Options cannot be used with 'full' hint.");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -239,6 +257,7 @@ void LoopInfoStack::push(BasicBlock *Header, clang::ASTContext &Ctx,
|
||||||
case LoopHintAttr::Unroll:
|
case LoopHintAttr::Unroll:
|
||||||
case LoopHintAttr::Vectorize:
|
case LoopHintAttr::Vectorize:
|
||||||
case LoopHintAttr::Interleave:
|
case LoopHintAttr::Interleave:
|
||||||
|
case LoopHintAttr::Distribute:
|
||||||
llvm_unreachable("Options cannot be assigned a value.");
|
llvm_unreachable("Options cannot be assigned a value.");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,6 +58,9 @@ struct LoopAttributes {
|
||||||
|
|
||||||
/// \brief llvm.unroll.
|
/// \brief llvm.unroll.
|
||||||
unsigned UnrollCount;
|
unsigned UnrollCount;
|
||||||
|
|
||||||
|
/// \brief Value for llvm.loop.distribute.enable metadata.
|
||||||
|
LVEnableState DistributeEnable;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// \brief Information used when generating a structured loop.
|
/// \brief Information used when generating a structured loop.
|
||||||
|
@ -130,6 +133,12 @@ public:
|
||||||
Enable ? LoopAttributes::Enable : LoopAttributes::Disable;
|
Enable ? LoopAttributes::Enable : LoopAttributes::Disable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// \brief Set the next pushed loop as a distribution candidate.
|
||||||
|
void setDistributeState(bool Enable = true) {
|
||||||
|
StagedAttrs.DistributeEnable =
|
||||||
|
Enable ? LoopAttributes::Enable : LoopAttributes::Disable;
|
||||||
|
}
|
||||||
|
|
||||||
/// \brief Set the next pushed loop unroll state.
|
/// \brief Set the next pushed loop unroll state.
|
||||||
void setUnrollState(const LoopAttributes::LVEnableState &State) {
|
void setUnrollState(const LoopAttributes::LVEnableState &State) {
|
||||||
StagedAttrs.UnrollEnable = State;
|
StagedAttrs.UnrollEnable = State;
|
||||||
|
|
|
@ -826,20 +826,25 @@ bool Parser::HandlePragmaLoopHint(LoopHint &Hint) {
|
||||||
|
|
||||||
// If no option is specified the argument is assumed to be a constant expr.
|
// If no option is specified the argument is assumed to be a constant expr.
|
||||||
bool OptionUnroll = false;
|
bool OptionUnroll = false;
|
||||||
|
bool OptionDistribute = false;
|
||||||
bool StateOption = false;
|
bool StateOption = false;
|
||||||
if (OptionInfo) { // Pragma Unroll does not specify an option.
|
if (OptionInfo) { // Pragma Unroll does not specify an option.
|
||||||
OptionUnroll = OptionInfo->isStr("unroll");
|
OptionUnroll = OptionInfo->isStr("unroll");
|
||||||
|
OptionDistribute = OptionInfo->isStr("distribute");
|
||||||
StateOption = llvm::StringSwitch<bool>(OptionInfo->getName())
|
StateOption = llvm::StringSwitch<bool>(OptionInfo->getName())
|
||||||
.Case("vectorize", true)
|
.Case("vectorize", true)
|
||||||
.Case("interleave", true)
|
.Case("interleave", true)
|
||||||
.Default(false) || OptionUnroll;
|
.Default(false) ||
|
||||||
|
OptionUnroll || OptionDistribute;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool AssumeSafetyArg = !OptionUnroll && !OptionDistribute;
|
||||||
// Verify loop hint has an argument.
|
// Verify loop hint has an argument.
|
||||||
if (Toks[0].is(tok::eof)) {
|
if (Toks[0].is(tok::eof)) {
|
||||||
ConsumeToken(); // The annotation token.
|
ConsumeToken(); // The annotation token.
|
||||||
Diag(Toks[0].getLocation(), diag::err_pragma_loop_missing_argument)
|
Diag(Toks[0].getLocation(), diag::err_pragma_loop_missing_argument)
|
||||||
<< /*StateArgument=*/StateOption << /*FullKeyword=*/OptionUnroll;
|
<< /*StateArgument=*/StateOption << /*FullKeyword=*/OptionUnroll
|
||||||
|
<< /*AssumeSafetyKeyword=*/AssumeSafetyArg;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -853,11 +858,12 @@ bool Parser::HandlePragmaLoopHint(LoopHint &Hint) {
|
||||||
llvm::StringSwitch<bool>(StateInfo->getName())
|
llvm::StringSwitch<bool>(StateInfo->getName())
|
||||||
.Cases("enable", "disable", true)
|
.Cases("enable", "disable", true)
|
||||||
.Case("full", OptionUnroll)
|
.Case("full", OptionUnroll)
|
||||||
.Case("assume_safety", !OptionUnroll)
|
.Case("assume_safety", AssumeSafetyArg)
|
||||||
.Default(false);
|
.Default(false);
|
||||||
if (!Valid) {
|
if (!Valid) {
|
||||||
Diag(Toks[0].getLocation(), diag::err_pragma_invalid_keyword)
|
Diag(Toks[0].getLocation(), diag::err_pragma_invalid_keyword)
|
||||||
<< /*FullKeyword=*/OptionUnroll;
|
<< /*FullKeyword=*/OptionUnroll
|
||||||
|
<< /*AssumeSafetyKeyword=*/AssumeSafetyArg;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (Toks.size() > 2)
|
if (Toks.size() > 2)
|
||||||
|
@ -2005,6 +2011,7 @@ void PragmaLoopHintHandler::HandlePragma(Preprocessor &PP,
|
||||||
.Case("vectorize", true)
|
.Case("vectorize", true)
|
||||||
.Case("interleave", true)
|
.Case("interleave", true)
|
||||||
.Case("unroll", true)
|
.Case("unroll", true)
|
||||||
|
.Case("distribute", true)
|
||||||
.Case("vectorize_width", true)
|
.Case("vectorize_width", true)
|
||||||
.Case("interleave_count", true)
|
.Case("interleave_count", true)
|
||||||
.Case("unroll_count", true)
|
.Case("unroll_count", true)
|
||||||
|
|
|
@ -107,6 +107,7 @@ static Attr *handleLoopHintAttr(Sema &S, Stmt *St, const AttributeList &A,
|
||||||
.Case("interleave_count", LoopHintAttr::InterleaveCount)
|
.Case("interleave_count", LoopHintAttr::InterleaveCount)
|
||||||
.Case("unroll", LoopHintAttr::Unroll)
|
.Case("unroll", LoopHintAttr::Unroll)
|
||||||
.Case("unroll_count", LoopHintAttr::UnrollCount)
|
.Case("unroll_count", LoopHintAttr::UnrollCount)
|
||||||
|
.Case("distribute", LoopHintAttr::Distribute)
|
||||||
.Default(LoopHintAttr::Vectorize);
|
.Default(LoopHintAttr::Vectorize);
|
||||||
if (Option == LoopHintAttr::VectorizeWidth ||
|
if (Option == LoopHintAttr::VectorizeWidth ||
|
||||||
Option == LoopHintAttr::InterleaveCount ||
|
Option == LoopHintAttr::InterleaveCount ||
|
||||||
|
@ -117,7 +118,8 @@ static Attr *handleLoopHintAttr(Sema &S, Stmt *St, const AttributeList &A,
|
||||||
State = LoopHintAttr::Numeric;
|
State = LoopHintAttr::Numeric;
|
||||||
} else if (Option == LoopHintAttr::Vectorize ||
|
} else if (Option == LoopHintAttr::Vectorize ||
|
||||||
Option == LoopHintAttr::Interleave ||
|
Option == LoopHintAttr::Interleave ||
|
||||||
Option == LoopHintAttr::Unroll) {
|
Option == LoopHintAttr::Unroll ||
|
||||||
|
Option == LoopHintAttr::Distribute) {
|
||||||
assert(StateLoc && StateLoc->Ident && "Loop hint must have an argument");
|
assert(StateLoc && StateLoc->Ident && "Loop hint must have an argument");
|
||||||
if (StateLoc->Ident->isStr("disable"))
|
if (StateLoc->Ident->isStr("disable"))
|
||||||
State = LoopHintAttr::Disable;
|
State = LoopHintAttr::Disable;
|
||||||
|
@ -140,18 +142,21 @@ static Attr *handleLoopHintAttr(Sema &S, Stmt *St, const AttributeList &A,
|
||||||
static void
|
static void
|
||||||
CheckForIncompatibleAttributes(Sema &S,
|
CheckForIncompatibleAttributes(Sema &S,
|
||||||
const SmallVectorImpl<const Attr *> &Attrs) {
|
const SmallVectorImpl<const Attr *> &Attrs) {
|
||||||
// There are 3 categories of loop hints attributes: vectorize, interleave,
|
// There are 4 categories of loop hints attributes: vectorize, interleave,
|
||||||
// and unroll. Each comes in two variants: a state form and a numeric form.
|
// unroll and distribute. Except for distribute they come in two variants: a
|
||||||
// The state form selectively defaults/enables/disables the transformation
|
// state form and a numeric form. The state form selectively
|
||||||
// for the loop (for unroll, default indicates full unrolling rather than
|
// defaults/enables/disables the transformation for the loop (for unroll,
|
||||||
// enabling the transformation). The numeric form form provides an integer
|
// default indicates full unrolling rather than enabling the transformation).
|
||||||
// hint (for example, unroll count) to the transformer. The following array
|
// The numeric form form provides an integer hint (for example, unroll count)
|
||||||
// accumulates the hints encountered while iterating through the attributes
|
// to the transformer. The following array accumulates the hints encountered
|
||||||
// to check for compatibility.
|
// while iterating through the attributes to check for compatibility.
|
||||||
struct {
|
struct {
|
||||||
const LoopHintAttr *StateAttr;
|
const LoopHintAttr *StateAttr;
|
||||||
const LoopHintAttr *NumericAttr;
|
const LoopHintAttr *NumericAttr;
|
||||||
} HintAttrs[] = {{nullptr, nullptr}, {nullptr, nullptr}, {nullptr, nullptr}};
|
} HintAttrs[] = {{nullptr, nullptr},
|
||||||
|
{nullptr, nullptr},
|
||||||
|
{nullptr, nullptr},
|
||||||
|
{nullptr, nullptr}};
|
||||||
|
|
||||||
for (const auto *I : Attrs) {
|
for (const auto *I : Attrs) {
|
||||||
const LoopHintAttr *LH = dyn_cast<LoopHintAttr>(I);
|
const LoopHintAttr *LH = dyn_cast<LoopHintAttr>(I);
|
||||||
|
@ -161,7 +166,7 @@ CheckForIncompatibleAttributes(Sema &S,
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
LoopHintAttr::OptionType Option = LH->getOption();
|
LoopHintAttr::OptionType Option = LH->getOption();
|
||||||
enum { Vectorize, Interleave, Unroll } Category;
|
enum { Vectorize, Interleave, Unroll, Distribute } Category;
|
||||||
switch (Option) {
|
switch (Option) {
|
||||||
case LoopHintAttr::Vectorize:
|
case LoopHintAttr::Vectorize:
|
||||||
case LoopHintAttr::VectorizeWidth:
|
case LoopHintAttr::VectorizeWidth:
|
||||||
|
@ -175,12 +180,17 @@ CheckForIncompatibleAttributes(Sema &S,
|
||||||
case LoopHintAttr::UnrollCount:
|
case LoopHintAttr::UnrollCount:
|
||||||
Category = Unroll;
|
Category = Unroll;
|
||||||
break;
|
break;
|
||||||
|
case LoopHintAttr::Distribute:
|
||||||
|
// Perform the check for duplicated 'distribute' hints.
|
||||||
|
Category = Distribute;
|
||||||
|
break;
|
||||||
};
|
};
|
||||||
|
|
||||||
auto &CategoryState = HintAttrs[Category];
|
auto &CategoryState = HintAttrs[Category];
|
||||||
const LoopHintAttr *PrevAttr;
|
const LoopHintAttr *PrevAttr;
|
||||||
if (Option == LoopHintAttr::Vectorize ||
|
if (Option == LoopHintAttr::Vectorize ||
|
||||||
Option == LoopHintAttr::Interleave || Option == LoopHintAttr::Unroll) {
|
Option == LoopHintAttr::Interleave || Option == LoopHintAttr::Unroll ||
|
||||||
|
Option == LoopHintAttr::Distribute) {
|
||||||
// Enable|Disable|AssumeSafety hint. For example, vectorize(enable).
|
// Enable|Disable|AssumeSafety hint. For example, vectorize(enable).
|
||||||
PrevAttr = CategoryState.StateAttr;
|
PrevAttr = CategoryState.StateAttr;
|
||||||
CategoryState.StateAttr = LH;
|
CategoryState.StateAttr = LH;
|
||||||
|
|
|
@ -9,6 +9,7 @@ void while_test(int *List, int Length) {
|
||||||
#pragma clang loop interleave_count(4)
|
#pragma clang loop interleave_count(4)
|
||||||
#pragma clang loop vectorize_width(4)
|
#pragma clang loop vectorize_width(4)
|
||||||
#pragma clang loop unroll(full)
|
#pragma clang loop unroll(full)
|
||||||
|
#pragma clang loop distribute(enable)
|
||||||
while (i < Length) {
|
while (i < Length) {
|
||||||
// CHECK: br label {{.*}}, !llvm.loop ![[LOOP_1:.*]]
|
// CHECK: br label {{.*}}, !llvm.loop ![[LOOP_1:.*]]
|
||||||
List[i] = i * 2;
|
List[i] = i * 2;
|
||||||
|
@ -20,7 +21,7 @@ void while_test(int *List, int Length) {
|
||||||
void do_test(int *List, int Length) {
|
void do_test(int *List, int Length) {
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
#pragma clang loop vectorize_width(8) interleave_count(4) unroll(disable)
|
#pragma clang loop vectorize_width(8) interleave_count(4) unroll(disable) distribute(disable)
|
||||||
do {
|
do {
|
||||||
// CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !llvm.loop ![[LOOP_2:.*]]
|
// CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !llvm.loop ![[LOOP_2:.*]]
|
||||||
List[i] = i * 2;
|
List[i] = i * 2;
|
||||||
|
@ -55,7 +56,7 @@ void for_range_test() {
|
||||||
|
|
||||||
// Verify disable pragma clang loop directive generates correct metadata
|
// Verify disable pragma clang loop directive generates correct metadata
|
||||||
void disable_test(int *List, int Length) {
|
void disable_test(int *List, int Length) {
|
||||||
#pragma clang loop vectorize(disable) unroll(disable)
|
#pragma clang loop vectorize(disable) unroll(disable) distribute(disable)
|
||||||
for (int i = 0; i < Length; i++) {
|
for (int i = 0; i < Length; i++) {
|
||||||
// CHECK: br label {{.*}}, !llvm.loop ![[LOOP_5:.*]]
|
// CHECK: br label {{.*}}, !llvm.loop ![[LOOP_5:.*]]
|
||||||
List[i] = i * 2;
|
List[i] = i * 2;
|
||||||
|
@ -157,20 +158,22 @@ void template_test(double *List, int Length) {
|
||||||
for_template_constant_expression_test<double, 2, 4, 8>(List, Length);
|
for_template_constant_expression_test<double, 2, 4, 8>(List, Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
// CHECK: ![[LOOP_1]] = distinct !{![[LOOP_1]], ![[WIDTH_4:.*]], ![[INTERLEAVE_4:.*]], ![[INTENABLE_1:.*]], ![[UNROLL_FULL:.*]]}
|
// CHECK: ![[LOOP_1]] = distinct !{![[LOOP_1]], ![[WIDTH_4:.*]], ![[INTERLEAVE_4:.*]], ![[INTENABLE_1:.*]], ![[UNROLL_FULL:.*]], ![[DISTRIBUTE_ENABLE:.*]]}
|
||||||
// CHECK: ![[WIDTH_4]] = !{!"llvm.loop.vectorize.width", i32 4}
|
// CHECK: ![[WIDTH_4]] = !{!"llvm.loop.vectorize.width", i32 4}
|
||||||
// CHECK: ![[INTERLEAVE_4]] = !{!"llvm.loop.interleave.count", i32 4}
|
// CHECK: ![[INTERLEAVE_4]] = !{!"llvm.loop.interleave.count", i32 4}
|
||||||
// CHECK: ![[INTENABLE_1]] = !{!"llvm.loop.vectorize.enable", i1 true}
|
// CHECK: ![[INTENABLE_1]] = !{!"llvm.loop.vectorize.enable", i1 true}
|
||||||
// CHECK: ![[UNROLL_FULL]] = !{!"llvm.loop.unroll.full"}
|
// CHECK: ![[UNROLL_FULL]] = !{!"llvm.loop.unroll.full"}
|
||||||
// CHECK: ![[LOOP_2]] = distinct !{![[LOOP_2:.*]], ![[WIDTH_8:.*]], ![[INTERLEAVE_4:.*]], ![[UNROLL_DISABLE:.*]]}
|
// CHECK: ![[DISTRIBUTE_ENABLE]] = !{!"llvm.loop.distribute.enable", i1 true}
|
||||||
|
// CHECK: ![[LOOP_2]] = distinct !{![[LOOP_2:.*]], ![[WIDTH_8:.*]], ![[INTERLEAVE_4:.*]], ![[UNROLL_DISABLE:.*]], ![[DISTRIBUTE_DISABLE:.*]]}
|
||||||
// CHECK: ![[WIDTH_8]] = !{!"llvm.loop.vectorize.width", i32 8}
|
// CHECK: ![[WIDTH_8]] = !{!"llvm.loop.vectorize.width", i32 8}
|
||||||
// CHECK: ![[UNROLL_DISABLE]] = !{!"llvm.loop.unroll.disable"}
|
// CHECK: ![[UNROLL_DISABLE]] = !{!"llvm.loop.unroll.disable"}
|
||||||
|
// CHECK: ![[DISTRIBUTE_DISABLE]] = !{!"llvm.loop.distribute.enable", i1 false}
|
||||||
// CHECK: ![[LOOP_3]] = distinct !{![[LOOP_3]], ![[INTERLEAVE_4:.*]], ![[UNROLL_8:.*]], ![[INTENABLE_1:.*]]}
|
// CHECK: ![[LOOP_3]] = distinct !{![[LOOP_3]], ![[INTERLEAVE_4:.*]], ![[UNROLL_8:.*]], ![[INTENABLE_1:.*]]}
|
||||||
// CHECK: ![[UNROLL_8]] = !{!"llvm.loop.unroll.count", i32 8}
|
// CHECK: ![[UNROLL_8]] = !{!"llvm.loop.unroll.count", i32 8}
|
||||||
// CHECK: ![[LOOP_4]] = distinct !{![[LOOP_4]], ![[WIDTH_2:.*]], ![[INTERLEAVE_2:.*]]}
|
// CHECK: ![[LOOP_4]] = distinct !{![[LOOP_4]], ![[WIDTH_2:.*]], ![[INTERLEAVE_2:.*]]}
|
||||||
// CHECK: ![[WIDTH_2]] = !{!"llvm.loop.vectorize.width", i32 2}
|
// CHECK: ![[WIDTH_2]] = !{!"llvm.loop.vectorize.width", i32 2}
|
||||||
// CHECK: ![[INTERLEAVE_2]] = !{!"llvm.loop.interleave.count", i32 2}
|
// CHECK: ![[INTERLEAVE_2]] = !{!"llvm.loop.interleave.count", i32 2}
|
||||||
// CHECK: ![[LOOP_5]] = distinct !{![[LOOP_5]], ![[WIDTH_1:.*]], ![[UNROLL_DISABLE:.*]]}
|
// CHECK: ![[LOOP_5]] = distinct !{![[LOOP_5]], ![[WIDTH_1:.*]], ![[UNROLL_DISABLE:.*]], ![[DISTRIBUTE_DISABLE:.*]]}
|
||||||
// CHECK: ![[WIDTH_1]] = !{!"llvm.loop.vectorize.width", i32 1}
|
// CHECK: ![[WIDTH_1]] = !{!"llvm.loop.vectorize.width", i32 1}
|
||||||
// CHECK: ![[LOOP_6]] = distinct !{![[LOOP_6]], ![[WIDTH_2:.*]], ![[INTERLEAVE_2:.*]], ![[UNROLL_8:.*]]}
|
// CHECK: ![[LOOP_6]] = distinct !{![[LOOP_6]], ![[WIDTH_2:.*]], ![[INTERLEAVE_2:.*]], ![[UNROLL_8:.*]]}
|
||||||
// CHECK: ![[LOOP_7]] = distinct !{![[LOOP_7]], ![[WIDTH_5:.*]]}
|
// CHECK: ![[LOOP_7]] = distinct !{![[LOOP_7]], ![[WIDTH_5:.*]]}
|
||||||
|
|
|
@ -19,7 +19,9 @@ void test(int *List, int Length) {
|
||||||
|
|
||||||
// CHECK: #pragma clang loop interleave(disable)
|
// CHECK: #pragma clang loop interleave(disable)
|
||||||
// CHECK-NEXT: #pragma clang loop vectorize(enable)
|
// CHECK-NEXT: #pragma clang loop vectorize(enable)
|
||||||
|
// CHECK-NEXT: #pragma clang loop distribute(disable)
|
||||||
|
|
||||||
|
#pragma clang loop distribute(disable)
|
||||||
#pragma clang loop vectorize(enable)
|
#pragma clang loop vectorize(enable)
|
||||||
#pragma clang loop interleave(disable)
|
#pragma clang loop interleave(disable)
|
||||||
// CHECK-NEXT: while (i - 1 < Length)
|
// CHECK-NEXT: while (i - 1 < Length)
|
||||||
|
@ -30,7 +32,9 @@ void test(int *List, int Length) {
|
||||||
|
|
||||||
// CHECK: #pragma clang loop interleave(enable)
|
// CHECK: #pragma clang loop interleave(enable)
|
||||||
// CHECK-NEXT: #pragma clang loop vectorize(disable)
|
// CHECK-NEXT: #pragma clang loop vectorize(disable)
|
||||||
|
// CHECK-NEXT: #pragma clang loop distribute(enable)
|
||||||
|
|
||||||
|
#pragma clang loop distribute(enable)
|
||||||
#pragma clang loop vectorize(disable)
|
#pragma clang loop vectorize(disable)
|
||||||
#pragma clang loop interleave(enable)
|
#pragma clang loop interleave(enable)
|
||||||
// CHECK-NEXT: while (i - 2 < Length)
|
// CHECK-NEXT: while (i - 2 < Length)
|
||||||
|
|
|
@ -7,9 +7,11 @@
|
||||||
// CHECK: #pragma clang loop unroll_count(16)
|
// CHECK: #pragma clang loop unroll_count(16)
|
||||||
// CHECK: #pragma clang loop interleave_count(8)
|
// CHECK: #pragma clang loop interleave_count(8)
|
||||||
// CHECK: #pragma clang loop vectorize_width(4)
|
// CHECK: #pragma clang loop vectorize_width(4)
|
||||||
|
// CHECK: #pragma clang loop distribute(enable)
|
||||||
// CHECK: #pragma clang loop unroll(disable)
|
// CHECK: #pragma clang loop unroll(disable)
|
||||||
// CHECK: #pragma clang loop interleave(disable)
|
// CHECK: #pragma clang loop interleave(disable)
|
||||||
// CHECK: #pragma clang loop vectorize(enable)
|
// CHECK: #pragma clang loop vectorize(enable)
|
||||||
|
// CHECK: #pragma clang loop distribute(disable)
|
||||||
// CHECK: #pragma clang loop unroll(full)
|
// CHECK: #pragma clang loop unroll(full)
|
||||||
// CHECK: #pragma clang loop interleave(enable)
|
// CHECK: #pragma clang loop interleave(enable)
|
||||||
// CHECK: #pragma clang loop vectorize(disable)
|
// CHECK: #pragma clang loop vectorize(disable)
|
||||||
|
@ -40,6 +42,7 @@ public:
|
||||||
#pragma clang loop vectorize(enable)
|
#pragma clang loop vectorize(enable)
|
||||||
#pragma clang loop interleave(disable)
|
#pragma clang loop interleave(disable)
|
||||||
#pragma clang loop unroll(disable)
|
#pragma clang loop unroll(disable)
|
||||||
|
#pragma clang loop distribute(enable)
|
||||||
while (i - 1 < Length) {
|
while (i - 1 < Length) {
|
||||||
List[i] = i;
|
List[i] = i;
|
||||||
i++;
|
i++;
|
||||||
|
@ -51,6 +54,7 @@ public:
|
||||||
#pragma clang loop vectorize(disable)
|
#pragma clang loop vectorize(disable)
|
||||||
#pragma clang loop interleave(enable)
|
#pragma clang loop interleave(enable)
|
||||||
#pragma clang loop unroll(full)
|
#pragma clang loop unroll(full)
|
||||||
|
#pragma clang loop distribute(disable)
|
||||||
while (i - 3 < Length) {
|
while (i - 3 < Length) {
|
||||||
List[i] = i;
|
List[i] = i;
|
||||||
i++;
|
i++;
|
||||||
|
|
|
@ -16,6 +16,7 @@ void test(int *List, int Length) {
|
||||||
/* expected-error {{expected ')'}} */ #pragma clang loop interleave(assume_safety
|
/* expected-error {{expected ')'}} */ #pragma clang loop interleave(assume_safety
|
||||||
|
|
||||||
/* expected-error {{invalid argument; expected 'enable', 'full' or 'disable'}} */ #pragma clang loop unroll(assume_safety)
|
/* expected-error {{invalid argument; expected 'enable', 'full' or 'disable'}} */ #pragma clang loop unroll(assume_safety)
|
||||||
|
/* expected-error {{invalid argument; expected 'enable' or 'disable'}} */ #pragma clang loop distribute(assume_safety)
|
||||||
|
|
||||||
/* expected-error {{invalid argument; expected 'enable', 'assume_safety' or 'disable'}} */ #pragma clang loop vectorize(badidentifier)
|
/* expected-error {{invalid argument; expected 'enable', 'assume_safety' or 'disable'}} */ #pragma clang loop vectorize(badidentifier)
|
||||||
/* expected-error {{invalid argument; expected 'enable', 'assume_safety' or 'disable'}} */ #pragma clang loop interleave(badidentifier)
|
/* expected-error {{invalid argument; expected 'enable', 'assume_safety' or 'disable'}} */ #pragma clang loop interleave(badidentifier)
|
||||||
|
|
|
@ -116,15 +116,27 @@ void test(int *List, int Length) {
|
||||||
VList[j] = List[j];
|
VList[j] = List[j];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#pragma clang loop distribute(enable)
|
||||||
|
for (int j : VList) {
|
||||||
|
VList[j] = List[j];
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma clang loop distribute(disable)
|
||||||
|
for (int j : VList) {
|
||||||
|
VList[j] = List[j];
|
||||||
|
}
|
||||||
|
|
||||||
test_nontype_template_param<4, 8>(List, Length);
|
test_nontype_template_param<4, 8>(List, Length);
|
||||||
|
|
||||||
/* expected-error {{expected '('}} */ #pragma clang loop vectorize
|
/* expected-error {{expected '('}} */ #pragma clang loop vectorize
|
||||||
/* expected-error {{expected '('}} */ #pragma clang loop interleave
|
/* expected-error {{expected '('}} */ #pragma clang loop interleave
|
||||||
/* expected-error {{expected '('}} */ #pragma clang loop unroll
|
/* expected-error {{expected '('}} */ #pragma clang loop unroll
|
||||||
|
/* expected-error {{expected '('}} */ #pragma clang loop distribute
|
||||||
|
|
||||||
/* expected-error {{expected ')'}} */ #pragma clang loop vectorize(enable
|
/* expected-error {{expected ')'}} */ #pragma clang loop vectorize(enable
|
||||||
/* expected-error {{expected ')'}} */ #pragma clang loop interleave(enable
|
/* expected-error {{expected ')'}} */ #pragma clang loop interleave(enable
|
||||||
/* expected-error {{expected ')'}} */ #pragma clang loop unroll(full
|
/* expected-error {{expected ')'}} */ #pragma clang loop unroll(full
|
||||||
|
/* expected-error {{expected ')'}} */ #pragma clang loop distribute(enable
|
||||||
|
|
||||||
/* expected-error {{expected ')'}} */ #pragma clang loop vectorize_width(4
|
/* expected-error {{expected ')'}} */ #pragma clang loop vectorize_width(4
|
||||||
/* expected-error {{expected ')'}} */ #pragma clang loop interleave_count(4
|
/* expected-error {{expected ')'}} */ #pragma clang loop interleave_count(4
|
||||||
|
@ -133,8 +145,9 @@ void test(int *List, int Length) {
|
||||||
/* expected-error {{missing argument; expected 'enable', 'assume_safety' or 'disable'}} */ #pragma clang loop vectorize()
|
/* expected-error {{missing argument; expected 'enable', 'assume_safety' or 'disable'}} */ #pragma clang loop vectorize()
|
||||||
/* expected-error {{missing argument; expected an integer value}} */ #pragma clang loop interleave_count()
|
/* expected-error {{missing argument; expected an integer value}} */ #pragma clang loop interleave_count()
|
||||||
/* expected-error {{missing argument; expected 'enable', 'full' or 'disable'}} */ #pragma clang loop unroll()
|
/* expected-error {{missing argument; expected 'enable', 'full' or 'disable'}} */ #pragma clang loop unroll()
|
||||||
|
/* expected-error {{missing argument; expected 'enable' or 'disable'}} */ #pragma clang loop distribute()
|
||||||
|
|
||||||
/* expected-error {{missing option; expected vectorize, vectorize_width, interleave, interleave_count, unroll, or unroll_count}} */ #pragma clang loop
|
/* expected-error {{missing option; expected vectorize, vectorize_width, interleave, interleave_count, unroll, unroll_count, or distribute}} */ #pragma clang loop
|
||||||
/* expected-error {{invalid option 'badkeyword'}} */ #pragma clang loop badkeyword
|
/* expected-error {{invalid option 'badkeyword'}} */ #pragma clang loop badkeyword
|
||||||
/* expected-error {{invalid option 'badkeyword'}} */ #pragma clang loop badkeyword(enable)
|
/* expected-error {{invalid option 'badkeyword'}} */ #pragma clang loop badkeyword(enable)
|
||||||
/* expected-error {{invalid option 'badkeyword'}} */ #pragma clang loop vectorize(enable) badkeyword(4)
|
/* expected-error {{invalid option 'badkeyword'}} */ #pragma clang loop vectorize(enable) badkeyword(4)
|
||||||
|
@ -187,6 +200,7 @@ const int VV = 4;
|
||||||
/* expected-error {{invalid argument; expected 'enable', 'assume_safety' or 'disable'}} */ #pragma clang loop vectorize(badidentifier)
|
/* expected-error {{invalid argument; expected 'enable', 'assume_safety' or 'disable'}} */ #pragma clang loop vectorize(badidentifier)
|
||||||
/* expected-error {{invalid argument; expected 'enable', 'assume_safety' or 'disable'}} */ #pragma clang loop interleave(badidentifier)
|
/* expected-error {{invalid argument; expected 'enable', 'assume_safety' or 'disable'}} */ #pragma clang loop interleave(badidentifier)
|
||||||
/* expected-error {{invalid argument; expected 'enable', 'full' or 'disable'}} */ #pragma clang loop unroll(badidentifier)
|
/* expected-error {{invalid argument; expected 'enable', 'full' or 'disable'}} */ #pragma clang loop unroll(badidentifier)
|
||||||
|
/* expected-error {{invalid argument; expected 'enable' or 'disable'}} */ #pragma clang loop distribute(badidentifier)
|
||||||
while (i-7 < Length) {
|
while (i-7 < Length) {
|
||||||
List[i] = i;
|
List[i] = i;
|
||||||
}
|
}
|
||||||
|
@ -196,6 +210,7 @@ const int VV = 4;
|
||||||
/* expected-error {{expected ')'}} */ #pragma clang loop vectorize(()
|
/* expected-error {{expected ')'}} */ #pragma clang loop vectorize(()
|
||||||
/* expected-error {{invalid argument; expected 'enable', 'assume_safety' or 'disable'}} */ #pragma clang loop interleave(*)
|
/* expected-error {{invalid argument; expected 'enable', 'assume_safety' or 'disable'}} */ #pragma clang loop interleave(*)
|
||||||
/* expected-error {{invalid argument; expected 'enable', 'full' or 'disable'}} */ #pragma clang loop unroll(=)
|
/* expected-error {{invalid argument; expected 'enable', 'full' or 'disable'}} */ #pragma clang loop unroll(=)
|
||||||
|
/* expected-error {{invalid argument; expected 'enable' or 'disable'}} */ #pragma clang loop distribute(+)
|
||||||
/* expected-error {{type name requires a specifier or qualifier}} expected-error {{expected expression}} */ #pragma clang loop vectorize_width(^)
|
/* expected-error {{type name requires a specifier or qualifier}} expected-error {{expected expression}} */ #pragma clang loop vectorize_width(^)
|
||||||
/* expected-error {{expected expression}} expected-error {{expected expression}} */ #pragma clang loop interleave_count(/)
|
/* expected-error {{expected expression}} expected-error {{expected expression}} */ #pragma clang loop interleave_count(/)
|
||||||
/* expected-error {{expected expression}} expected-error {{expected expression}} */ #pragma clang loop unroll_count(==)
|
/* expected-error {{expected expression}} expected-error {{expected expression}} */ #pragma clang loop unroll_count(==)
|
||||||
|
@ -232,6 +247,8 @@ const int VV = 4;
|
||||||
#pragma clang loop interleave(disable)
|
#pragma clang loop interleave(disable)
|
||||||
/* expected-error {{duplicate directives 'unroll(disable)' and 'unroll(full)'}} */ #pragma clang loop unroll(full)
|
/* expected-error {{duplicate directives 'unroll(disable)' and 'unroll(full)'}} */ #pragma clang loop unroll(full)
|
||||||
#pragma clang loop unroll(disable)
|
#pragma clang loop unroll(disable)
|
||||||
|
/* expected-error {{duplicate directives 'distribute(disable)' and 'distribute(enable)'}} */ #pragma clang loop distribute(enable)
|
||||||
|
#pragma clang loop distribute(disable)
|
||||||
while (i-9 < Length) {
|
while (i-9 < Length) {
|
||||||
List[i] = i;
|
List[i] = i;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue