forked from OSchip/llvm-project
Add loop unroll pragma support
http://reviews.llvm.org/D4089 Patch by Mark Heffernan. llvm-svn: 210667
This commit is contained in:
parent
364a6747aa
commit
86483b3a0c
|
@ -1766,6 +1766,8 @@ def LoopHint : Attr {
|
|||
/// vectorize_width: vectorize loop operations with width 'value'.
|
||||
/// interleave: interleave multiple loop iterations if 'value != 0'.
|
||||
/// interleave_count: interleaves 'value' loop interations.
|
||||
/// unroll: unroll loop if 'value != 0'.
|
||||
/// unroll_count: unrolls loop 'value' times.
|
||||
|
||||
/// FIXME: Add Pragma spelling to tablegen and
|
||||
/// use it here.
|
||||
|
@ -1773,8 +1775,10 @@ def LoopHint : Attr {
|
|||
|
||||
/// State of the loop optimization specified by the spelling.
|
||||
let Args = [EnumArgument<"Option", "OptionType",
|
||||
["vectorize", "vectorize_width", "interleave", "interleave_count"],
|
||||
["Vectorize", "VectorizeWidth", "Interleave", "InterleaveCount"]>,
|
||||
["vectorize", "vectorize_width", "interleave", "interleave_count",
|
||||
"unroll", "unroll_count"],
|
||||
["Vectorize", "VectorizeWidth", "Interleave", "InterleaveCount",
|
||||
"Unroll", "UnrollCount"]>,
|
||||
DefaultIntArgument<"Value", 1>];
|
||||
|
||||
let AdditionalMembers = [{
|
||||
|
@ -1784,6 +1788,8 @@ def LoopHint : Attr {
|
|||
case VectorizeWidth: return "vectorize_width";
|
||||
case Interleave: return "interleave";
|
||||
case InterleaveCount: return "interleave_count";
|
||||
case Unroll: return "unroll";
|
||||
case UnrollCount: return "unroll_count";
|
||||
}
|
||||
llvm_unreachable("Unhandled LoopHint option.");
|
||||
}
|
||||
|
@ -1797,7 +1803,8 @@ def LoopHint : Attr {
|
|||
// FIXME: Modify pretty printer to print this pragma.
|
||||
void print(raw_ostream &OS, const PrintingPolicy &Policy) const {
|
||||
OS << "#pragma clang loop " << getOptionName(option) << "(";
|
||||
if (option == VectorizeWidth || option == InterleaveCount)
|
||||
if (option == VectorizeWidth || option == InterleaveCount ||
|
||||
option == UnrollCount)
|
||||
OS << value;
|
||||
else
|
||||
OS << getValueName(value);
|
||||
|
|
|
@ -895,7 +895,8 @@ def err_omp_more_one_clause : Error<
|
|||
|
||||
// Pragma loop support.
|
||||
def err_pragma_loop_invalid_option : Error<
|
||||
"%select{invalid|missing}0 option%select{ %1|}0; expected vectorize, vectorize_width, interleave, or interleave_count">;
|
||||
"%select{invalid|missing}0 option%select{ %1|}0; expected vectorize, "
|
||||
"vectorize_width, interleave, interleave_count, unroll, or unroll_count">;
|
||||
} // end of Parse Issue category.
|
||||
|
||||
let CategoryName = "Modules Issue" in {
|
||||
|
|
|
@ -550,6 +550,12 @@ void CodeGenFunction::EmitCondBrHints(llvm::LLVMContext &Context,
|
|||
case LoopHintAttr::InterleaveCount:
|
||||
MetadataName = "llvm.vectorizer.unroll";
|
||||
break;
|
||||
case LoopHintAttr::Unroll:
|
||||
MetadataName = "llvm.loopunroll.enable";
|
||||
break;
|
||||
case LoopHintAttr::UnrollCount:
|
||||
MetadataName = "llvm.loopunroll.count";
|
||||
break;
|
||||
}
|
||||
|
||||
llvm::Value *Value;
|
||||
|
@ -572,6 +578,14 @@ void CodeGenFunction::EmitCondBrHints(llvm::LLVMContext &Context,
|
|||
Name = llvm::MDString::get(Context, MetadataName);
|
||||
Value = llvm::ConstantInt::get(Int32Ty, ValueInt);
|
||||
break;
|
||||
case LoopHintAttr::Unroll:
|
||||
Name = llvm::MDString::get(Context, MetadataName);
|
||||
Value = (ValueInt == 0) ? Builder.getFalse() : Builder.getTrue();
|
||||
break;
|
||||
case LoopHintAttr::UnrollCount:
|
||||
Name = llvm::MDString::get(Context, MetadataName);
|
||||
Value = llvm::ConstantInt::get(Int32Ty, ValueInt);
|
||||
break;
|
||||
}
|
||||
|
||||
SmallVector<llvm::Value *, 2> OpValues;
|
||||
|
|
|
@ -1641,8 +1641,10 @@ void PragmaOptimizeHandler::HandlePragma(Preprocessor &PP,
|
|||
/// loop-hint:
|
||||
/// 'vectorize' '(' loop-hint-keyword ')'
|
||||
/// 'interleave' '(' loop-hint-keyword ')'
|
||||
/// 'unroll' '(' loop-hint-keyword ')'
|
||||
/// 'vectorize_width' '(' loop-hint-value ')'
|
||||
/// 'interleave_count' '(' loop-hint-value ')'
|
||||
/// 'unroll_count' '(' loop-hint-value ')'
|
||||
///
|
||||
/// loop-hint-keyword:
|
||||
/// 'enable'
|
||||
|
@ -1661,6 +1663,13 @@ void PragmaOptimizeHandler::HandlePragma(Preprocessor &PP,
|
|||
/// possible and profitable, and 0 is invalid. The loop vectorizer currently
|
||||
/// only works on inner loops.
|
||||
///
|
||||
/// The unroll and unroll_count directives control the concatenation
|
||||
/// unroller. Specifying unroll(enable) instructs llvm to try to
|
||||
/// unroll the loop completely, and unroll(disable) disables unrolling
|
||||
/// for the loop. Specifying unroll_count(_value_) instructs llvm to
|
||||
/// try to unroll the loop the number of times indicated by the value.
|
||||
/// If unroll(enable) and unroll_count are both specified only
|
||||
/// unroll_count takes effect.
|
||||
void PragmaLoopHintHandler::HandlePragma(Preprocessor &PP,
|
||||
PragmaIntroducerKind Introducer,
|
||||
Token &Tok) {
|
||||
|
@ -1679,9 +1688,15 @@ void PragmaLoopHintHandler::HandlePragma(Preprocessor &PP,
|
|||
Token Option = Tok;
|
||||
IdentifierInfo *OptionInfo = Tok.getIdentifierInfo();
|
||||
|
||||
if (!OptionInfo->isStr("vectorize") && !OptionInfo->isStr("interleave") &&
|
||||
!OptionInfo->isStr("vectorize_width") &&
|
||||
!OptionInfo->isStr("interleave_count")) {
|
||||
bool OptionValid = llvm::StringSwitch<bool>(OptionInfo->getName())
|
||||
.Case("vectorize", true)
|
||||
.Case("interleave", true)
|
||||
.Case("unroll", true)
|
||||
.Case("vectorize_width", true)
|
||||
.Case("interleave_count", true)
|
||||
.Case("unroll_count", true)
|
||||
.Default(false);
|
||||
if (!OptionValid) {
|
||||
PP.Diag(Tok.getLocation(), diag::err_pragma_loop_invalid_option)
|
||||
<< /*MissingOption=*/false << OptionInfo;
|
||||
return;
|
||||
|
|
|
@ -67,10 +67,13 @@ static Attr *handleLoopHintAttr(Sema &S, Stmt *St, const AttributeList &A,
|
|||
.Case("vectorize_width", LoopHintAttr::VectorizeWidth)
|
||||
.Case("interleave", LoopHintAttr::Interleave)
|
||||
.Case("interleave_count", LoopHintAttr::InterleaveCount)
|
||||
.Case("unroll", LoopHintAttr::Unroll)
|
||||
.Case("unroll_count", LoopHintAttr::UnrollCount)
|
||||
.Default(LoopHintAttr::Vectorize);
|
||||
|
||||
int ValueInt;
|
||||
if (Option == LoopHintAttr::Vectorize || Option == LoopHintAttr::Interleave) {
|
||||
if (Option == LoopHintAttr::Vectorize || Option == LoopHintAttr::Interleave ||
|
||||
Option == LoopHintAttr::Unroll) {
|
||||
if (!ValueInfo) {
|
||||
S.Diag(ValueLoc->Loc, diag::err_pragma_loop_invalid_keyword)
|
||||
<< /*MissingKeyword=*/true << "";
|
||||
|
@ -87,7 +90,8 @@ static Attr *handleLoopHintAttr(Sema &S, Stmt *St, const AttributeList &A,
|
|||
return nullptr;
|
||||
}
|
||||
} else if (Option == LoopHintAttr::VectorizeWidth ||
|
||||
Option == LoopHintAttr::InterleaveCount) {
|
||||
Option == LoopHintAttr::InterleaveCount ||
|
||||
Option == LoopHintAttr::UnrollCount) {
|
||||
// FIXME: We should support template parameters for the loop hint value.
|
||||
// See bug report #19610.
|
||||
llvm::APSInt ValueAPS;
|
||||
|
@ -111,9 +115,24 @@ static Attr *handleLoopHintAttr(Sema &S, Stmt *St, const AttributeList &A,
|
|||
|
||||
static void
|
||||
CheckForIncompatibleAttributes(Sema &S, SmallVectorImpl<const Attr *> &Attrs) {
|
||||
int PrevOptionValue[4] = {-1, -1, -1, -1};
|
||||
int OptionId[4] = {LoopHintAttr::Vectorize, LoopHintAttr::VectorizeWidth,
|
||||
LoopHintAttr::Interleave, LoopHintAttr::InterleaveCount};
|
||||
// There are 3 categories of loop hints: vectorize, interleave, and
|
||||
// unroll. Each comes in two variants: an enable/disable form and a
|
||||
// form which takes a numeric argument. For example:
|
||||
// unroll(enable|disable) and unroll_count(N). The following array
|
||||
// accumulate the hints encountered while iterating through the
|
||||
// attributes to check for compatibility.
|
||||
struct {
|
||||
int EnableOptionId;
|
||||
int NumericOptionId;
|
||||
bool EnabledIsSet;
|
||||
bool ValueIsSet;
|
||||
bool Enabled;
|
||||
int Value;
|
||||
} Options[] = {
|
||||
{LoopHintAttr::Vectorize, LoopHintAttr::VectorizeWidth},
|
||||
{LoopHintAttr::Interleave, LoopHintAttr::InterleaveCount},
|
||||
{LoopHintAttr::Unroll, LoopHintAttr::UnrollCount}
|
||||
};
|
||||
|
||||
for (const auto *I : Attrs) {
|
||||
const LoopHintAttr *LH = dyn_cast<LoopHintAttr>(I);
|
||||
|
@ -122,76 +141,64 @@ CheckForIncompatibleAttributes(Sema &S, SmallVectorImpl<const Attr *> &Attrs) {
|
|||
if (!LH)
|
||||
continue;
|
||||
|
||||
int State, Value;
|
||||
int Option = LH->getOption();
|
||||
int ValueInt = LH->getValue();
|
||||
|
||||
int Category;
|
||||
switch (Option) {
|
||||
case LoopHintAttr::Vectorize:
|
||||
case LoopHintAttr::VectorizeWidth:
|
||||
State = 0;
|
||||
Value = 1;
|
||||
Category = 0;
|
||||
break;
|
||||
case LoopHintAttr::Interleave:
|
||||
case LoopHintAttr::InterleaveCount:
|
||||
State = 2;
|
||||
Value = 3;
|
||||
Category = 1;
|
||||
break;
|
||||
}
|
||||
case LoopHintAttr::Unroll:
|
||||
case LoopHintAttr::UnrollCount:
|
||||
Category = 2;
|
||||
break;
|
||||
};
|
||||
|
||||
auto &CategoryState = Options[Category];
|
||||
SourceLocation ValueLoc = LH->getRange().getEnd();
|
||||
|
||||
// Compatibility testing is split into two cases.
|
||||
// 1. if the current loop hint sets state (enable/disable) - check against
|
||||
// previous state and value.
|
||||
// 2. if the current loop hint sets a value - check against previous state
|
||||
// and value.
|
||||
|
||||
if (Option == State) {
|
||||
if (PrevOptionValue[State] != -1) {
|
||||
// Cannot specify state twice.
|
||||
int PrevValue = PrevOptionValue[State];
|
||||
if (Option == LoopHintAttr::Vectorize ||
|
||||
Option == LoopHintAttr::Interleave || Option == LoopHintAttr::Unroll) {
|
||||
// Enable|disable hint. For example, vectorize(enable).
|
||||
if (CategoryState.EnabledIsSet) {
|
||||
// Cannot specify enable/disable state twice.
|
||||
S.Diag(ValueLoc, diag::err_pragma_loop_compatibility)
|
||||
<< /*Duplicate=*/true << LoopHintAttr::getOptionName(Option)
|
||||
<< LoopHintAttr::getValueName(PrevValue)
|
||||
<< LoopHintAttr::getValueName(CategoryState.Enabled)
|
||||
<< LoopHintAttr::getOptionName(Option)
|
||||
<< LoopHintAttr::getValueName(Value);
|
||||
}
|
||||
|
||||
if (PrevOptionValue[Value] != -1) {
|
||||
// Compare state with previous width/count.
|
||||
int PrevOption = OptionId[Value];
|
||||
int PrevValueInt = PrevOptionValue[Value];
|
||||
if ((ValueInt == 0 && PrevValueInt > 1) ||
|
||||
(ValueInt == 1 && PrevValueInt <= 1))
|
||||
S.Diag(ValueLoc, diag::err_pragma_loop_compatibility)
|
||||
<< /*Duplicate=*/false << LoopHintAttr::getOptionName(PrevOption)
|
||||
<< PrevValueInt << LoopHintAttr::getOptionName(Option)
|
||||
<< LoopHintAttr::getValueName(ValueInt);
|
||||
<< LoopHintAttr::getValueName(ValueInt);
|
||||
}
|
||||
CategoryState.EnabledIsSet = true;
|
||||
CategoryState.Enabled = ValueInt;
|
||||
} else {
|
||||
if (PrevOptionValue[State] != -1) {
|
||||
// Compare width/count value with previous state.
|
||||
int PrevOption = OptionId[State];
|
||||
int PrevValueInt = PrevOptionValue[State];
|
||||
if ((ValueInt > 1 && PrevValueInt == 0) ||
|
||||
(ValueInt <= 1 && PrevValueInt == 1))
|
||||
S.Diag(ValueLoc, diag::err_pragma_loop_compatibility)
|
||||
<< /*Duplicate=*/false << LoopHintAttr::getOptionName(PrevOption)
|
||||
<< LoopHintAttr::getValueName(PrevValueInt)
|
||||
<< LoopHintAttr::getOptionName(Option) << ValueInt;
|
||||
}
|
||||
|
||||
if (PrevOptionValue[Value] != -1) {
|
||||
// Cannot specify a width/count twice.
|
||||
int PrevValueInt = PrevOptionValue[Value];
|
||||
// Numeric hint. For example, unroll_count(8).
|
||||
if (CategoryState.ValueIsSet) {
|
||||
// Cannot specify numeric hint twice.
|
||||
S.Diag(ValueLoc, diag::err_pragma_loop_compatibility)
|
||||
<< /*Duplicate=*/true << LoopHintAttr::getOptionName(Option)
|
||||
<< PrevValueInt << LoopHintAttr::getOptionName(Option) << ValueInt;
|
||||
<< CategoryState.Value << LoopHintAttr::getOptionName(Option)
|
||||
<< ValueInt;
|
||||
}
|
||||
CategoryState.ValueIsSet = true;
|
||||
CategoryState.Value = ValueInt;
|
||||
}
|
||||
|
||||
PrevOptionValue[Option] = ValueInt;
|
||||
if (CategoryState.EnabledIsSet && !CategoryState.Enabled &&
|
||||
CategoryState.ValueIsSet) {
|
||||
// Disable hints are not compatible with numeric hints of the
|
||||
// same category.
|
||||
S.Diag(ValueLoc, diag::err_pragma_loop_compatibility)
|
||||
<< /*Duplicate=*/false
|
||||
<< LoopHintAttr::getOptionName(CategoryState.EnableOptionId)
|
||||
<< LoopHintAttr::getValueName(CategoryState.Enabled)
|
||||
<< LoopHintAttr::getOptionName(CategoryState.NumericOptionId)
|
||||
<< CategoryState.Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ void while_test(int *List, int Length) {
|
|||
#pragma clang loop vectorize(enable)
|
||||
#pragma clang loop interleave_count(4)
|
||||
#pragma clang loop vectorize_width(4)
|
||||
#pragma clang loop unroll(enable)
|
||||
while (i < Length) {
|
||||
// CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !llvm.loop ![[LOOP_1:.*]]
|
||||
List[i] = i * 2;
|
||||
|
@ -19,7 +20,7 @@ void while_test(int *List, int Length) {
|
|||
void do_test(int *List, int Length) {
|
||||
int i = 0;
|
||||
|
||||
#pragma clang loop vectorize_width(8) interleave_count(4)
|
||||
#pragma clang loop vectorize_width(8) interleave_count(4) unroll(disable)
|
||||
do {
|
||||
// CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !llvm.loop ![[LOOP_2:.*]]
|
||||
List[i] = i * 2;
|
||||
|
@ -31,6 +32,7 @@ void do_test(int *List, int Length) {
|
|||
void for_test(int *List, int Length) {
|
||||
#pragma clang loop interleave(enable)
|
||||
#pragma clang loop interleave_count(4)
|
||||
#pragma clang loop unroll_count(8)
|
||||
for (int i = 0; i < Length; i++) {
|
||||
// CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !llvm.loop ![[LOOP_3:.*]]
|
||||
List[i] = i * 2;
|
||||
|
@ -51,7 +53,7 @@ void for_range_test() {
|
|||
|
||||
// Verify disable pragma clang loop directive generates correct metadata
|
||||
void disable_test(int *List, int Length) {
|
||||
#pragma clang loop vectorize(disable)
|
||||
#pragma clang loop vectorize(disable) unroll(disable)
|
||||
for (int i = 0; i < Length; i++) {
|
||||
// CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !llvm.loop ![[LOOP_5:.*]]
|
||||
List[i] = i * 2;
|
||||
|
@ -60,10 +62,12 @@ void disable_test(int *List, int Length) {
|
|||
|
||||
#define VECWIDTH 2
|
||||
#define INTCOUNT 2
|
||||
#define UNROLLCOUNT 8
|
||||
|
||||
// Verify defines are correctly resolved in pragma clang loop directive
|
||||
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:.*]]
|
||||
List[i] = i * Value;
|
||||
|
@ -74,7 +78,7 @@ void for_define_test(int *List, int Length, int Value) {
|
|||
template <typename A>
|
||||
void for_template_test(A *List, int Length, A Value) {
|
||||
|
||||
#pragma clang loop vectorize_width(8) interleave_count(8)
|
||||
#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_7:.*]]
|
||||
List[i] = i * Value;
|
||||
|
@ -85,6 +89,7 @@ void for_template_test(A *List, int Length, A Value) {
|
|||
template <typename A>
|
||||
void for_template_define_test(A *List, int Length, A 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_8:.*]]
|
||||
List[i] = i * Value;
|
||||
|
@ -93,6 +98,7 @@ void for_template_define_test(A *List, int Length, A Value) {
|
|||
|
||||
#undef VECWIDTH
|
||||
#undef INTCOUNT
|
||||
#undef UNROLLCOUNT
|
||||
|
||||
// Use templates defined above. Test verifies metadata is generated correctly.
|
||||
void template_test(double *List, int Length) {
|
||||
|
@ -102,19 +108,22 @@ void template_test(double *List, int Length) {
|
|||
for_template_define_test<double>(List, Length, Value);
|
||||
}
|
||||
|
||||
// CHECK: ![[LOOP_1]] = metadata !{metadata ![[LOOP_1]], metadata ![[WIDTH_4:.*]], metadata ![[UNROLL_4:.*]], metadata ![[ENABLE_1:.*]]}
|
||||
// CHECK: ![[LOOP_1]] = metadata !{metadata ![[LOOP_1]], metadata ![[UNROLLENABLE_1:.*]], metadata ![[WIDTH_4:.*]], metadata ![[INTERLEAVE_4:.*]], metadata ![[INTENABLE_1:.*]]}
|
||||
// CHECK: ![[UNROLLENABLE_1]] = metadata !{metadata !"llvm.loopunroll.enable", i1 true}
|
||||
// CHECK: ![[WIDTH_4]] = metadata !{metadata !"llvm.vectorizer.width", i32 4}
|
||||
// CHECK: ![[UNROLL_4]] = metadata !{metadata !"llvm.vectorizer.unroll", i32 4}
|
||||
// CHECK: ![[ENABLE_1]] = metadata !{metadata !"llvm.vectorizer.enable", i1 true}
|
||||
// CHECK: ![[LOOP_2]] = metadata !{metadata ![[LOOP_2:.*]], metadata ![[UNROLL_4:.*]], metadata ![[WIDTH_8:.*]]}
|
||||
// CHECK: ![[INTERLEAVE_4]] = metadata !{metadata !"llvm.vectorizer.unroll", i32 4}
|
||||
// CHECK: ![[INTENABLE_1]] = metadata !{metadata !"llvm.vectorizer.enable", i1 true}
|
||||
// CHECK: ![[LOOP_2]] = metadata !{metadata ![[LOOP_2:.*]], metadata ![[UNROLLENABLE_0:.*]], metadata ![[INTERLEAVE_4:.*]], metadata ![[WIDTH_8:.*]]}
|
||||
// CHECK: ![[UNROLLENABLE_0]] = metadata !{metadata !"llvm.loopunroll.enable", i1 false}
|
||||
// CHECK: ![[WIDTH_8]] = metadata !{metadata !"llvm.vectorizer.width", i32 8}
|
||||
// CHECK: ![[LOOP_3]] = metadata !{metadata ![[LOOP_3]], metadata ![[UNROLL_4:.*]], metadata ![[ENABLE_1:.*]]}
|
||||
// CHECK: ![[LOOP_4]] = metadata !{metadata ![[LOOP_4]], metadata ![[UNROLL_2:.*]], metadata ![[WIDTH_2:.*]]}
|
||||
// CHECK: ![[UNROLL_2]] = metadata !{metadata !"llvm.vectorizer.unroll", i32 2}
|
||||
// CHECK: ![[LOOP_3]] = metadata !{metadata ![[LOOP_3]], metadata ![[UNROLL_8:.*]], metadata ![[INTERLEAVE_4:.*]], metadata ![[ENABLE_1:.*]]}
|
||||
// CHECK: ![[UNROLL_8]] = metadata !{metadata !"llvm.loopunroll.count", i32 8}
|
||||
// CHECK: ![[LOOP_4]] = metadata !{metadata ![[LOOP_4]], metadata ![[INTERLEAVE_2:.*]], metadata ![[WIDTH_2:.*]]}
|
||||
// CHECK: ![[INTERLEAVE_2]] = metadata !{metadata !"llvm.vectorizer.unroll", i32 2}
|
||||
// CHECK: ![[WIDTH_2]] = metadata !{metadata !"llvm.vectorizer.width", i32 2}
|
||||
// CHECK: ![[LOOP_5]] = metadata !{metadata ![[LOOP_5]], metadata ![[WIDTH_1:.*]]}
|
||||
// CHECK: ![[LOOP_5]] = metadata !{metadata ![[LOOP_5]], metadata ![[UNROLLENABLE_0:.*]], metadata ![[WIDTH_1:.*]]}
|
||||
// CHECK: ![[WIDTH_1]] = metadata !{metadata !"llvm.vectorizer.width", i32 1}
|
||||
// CHECK: ![[LOOP_6]] = metadata !{metadata ![[LOOP_6]], metadata ![[UNROLL_2:.*]], metadata ![[WIDTH_2:.*]]}
|
||||
// CHECK: ![[LOOP_7]] = metadata !{metadata ![[LOOP_7]], metadata ![[UNROLL_8:.*]], metadata ![[WIDTH_8:.*]]}
|
||||
// CHECK: ![[UNROLL_8]] = metadata !{metadata !"llvm.vectorizer.unroll", i32 8}
|
||||
// CHECK: ![[LOOP_8]] = metadata !{metadata ![[LOOP_8]], metadata ![[UNROLL_2:.*]], metadata ![[WIDTH_2:.*]]}
|
||||
// CHECK: ![[LOOP_6]] = metadata !{metadata ![[LOOP_6]], metadata ![[UNROLL_8:.*]], metadata ![[INTERLEAVE_2:.*]], metadata ![[WIDTH_2:.*]]}
|
||||
// CHECK: ![[LOOP_7]] = metadata !{metadata ![[LOOP_7]], metadata ![[UNROLL_8:.*]], metadata ![[INTERLEAVE_8:.*]], metadata ![[WIDTH_8:.*]]}
|
||||
// CHECK: ![[INTERLEAVE_8]] = metadata !{metadata !"llvm.vectorizer.unroll", i32 8}
|
||||
// CHECK: ![[LOOP_8]] = metadata !{metadata ![[LOOP_8]], metadata ![[UNROLL_8:.*]], metadata ![[INTERLEAVE_2:.*]], metadata ![[WIDTH_2:.*]]}
|
||||
|
|
|
@ -4,10 +4,13 @@
|
|||
// FIXME: A bug in ParsedAttributes causes the order of the attributes to be
|
||||
// reversed. The checks are consequently in the reverse order below.
|
||||
|
||||
// CHECK: #pragma clang loop unroll_count(16)
|
||||
// CHECK: #pragma clang loop interleave_count(8)
|
||||
// CHECK: #pragma clang loop vectorize_width(4)
|
||||
// CHECK: #pragma clang loop unroll(disable)
|
||||
// CHECK: #pragma clang loop interleave(disable)
|
||||
// CHECK: #pragma clang loop vectorize(enable)
|
||||
// CHECK: #pragma clang loop unroll(enable)
|
||||
// CHECK: #pragma clang loop interleave(enable)
|
||||
// CHECK: #pragma clang loop vectorize(disable)
|
||||
|
||||
|
@ -20,6 +23,7 @@ public:
|
|||
int i = 0;
|
||||
#pragma clang loop vectorize_width(4)
|
||||
#pragma clang loop interleave_count(8)
|
||||
#pragma clang loop unroll_count(16)
|
||||
while (i < Length) {
|
||||
List[i] = i;
|
||||
i++;
|
||||
|
@ -30,6 +34,7 @@ public:
|
|||
int i = 0;
|
||||
#pragma clang loop vectorize(enable)
|
||||
#pragma clang loop interleave(disable)
|
||||
#pragma clang loop unroll(disable)
|
||||
while (i - 1 < Length) {
|
||||
List[i] = i;
|
||||
i++;
|
||||
|
@ -40,6 +45,7 @@ public:
|
|||
int i = 0;
|
||||
#pragma clang loop vectorize(disable)
|
||||
#pragma clang loop interleave(enable)
|
||||
#pragma clang loop unroll(enable)
|
||||
while (i - 3 < Length) {
|
||||
List[i] = i;
|
||||
i++;
|
||||
|
|
|
@ -8,23 +8,26 @@ void test(int *List, int Length) {
|
|||
|
||||
#pragma clang loop vectorize(enable)
|
||||
#pragma clang loop interleave(enable)
|
||||
#pragma clang loop unroll(enable)
|
||||
while (i + 1 < Length) {
|
||||
List[i] = i;
|
||||
}
|
||||
|
||||
#pragma clang loop vectorize_width(4)
|
||||
#pragma clang loop interleave_count(8)
|
||||
#pragma clang loop unroll_count(16)
|
||||
while (i < Length) {
|
||||
List[i] = i;
|
||||
}
|
||||
|
||||
#pragma clang loop vectorize(disable)
|
||||
#pragma clang loop interleave(disable)
|
||||
#pragma clang loop unroll(disable)
|
||||
while (i - 1 < Length) {
|
||||
List[i] = i;
|
||||
}
|
||||
|
||||
#pragma clang loop vectorize_width(4) interleave_count(8)
|
||||
#pragma clang loop vectorize_width(4) interleave_count(8) unroll_count(16)
|
||||
while (i - 2 < Length) {
|
||||
List[i] = i;
|
||||
}
|
||||
|
@ -35,19 +38,22 @@ void test(int *List, int Length) {
|
|||
}
|
||||
|
||||
int VList[Length];
|
||||
#pragma clang loop vectorize(disable) interleave(disable)
|
||||
#pragma clang loop vectorize(disable) interleave(disable) unroll(disable)
|
||||
for (int j : VList) {
|
||||
VList[j] = List[j];
|
||||
}
|
||||
|
||||
/* expected-error {{expected '('}} */ #pragma clang loop vectorize
|
||||
/* expected-error {{expected '('}} */ #pragma clang loop interleave
|
||||
/* expected-error {{expected '('}} */ #pragma clang loop unroll
|
||||
|
||||
/* expected-error {{expected ')'}} */ #pragma clang loop vectorize(enable
|
||||
/* expected-error {{expected ')'}} */ #pragma clang loop interleave(enable
|
||||
/* expected-error {{expected ')'}} */ #pragma clang loop unroll(enable
|
||||
|
||||
/* expected-error {{expected ')'}} */ #pragma clang loop vectorize_width(4
|
||||
/* expected-error {{expected ')'}} */ #pragma clang loop interleave_count(4
|
||||
/* expected-error {{expected ')'}} */ #pragma clang loop unroll_count(4
|
||||
|
||||
/* expected-error {{missing option}} */ #pragma clang loop
|
||||
/* expected-error {{invalid option 'badkeyword'}} */ #pragma clang loop badkeyword
|
||||
|
@ -61,24 +67,28 @@ void test(int *List, int Length) {
|
|||
|
||||
/* expected-error {{invalid value 0; expected a positive integer value}} */ #pragma clang loop vectorize_width(0)
|
||||
/* expected-error {{invalid value 0; expected a positive integer value}} */ #pragma clang loop interleave_count(0)
|
||||
/* expected-error {{invalid value 0; expected a positive integer value}} */ #pragma clang loop unroll_count(0)
|
||||
while (i-5 < Length) {
|
||||
List[i] = i;
|
||||
}
|
||||
|
||||
/* expected-error {{invalid value -1294967296; expected a positive integer value}} */ #pragma clang loop vectorize_width(3000000000)
|
||||
/* expected-error {{invalid value -1294967296; expected a positive integer value}} */ #pragma clang loop interleave_count(3000000000)
|
||||
/* expected-error {{invalid value -1294967296; expected a positive integer value}} */ #pragma clang loop unroll_count(3000000000)
|
||||
while (i-6 < Length) {
|
||||
List[i] = i;
|
||||
}
|
||||
|
||||
/* expected-error {{missing value; expected a positive integer value}} */ #pragma clang loop vectorize_width(badvalue)
|
||||
/* expected-error {{missing value; expected a positive integer value}} */ #pragma clang loop interleave_count(badvalue)
|
||||
/* expected-error {{missing value; expected a positive integer value}} */ #pragma clang loop unroll_count(badvalue)
|
||||
while (i-6 < Length) {
|
||||
List[i] = i;
|
||||
}
|
||||
|
||||
/* expected-error {{invalid keyword 'badidentifier'; expected 'enable' or 'disable'}} */ #pragma clang loop vectorize(badidentifier)
|
||||
/* expected-error {{invalid keyword 'badidentifier'; expected 'enable' or 'disable'}} */ #pragma clang loop interleave(badidentifier)
|
||||
/* expected-error {{invalid keyword 'badidentifier'; expected 'enable' or 'disable'}} */ #pragma clang loop unroll(badidentifier)
|
||||
while (i-7 < Length) {
|
||||
List[i] = i;
|
||||
}
|
||||
|
@ -100,6 +110,8 @@ void test(int *List, int Length) {
|
|||
#pragma clang loop vectorize(disable)
|
||||
/* expected-error {{incompatible directives 'interleave(disable)' and 'interleave_count(4)'}} */ #pragma clang loop interleave_count(4)
|
||||
#pragma clang loop interleave(disable)
|
||||
/* expected-error {{incompatible directives 'unroll(disable)' and 'unroll_count(4)'}} */ #pragma clang loop unroll_count(4)
|
||||
#pragma clang loop unroll(disable)
|
||||
while (i-8 < Length) {
|
||||
List[i] = i;
|
||||
}
|
||||
|
@ -108,14 +120,18 @@ void test(int *List, int Length) {
|
|||
#pragma clang loop vectorize(disable)
|
||||
/* expected-error {{duplicate directives 'interleave(disable)' and 'interleave(enable)'}} */ #pragma clang loop interleave(enable)
|
||||
#pragma clang loop interleave(disable)
|
||||
/* expected-error {{duplicate directives 'unroll(disable)' and 'unroll(enable)'}} */ #pragma clang loop unroll(enable)
|
||||
#pragma clang loop unroll(disable)
|
||||
while (i-9 < Length) {
|
||||
List[i] = i;
|
||||
}
|
||||
|
||||
/* expected-error {{incompatible directives 'vectorize_width(4)' and 'vectorize(disable)'}} */ #pragma clang loop vectorize(disable)
|
||||
/* expected-error {{incompatible directives 'vectorize(disable)' and 'vectorize_width(4)'}} */ #pragma clang loop vectorize(disable)
|
||||
#pragma clang loop vectorize_width(4)
|
||||
/* expected-error {{incompatible directives 'interleave_count(4)' and 'interleave(disable)'}} */ #pragma clang loop interleave(disable)
|
||||
/* expected-error {{incompatible directives 'interleave(disable)' and 'interleave_count(4)'}} */ #pragma clang loop interleave(disable)
|
||||
#pragma clang loop interleave_count(4)
|
||||
/* expected-error {{incompatible directives 'unroll(disable)' and 'unroll_count(4)'}} */ #pragma clang loop unroll(disable)
|
||||
#pragma clang loop unroll_count(4)
|
||||
while (i-10 < Length) {
|
||||
List[i] = i;
|
||||
}
|
||||
|
@ -124,6 +140,8 @@ void test(int *List, int Length) {
|
|||
#pragma clang loop vectorize_width(4)
|
||||
/* expected-error {{duplicate directives 'interleave_count(4)' and 'interleave_count(8)'}} */ #pragma clang loop interleave_count(8)
|
||||
#pragma clang loop interleave_count(4)
|
||||
/* expected-error {{duplicate directives 'unroll_count(4)' and 'unroll_count(8)'}} */ #pragma clang loop unroll_count(8)
|
||||
#pragma clang loop unroll_count(4)
|
||||
while (i-11 < Length) {
|
||||
List[i] = i;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue