Index: include/clang/Basic/DiagnosticParseKinds.td =================================================================== --- include/clang/Basic/DiagnosticParseKinds.td +++ include/clang/Basic/DiagnosticParseKinds.td @@ -1124,7 +1124,8 @@ "'enable'%select{|, 'full'}1%select{|, 'assume_safety'}2 or 'disable'}0">; def err_pragma_loop_invalid_option : Error< "%select{invalid|missing}0 option%select{ %1|}0; expected vectorize, " - "vectorize_width, interleave, interleave_count, unroll, unroll_count, or distribute">; + "vectorize_width, interleave, interleave_count, unroll, unroll_count, unroll_and_jam, " + "unroll_and_jam_count, or distribute">; def err_pragma_fp_invalid_option : Error< "%select{invalid|missing}0 option%select{ %1|}0; expected contract">; Index: lib/Parse/ParsePragma.cpp =================================================================== --- lib/Parse/ParsePragma.cpp +++ lib/Parse/ParsePragma.cpp @@ -2757,9 +2757,11 @@ /// 'vectorize' '(' loop-hint-keyword ')' /// 'interleave' '(' loop-hint-keyword ')' /// 'unroll' '(' unroll-hint-keyword ')' +/// 'unroll_and_jam' '(' unroll-hint-keyword ')' /// 'vectorize_width' '(' loop-hint-value ')' /// 'interleave_count' '(' loop-hint-value ')' /// 'unroll_count' '(' loop-hint-value ')' +/// 'unroll_and_jam_count' '(' loop-hint-value ')' /// /// loop-hint-keyword: /// 'enable' @@ -2815,10 +2817,12 @@ .Case("vectorize", true) .Case("interleave", true) .Case("unroll", true) + .Case("unroll_and_jam", true) .Case("distribute", true) .Case("vectorize_width", true) .Case("interleave_count", true) .Case("unroll_count", true) + .Case("unroll_and_jam_count", true) .Default(false); if (!OptionValid) { PP.Diag(Tok.getLocation(), diag::err_pragma_loop_invalid_option) Index: lib/Sema/SemaStmtAttr.cpp =================================================================== --- lib/Sema/SemaStmtAttr.cpp +++ lib/Sema/SemaStmtAttr.cpp @@ -149,11 +149,14 @@ .Case("interleave_count", LoopHintAttr::InterleaveCount) .Case("unroll", LoopHintAttr::Unroll) .Case("unroll_count", LoopHintAttr::UnrollCount) + .Case("unroll_and_jam", LoopHintAttr::UnrollAndJam) + .Case("unroll_and_jam_count", LoopHintAttr::UnrollAndJamCount) .Case("distribute", LoopHintAttr::Distribute) .Default(LoopHintAttr::Vectorize); if (Option == LoopHintAttr::VectorizeWidth || Option == LoopHintAttr::InterleaveCount || - Option == LoopHintAttr::UnrollCount) { + Option == LoopHintAttr::UnrollCount || + Option == LoopHintAttr::UnrollAndJamCount) { assert(ValueExpr && "Attribute must have a valid value expression."); if (S.CheckLoopHintExpr(ValueExpr, St->getLocStart())) return nullptr; @@ -161,6 +164,7 @@ } else if (Option == LoopHintAttr::Vectorize || Option == LoopHintAttr::Interleave || Option == LoopHintAttr::Unroll || + Option == LoopHintAttr::UnrollAndJam || Option == LoopHintAttr::Distribute) { assert(StateLoc && StateLoc->Ident && "Loop hint must have an argument"); if (StateLoc->Ident->isStr("disable")) Index: test/CodeGenCXX/pragma-unroll-and-jam.cpp =================================================================== --- test/CodeGenCXX/pragma-unroll-and-jam.cpp +++ test/CodeGenCXX/pragma-unroll-and-jam.cpp @@ -33,6 +33,39 @@ } } +void clang_unroll_and_jam(int *List, int Length, int Value) { + // CHECK: define {{.*}} @_Z20clang_unroll_and_jam +#pragma clang loop unroll_and_jam(enable) + for (int i = 0; i < Length; i++) { + for (int j = 0; j < Length; j++) { + // CHECK: br label {{.*}}, !llvm.loop ![[LOOP_4:.*]] + List[i * Length + j] = Value; + } + } +} + +void clang_unroll_and_jam_count(int *List, int Length, int Value) { + // CHECK: define {{.*}} @_Z26clang_unroll_and_jam_count +#pragma clang loop unroll_and_jam_count(4) + for (int i = 0; i < Length; i++) { + for (int j = 0; j < Length; j++) { + // CHECK: br label {{.*}}, !llvm.loop ![[LOOP_5:.*]] + List[i * Length + j] = Value; + } + } +} + +void clang_nounroll_and_jam(int *List, int Length, int Value) { + // CHECK: define {{.*}} @_Z22clang_nounroll_and_jam +#pragma clang loop unroll_and_jam(disable) + for (int i = 0; i < Length; i++) { + for (int j = 0; j < Length; j++) { + // CHECK: br label {{.*}}, !llvm.loop ![[LOOP_6:.*]] + List[i * Length + j] = Value; + } + } +} + void clang_unroll_plus_nounroll_and_jam(int *List, int Length, int Value) { // CHECK: define {{.*}} @_Z34clang_unroll_plus_nounroll_and_jam #pragma nounroll_and_jam @@ -51,5 +84,8 @@ // CHECK: ![[UNJ_4]] = !{!"llvm.loop.unroll_and_jam.count", i32 4} // CHECK: ![[LOOP_3]] = distinct !{![[LOOP_3]], ![[UNJ_DISABLE:.*]]} // CHECK: ![[UNJ_DISABLE]] = !{!"llvm.loop.unroll_and_jam.disable"} +// CHECK: ![[LOOP_4]] = distinct !{![[LOOP_4]], ![[UNJ_ENABLE:.*]]} +// CHECK: ![[LOOP_5]] = distinct !{![[LOOP_5]], ![[UNJ_4:.*]]} +// CHECK: ![[LOOP_6]] = distinct !{![[LOOP_6]], ![[UNJ_DISABLE:.*]]} // CHECK: ![[LOOP_7]] = distinct !{![[LOOP_7]], ![[UNROLL_4:.*]], ![[UNJ_DISABLE:.*]]} // CHECK: ![[UNROLL_4]] = !{!"llvm.loop.unroll.count", i32 4} Index: test/Parser/pragma-loop.cpp =================================================================== --- test/Parser/pragma-loop.cpp +++ test/Parser/pragma-loop.cpp @@ -147,7 +147,7 @@ /* 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, unroll_count, or distribute}} */ #pragma clang loop +/* expected-error {{missing option; expected vectorize, vectorize_width, interleave, interleave_count, unroll, unroll_count, unroll_and_jam, unroll_and_jam_count, or distribute}} */ #pragma clang loop /* 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 vectorize(enable) badkeyword(4) Index: test/Parser/pragma-unroll-and-jam.cpp =================================================================== --- test/Parser/pragma-unroll-and-jam.cpp +++ test/Parser/pragma-unroll-and-jam.cpp @@ -50,24 +50,24 @@ #pragma nounroll_and_jam /* expected-error {{expected a for, while, or do-while loop to follow '#pragma nounroll_and_jam'}} */ int l = Length; -/* expected-error {{incompatible directives '#pragma nounroll_and_jam' and '#pragma unroll_and_jam(4)'}} */ #pragma unroll_and_jam 4 -#pragma nounroll_and_jam +/* expected-error {{incompatible directives 'unroll_and_jam(disable)' and '#pragma unroll_and_jam(4)'}} */ #pragma unroll_and_jam 4 +#pragma clang loop unroll_and_jam(disable) for (int i = 0; i < Length; i++) { for (int j = 0; j < Length; j++) { List[i * Length + j] = Value; } } -#pragma nounroll_and_jam -#pragma unroll(4) +/* expected-error {{incompatible directives 'unroll_and_jam(full)' and '#pragma unroll_and_jam(4)'}} */ #pragma unroll_and_jam(4) +#pragma clang loop unroll_and_jam(full) for (int i = 0; i < Length; i++) { for (int j = 0; j < Length; j++) { List[i * Length + j] = Value; } } -// pragma clang unroll_and_jam is disabled for the moment -/* expected-error {{invalid option 'unroll_and_jam'; expected vectorize, vectorize_width, interleave, interleave_count, unroll, unroll_count, or distribute}} */ #pragma clang loop unroll_and_jam(4) +#pragma nounroll_and_jam +#pragma unroll(4) for (int i = 0; i < Length; i++) { for (int j = 0; j < Length; j++) { List[i * Length + j] = Value;