<div dir="ltr">I'd be nice to have a command-line switch to turn on and off this pragma. For example skipping "-fopenmp" makes a compiler to ignore OMP pragmas. <div>So if you add this switch one can analyse the pure effect of using vectorizing pragmas at the specified locations.</div>
</div><div class="gmail_extra"><br><br><div class="gmail_quote">2014-05-13 19:22 GMT+04:00 Aaron Ballman <span dir="ltr"><<a href="mailto:aaron@aaronballman.com" target="_blank">aaron@aaronballman.com</a>></span>:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">After committing r208702/3, your tests now pass for me. I'll take it<br>
on faith that the comment and formatting gets resolved when you<br>
commit, so LGTM. You should wait for Richard to sign off as well,<br>
since he had some comments.<br>
<br>
~Aaron<br>
<br>
On Tue, May 13, 2014 at 10:07 AM, Aaron Ballman <<a href="mailto:aaron@aaronballman.com">aaron@aaronballman.com</a>> wrote:<br>
> So I did a bit of looking at the crash issue, and this isn't Tyler's<br>
> bug. It's a bug with the way AttributedStmt is written. It has a<br>
> member declaration:<br>
><br>
> const Attr *Attrs[1];<br>
><br>
> So when std::copy is called with MSVC, a checked iterator overload is<br>
> called which says that there's only one element in the destination<br>
> array. So when we attempt to copy two attributes into the array, we<br>
> get the debug assert.<br>
><br>
> At first blush, ASTStmtReader::VisitAttributedStmt looks to be wrong.<br>
> It never allocates space for the attributes that it copies in, so<br>
> anything other than the first attribute will be a memory stomp.<br>
><br>
> I'll take a stab at fixing this.<br>
><br>
> ~Aaron<br>
><br>
> On Tue, May 13, 2014 at 9:56 AM, Aaron Ballman <<a href="mailto:aaron@aaronballman.com">aaron@aaronballman.com</a>> wrote:<br>
>> On Mon, May 12, 2014 at 7:20 PM, Tyler Nowicki <<a href="mailto:tnowicki@apple.com">tnowicki@apple.com</a>> wrote:<br>
>>> Hi Aaron, Ben,<br>
>>><br>
>>> Thank again for the review. I’ve made the changes you suggested.<br>
>>><br>
>>> There was a question about why I reversed the iteration over the attribute<br>
>>> list. The answer is that the attribute list built by ParsedAttributes stores<br>
>>> attributes in reverse order. However, this is wrong because the correct<br>
>>> order should be maintained for serialization/deserialization and error<br>
>>> reporting. So we have to iterate rbegin->rend. Ideally the ParsedAttributes<br>
>>> list should be fixed to store attributes in the order they appear but this<br>
>>> looks like a lot of work.<br>
>><br>
>> Ah, yes. That problem keeps rearing its ugly head. :-/<br>
>><br>
>>><br>
>>> Tyler<br>
>>><br>
>>><br>
>>><br>
>>><br>
>>> That part of tablegen probably shouldn’t be specialized for each type of<br>
>>> pragma should it? But from your comment below it sounds like thats what you<br>
>>> are thinking.<br>
>>><br>
>>><br>
>>> I'd have to think about it more, but it seems like tablegen shouldn't<br>
>>> have to specialize for each pragma, just all pragmas. Eg) the<br>
>>> difference between printing pragmas and printing attributes is minor<br>
>>> enough that it could be handled entirely by tablegen without the<br>
>>> pragma authors having to write special code.<br>
>>><br>
>>><br>
>>> I’m pretty sure that each type of pragma has a unique syntax that makes it<br>
>>> difficult to generalize.<br>
>>><br>
>>><br>
>>> + ["disable", "enable", "value"],<br>
>>> + ["Disable", "Enable", "Value"]>,<br>
>>><br>
>>><br>
>>> This is actually an optional argument as well, but is not marked as<br>
>>> such. It should get a , 1. Also, this suggests we need a new argument<br>
>>> type that represents a union of arguments, since that's really what<br>
>>> you want (one of these two arguments must be used, but you don't care<br>
>>> which). A FIXME would probably be appropriate (though you don't have<br>
>>> to implement the functionality for this patch).<br>
>>><br>
>>><br>
>>> I don’t think it is. Just specifying vectorize or interleave does not imply<br>
>>> a default action. Perhaps it should?<br>
>><br>
>> As it's written, it implies that you must specify vectorize or<br>
>> interleave, followed by disable/enable/value, and then optionally<br>
>> supply a value. Eg) #pragma loop vectorize(enable, 4)<br>
>><br>
>> That's why I think we should have a Union argument type because you<br>
>> really want it to either be enable|disable, or an integer value, not<br>
>> both.<br>
>><br>
>> Not something that needs doing for this patch by any means. :-)<br>
>><br>
>>><br>
>>><br>
>>> + ExprArgument<"Value", 1>];<br>
>>><br>
>>><br>
>>> Judging by the tests, this should be a DefaultIntArgument<"Value", 1>.<br>
>>> Either that, or there are tests missing where expressions are used<br>
>>> (and honestly, it would strike me as slightly strange to allow general<br>
>>> expressions here).<br>
>>><br>
>>><br>
>>> I was thinking ahead to non-type template arguments. But that can wait. I’ll<br>
>>> use an int for now.<br>
>>><br>
>>><br>
>>> const char *Names[] = { "llvm.vectorizer.width", "llvm.vectorizer.unroll" };<br>
>>> llvm::Value *Value;<br>
>>> llvm::MDString *Name;<br>
>>><br>
>>> if (Kind == LoopHintAttr::Enable) {<br>
>>> Name = llvm::MDString::get(Context, "llvm.vectorizer.enable");<br>
>>> Value = Builder.getTrue();<br>
>>> } else {<br>
>>> Name = llvm::MDString::get(Context, Names[Option]);<br>
>>> Value = llvm::ConstantInt::get(Int32Ty, ValueInt); // You already<br>
>>> set ValueInt to 1 by default, and overwrite when the Kind is a Value.<br>
>>> }<br>
>>><br>
>>><br>
>>> Good idea!<br>
>>><br>
>>><br>
>>> + }<br>
>>> +<br>
>>> + // Get the next statement.<br>
>>> + MaybeParseCXX11Attributes(Attrs);<br>
>>> +<br>
>>> + StmtResult S = ParseStatementOrDeclarationAfterAttributes(Stmts,<br>
>>> + /*OnlyStatement*/ true, 0, Attrs);<br>
>>><br>
>>><br>
>>> Shouldn't we be passing the OnlyStatement which was passed into the<br>
>>> function? Same for passing in the TrailingElseLoc instead of 0?<br>
>>><br>
>>><br>
>>> These inputs confused me, I duplicated the call made in<br>
>>> ParseLabeledStatement(). I think OnlyStatement indicates that the next thing<br>
>>> parsed is expected be a statement, rather than a declaration. I’ll pass the<br>
>>> arguments as you suggest.<br>
>>><br>
>>><br>
>>> Btw, when I test your patch locally, I get failed assertions from the<br>
>>> STL. "array iterator + offset out of range" on a call to std::copy<br>
>>> within ASTStmtReader::VisitAttributedStmt().<br>
>>><br>
>>><br>
>>> I don’t seem to have that, also I didn’t make any changes to ASTStmtReader?<br>
>>> Could you try out the attached patch and provide the stack dump if it fails<br>
>>> again.<br>
>><br>
>> Yup, still failing.<br>
>><br>
>> 58> FAIL: Clang :: PCH/pragma-loop.cpp (3877 of 7229)<br>
>> 58> ******************** TEST 'Clang :: PCH/pragma-loop.cpp' FAILED<br>
>> ********************<br>
>> 58> Script:<br>
>> 58> --<br>
>> 58> E:/llvm/2013/Debug/bin/clang.EXE -cc1 -internal-isystem<br>
>> E:\llvm\2013\Debug\bin\..\lib\clang\3.5.0\include -emit-pch -o<br>
>> E:\llvm\2013\tools\clang\test\PCH\Output\pragma-loop.cpp.tmp.a<br>
>> E:\llvm\llvm\tools\clang\test\PCH\pragma-loop.cpp<br>
>> 58> E:/llvm/2013/Debug/bin/clang.EXE -cc1 -internal-isystem<br>
>> E:\llvm\2013\Debug\bin\..\lib\clang\3.5.0\include -include-pch<br>
>> E:\llvm\2013\tools\clang\test\PCH\Output\pragma-loop.cpp.tmp.a<br>
>> E:\llvm\llvm\tools\clang\test\PCH\pragma-loop.cpp -ast-print -o - |<br>
>> E:/llvm/2013/Debug/bin\FileCheck.EXE<br>
>> E:\llvm\llvm\tools\clang\test\PCH\pragma-loop.cpp<br>
>> 58> --<br>
>> 58> Exit Code: 2<br>
>> 58><br>
>> 58> Command Output (stdout):<br>
>> 58> --<br>
>> 58> Command 0: "E:/llvm/2013/Debug/bin/clang.EXE" "-cc1"<br>
>> "-internal-isystem"<br>
>> "E:\llvm\2013\Debug\bin\..\lib\clang\3.5.0\include" "-emit-pch" "-o"<br>
>> "E:\llvm\2013\tools\clang\test\PCH\Output\pragma-loop.cpp.tmp.a"<br>
>> "E:\llvm\llvm\tools\clang\test\PCH\pragma-loop.cpp"<br>
>> 58> Command 0 Result: 0<br>
>> 58> Command 0 Output:<br>
>> 58><br>
>> 58><br>
>> 58> Command 0 Stderr:<br>
>> 58><br>
>> 58><br>
>> 58> Command 1: "E:/llvm/2013/Debug/bin/clang.EXE" "-cc1"<br>
>> "-internal-isystem"<br>
>> "E:\llvm\2013\Debug\bin\..\lib\clang\3.5.0\include" "-include-pch"<br>
>> "E:\llvm\2013\tools\clang\test\PCH\Output\pragma-loop.cpp.tmp.a"<br>
>> "E:\llvm\llvm\tools\clang\test\PCH\pragma-loop.cpp" "-ast-print" "-o"<br>
>> "-"<br>
>> 58> Command 1 Result: -2147483645<br>
>> 58> Command 1 Output:<br>
>> 58><br>
>> 58><br>
>> 58> Command 1 Stderr:<br>
>> 58> Stack dump:<br>
>> 58><br>
>> 58> 0. Program arguments: E:/llvm/2013/Debug/bin/clang.EXE -cc1<br>
>> -internal-isystem E:\llvm\2013\Debug\bin\..\lib\clang\3.5.0\include<br>
>> -include-pch E:\llvm\2013\tools\clang\test\PCH\Output\pragma-loop.cpp.tmp.a<br>
>> E:\llvm\llvm\tools\clang\test\PCH\pragma-loop.cpp -ast-print -o -<br>
>> 58><br>
>> 58> 1. <eof> parser at end of file<br>
>> 58><br>
>> 58> 0x6C47CEE6 (0x055612B0 0x04BD89E0 0x00000618 0x00C6D504),<br>
>> ?_Debug_message@std@@YAXPB_W0I@Z() + 0x26 bytes(s)<br>
>> 58><br>
>> 58> 0x032A6E98 (0x00000002 0x00C6D434 0x00C6D44C 0x032A6E0B),<br>
>> std::_Array_const_iterator<clang::Attr const *,1>::operator+=() + 0x38<br>
>> bytes(s), d:\program files (x86)\microsoft visual studio<br>
>> 12.0\vc\include\xutility, line 1560 + 0x17 byte(s)<br>
>> 58><br>
>> 58> 0x032A6F4A (0x00000002 0xCCCCCCCC 0x00000000 0x00000000),<br>
>> std::_Array_iterator<clang::Attr const *,1>::operator+=() + 0x1A<br>
>> bytes(s), d:\program files (x86)\microsoft visual studio<br>
>> 12.0\vc\include\xutility, line 1764<br>
>> 58><br>
>> 58> 0x032A6E0B (0x00C6D464 0x00000002 0xCCCCCCCC 0xCCCCCCCC),<br>
>> std::_Array_iterator<clang::Attr const *,1>::operator+() + 0x3B<br>
>> bytes(s), d:\program files (x86)\microsoft visual studio<br>
>> 12.0\vc\include\xutility, line 1770 + 0xC byte(s)<br>
>> 58><br>
>> 58> 0x032A22D6 (0x00C6D504 0x00C6D564 0x00C6D56C 0x00000000),<br>
>> std::_Copy_impl<clang::Attr * *,std::_Array_iterator<clang::Attr const<br>
>> *,1> >() + 0x36 bytes(s), d:\program files (x86)\microsoft visual<br>
>> studio 12.0\vc\include\xutility, line 2097<br>
>> 58><br>
>> 58> 0x032A227F (0x00C6D504 0x00C6D564 0x00C6D56C 0x00000000),<br>
>> std::_Copy_impl<clang::Attr * *,std::_Array_iterator<clang::Attr const<br>
>> *,1> >() + 0x5F bytes(s), d:\program files (x86)\microsoft visual<br>
>> studio 12.0\vc\include\xutility, line 2107 + 0x4B byte(s)<br>
>> 58><br>
>> 58> 0x032A3313 (0x00C6D504 0x00C6D564 0x00C6D56C 0x00000000),<br>
>> std::copy<clang::Attr * *,std::_Array_iterator<clang::Attr const *,1><br>
>>>() + 0xC3 bytes(s), d:\program files (x86)\microsoft visual studio<br>
>> 12.0\vc\include\xutility, line 2132 + 0x4F byte(s)<br>
>> 58><br>
>> 58> 0x032A3228 (0x00C6D564 0x00C6D56C 0x00FF510C 0x00C6DEFC),<br>
>> std::copy<clang::Attr * *,clang::Attr const *,1>() + 0x38 bytes(s),<br>
>> d:\program files (x86)\microsoft visual studio<br>
>> 12.0\vc\include\xutility, line 2145 + 0x23 byte(s)<br>
>> 58><br>
>> 58> 0x03297A73 (0x00FF50FC 0xCCCCCCCC 0x00000002 0xCCCCCCCC),<br>
>> clang::ASTStmtReader::VisitAttributedStmt() + 0x133 bytes(s),<br>
>> e:\llvm\llvm\tools\clang\lib\serialization\astreaderstmt.cpp, line 179<br>
>> + 0x1E byte(s)<br>
>> 58><br>
>> 58> 0x032A7C3B (0x00FF50FC 0x00C6E3E4 0x00C6DF34 0xCCCCCCCC),<br>
>> clang::StmtVisitorBase<clang::make_ptr,clang::ASTStmtReader,void>::Visit()<br>
>> + 0x3FB bytes(s),<br>
>> e:\llvm\llvm\tools\clang\include\clang\ast\stmtvisitor.h, line 43 +<br>
>> 0xC byte(s)<br>
>> 58><br>
>> 58> 0x03296804 (0x00FD6E30 0xCCCCCCCC 0x00FD6E30 0xCCCCCCCC),<br>
>> clang::ASTReader::ReadStmtFromStream() + 0x3604 bytes(s),<br>
>> e:\llvm\llvm\tools\clang\lib\serialization\astreaderstmt.cpp, line<br>
>> 2539<br>
>> 58><br>
>> 58> 0x031CBE4A (0x00014648 0x00000000 0x00C6DF78 0x03BB3352),<br>
>> clang::ASTReader::GetExternalDeclStmt() + 0x6A bytes(s),<br>
>> e:\llvm\llvm\tools\clang\lib\serialization\astreader.cpp, line 6156<br>
>> 58><br>
>> 58> 0x03BB42D8 (0x00FD40C4 0x00FD38C8 0x00C6DF70 0x03BB4416),<br>
>> clang::LazyOffsetPtr<clang::Stmt,unsigned<br>
>> __int64,{clang::ExternalASTSource::`vcall'{16}',0}>::get() + 0x88<br>
>> bytes(s), e:\llvm\llvm\tools\clang\include\clang\ast\externalastsource.h,<br>
>> line 351 + 0x2A byte(s)<br>
>> 58><br>
>> 58> 0x03BA74F6 (0x00C6DF64 0xCCCCCCCC 0x00FD38C8 0xCCCCCCCC),<br>
>> clang::FunctionDecl::getBody() + 0x56 bytes(s),<br>
>> e:\llvm\llvm\tools\clang\lib\ast\decl.cpp, line 2246 + 0x1D byte(s)<br>
>> 58><br>
>> 58> 0x03BB4416 (0x00FC8880 0x00000000 0x00C6E304 0x00000002),<br>
>> clang::FunctionDecl::getBody() + 0x26 bytes(s),<br>
>> e:\llvm\llvm\tools\clang\include\clang\ast\decl.h, line 1654<br>
>> 58><br>
>> 58> 0x03C4F282 (0x00FD38C8 0x00C6E5B0 0x00C6E408 0x03C524AC),<br>
>> `anonymous namespace'::DeclPrinter::VisitFunctionDecl() + 0xD92<br>
>> bytes(s), e:\llvm\llvm\tools\clang\lib\ast\declprinter.cpp, line 589 +<br>
>> 0x28 byte(s)<br>
>> 58><br>
>> 58> 0x03C527DA (0x00FD38C8 0x0000002A 0x00C6E5B0 0x00C6E488),<br>
>> clang::declvisitor::Base<clang::declvisitor::make_ptr,`anonymous<br>
>> namespace'::DeclPrinter,void>::VisitCXXMethodDecl() + 0x1A bytes(s),<br>
>> e:\llvm\2013\tools\clang\include\clang\ast\declnodes.inc, line 349 +<br>
>> 0x1A byte(s)<br>
>> 58><br>
>> 58> 0x03C524AC (0x00FD38C8 0x00C6E4DC 0x00C6E6EC 0xCCCCCCCC),<br>
>> clang::declvisitor::Base<clang::declvisitor::make_ptr,`anonymous<br>
>> namespace'::DeclPrinter,void>::Visit() + 0x30C bytes(s),<br>
>> e:\llvm\llvm\tools\clang\include\clang\ast\declvisitor.h, line 349 +<br>
>> 0xC byte(s)<br>
>> 58><br>
>> 58> 0x03C4DD12 (0x00FD3548 0x00000001 0x00C6E570 0x00FD3548),<br>
>> `anonymous namespace'::DeclPrinter::VisitDeclContext() + 0x2D2<br>
>> bytes(s), e:\llvm\llvm\tools\clang\lib\ast\declprinter.cpp, line 285<br>
>> 58><br>
>> 58> 0x03C4FF83 (0x00FD3528 0x0000001C 0x00C6E5B0 0x00C6E570),<br>
>> `anonymous namespace'::DeclPrinter::VisitCXXRecordDecl() + 0x1E3<br>
>> bytes(s), e:\llvm\llvm\tools\clang\lib\ast\declprinter.cpp, line 787<br>
>> 58><br>
>> 58> 0x03C523BE (0x00FD3528 0x00C6E694 0x00C6E6EC 0xCCCCCCCC),<br>
>> clang::declvisitor::Base<clang::declvisitor::make_ptr,`anonymous<br>
>> namespace'::DeclPrinter,void>::Visit() + 0x21E bytes(s),<br>
>> e:\llvm\llvm\tools\clang\include\clang\ast\declvisitor.h, line 233 +<br>
>> 0xC byte(s)<br>
>> 58><br>
>> 58> 0x03C4DD12 (0x00FD30D4 0x00000000 0x00FD30D4 0x00C6E5B0),<br>
>> `anonymous namespace'::DeclPrinter::VisitDeclContext() + 0x2D2<br>
>> bytes(s), e:\llvm\llvm\tools\clang\lib\ast\declprinter.cpp, line 285<br>
>> 58><br>
>> 58> 0x03C4E03D (0x00FD30C0 0x0000003B 0x00C6E5B0 0x00C6E694),<br>
>> `anonymous namespace'::DeclPrinter::VisitTranslationUnitDecl() + 0x3D<br>
>> bytes(s), e:\llvm\llvm\tools\clang\lib\ast\declprinter.cpp, line 322<br>
>> 58><br>
>> 58> 0x03C525B8 (0x00FD30C0 0x00C6E770 0xCCCCCCCC 0x00FC8880),<br>
>> clang::declvisitor::Base<clang::declvisitor::make_ptr,`anonymous<br>
>> namespace'::DeclPrinter,void>::Visit() + 0x418 bytes(s),<br>
>> e:\llvm\llvm\tools\clang\include\clang\ast\declvisitor.h, line 473 +<br>
>> 0xC byte(s)<br>
>> 58><br>
>> 58> 0x03C4D5F6 (0x00FC8880 0x00FCF114 0x00000000 0x00000001),<br>
>> clang::Decl::print() + 0x56 bytes(s),<br>
>> e:\llvm\llvm\tools\clang\lib\ast\declprinter.cpp, line 102<br>
>> 58><br>
>> 58> 0x03C4D583 (0x00FC8880 0x00000000 0x00000001 0xCCCCCCCC),<br>
>> clang::Decl::print() + 0x33 bytes(s),<br>
>> e:\llvm\llvm\tools\clang\lib\ast\declprinter.cpp, line 96<br>
>> 58><br>
>> 58> 0x023E2279 (0x00FD30C0 0x00FD30C0 0x00FC6638 0x00C6E770),<br>
>> `anonymous namespace'::ASTPrinter::print() + 0x89 bytes(s),<br>
>> e:\llvm\llvm\tools\clang\lib\frontend\astconsumers.cpp, line 90<br>
>> 58><br>
>> 58> 0x023521D0 (0x00FCBA38 0x00C6E818 0x00C6E780 0x00FF2AC0),<br>
>> `anonymous namespace'::ASTPrinter::HandleTranslationUnit() + 0x40<br>
>> bytes(s), e:\llvm\llvm\tools\clang\lib\frontend\astconsumers.cpp, line<br>
>> 48 + 0xC byte(s)<br>
>> 58><br>
>> 58> 0x03130FB8 (0x00FE4E10 0x00000000 0x00000000 0x00C6E79C),<br>
>> clang::ParseAST() + 0x238 bytes(s),<br>
>> e:\llvm\llvm\tools\clang\lib\parse\parseast.cpp, line 154 + 0x18<br>
>> byte(s)<br>
>> 58><br>
>> 58> 0x022E00B1 (0x00C6E7C4 0xCCCCCCCC 0xCCCCCCCC 0xCCCCCCCC),<br>
>> clang::ASTFrontendAction::ExecuteAction() + 0x101 bytes(s),<br>
>> e:\llvm\llvm\tools\clang\lib\frontend\frontendaction.cpp, line 501 +<br>
>> 0x30 byte(s)<br>
>> 58><br>
>> 58> 0x022DFCBE (0x00C6E8BC 0x00C6F97C 0xCCCCCCCC 0xCCCCCCCC),<br>
>> clang::FrontendAction::Execute() + 0x7E bytes(s),<br>
>> e:\llvm\llvm\tools\clang\lib\frontend\frontendaction.cpp, line 402 +<br>
>> 0xF byte(s)<br>
>> 58><br>
>> 58> 0x022AF2B1 (0x00FABE08 0x00C6EE38 0x00C6F97C 0xCCCCCCCC),<br>
>> clang::CompilerInstance::ExecuteAction() + 0x281 bytes(s),<br>
>> e:\llvm\llvm\tools\clang\lib\frontend\compilerinstance.cpp, line 721<br>
>> 58><br>
>> 58> 0x023EDAE8 (0x00FA6968 0x00C6FD9C 0xCCCCCCCC 0xCCCCCCCC),<br>
>> clang::ExecuteCompilerInvocation() + 0x318 bytes(s),<br>
>> e:\llvm\llvm\tools\clang\lib\frontendtool\executecompilerinvocation.cpp,<br>
>> line 239 + 0x11 byte(s)<br>
>> 58><br>
>> 58> 0x012C9682 (0x00C6F984 0x00C6F9A4 0x00FA6B90 0x01201361),<br>
>> cc1_main() + 0x2F2 bytes(s),<br>
>> e:\llvm\llvm\tools\clang\tools\driver\cc1_main.cpp, line 112 + 0xE<br>
>> byte(s)<br>
>> 58><br>
>> 58> 0x012B80B5 (0x0000000A 0x00FA2A98 0x00F9EAF8 0xFF71AEA3), main()<br>
>> + 0x225 bytes(s), e:\llvm\llvm\tools\clang\tools\driver\driver.cpp,<br>
>> line 319 + 0x45 byte(s)<br>
>> 58><br>
>> 58> 0x03EC2F89 (0x00C6FE00 0x7655338A 0x7EFDE000 0x00C6FE40),<br>
>> __tmainCRTStartup() + 0x199 bytes(s),<br>
>> f:\dd\vctools\crt\crtw32\dllstuff\crtexe.c, line 626 + 0x19 byte(s)<br>
>> 58><br>
>> 58> 0x03EC30CD (0x7EFDE000 0x00C6FE40 0x778C9F72 0x7EFDE000),<br>
>> mainCRTStartup() + 0xD bytes(s),<br>
>> f:\dd\vctools\crt\crtw32\dllstuff\crtexe.c, line 466<br>
>> 58><br>
>> 58> 0x7655338A (0x7EFDE000 0x1D841147 0x00000000 0x00000000),<br>
>> BaseThreadInitThunk() + 0x12 bytes(s)<br>
>> 58><br>
>> 58> 0x778C9F72 (0x03EC30C0 0x7EFDE000 0x00000000 0x00000000),<br>
>> RtlInitializeExceptionChain() + 0x63 bytes(s)<br>
>> 58><br>
>> 58> 0x778C9F45 (0x03EC30C0 0x7EFDE000 0x00000000 0x00000000),<br>
>> RtlInitializeExceptionChain() + 0x36 bytes(s)<br>
>> 58><br>
>> 58><br>
>> 58><br>
>> 58> Command 2: "E:/llvm/2013/Debug/bin\FileCheck.EXE"<br>
>> "E:\llvm\llvm\tools\clang\test\PCH\pragma-loop.cpp"<br>
>> 58> Command 2 Result: 2<br>
>> 58> Command 2 Output:<br>
>> 58><br>
>> 58><br>
>> 58> Command 2 Stderr:<br>
>> 58>CUSTOMBUILD : FileCheck error : '-' is empty.<br>
>> 58><br>
>> 58><br>
>> 58><br>
>> 58><br>
>> 58> --<br>
>> 58><br>
>> 58> ********************<br>
>><br>
>> Some formatting nits (you may want to run clang-format over your<br>
>> patch; <a href="http://clang.llvm.org/docs/ClangFormat.html" target="_blank">http://clang.llvm.org/docs/ClangFormat.html</a>) and one question<br>
>> which may require a comment to be updated. Once those are resolved,<br>
>> along with the crash from above, I think you'll be all set!<br>
>><br>
>>> Index: include/clang/Basic/Attr.td<br>
>>> ===================================================================<br>
>>> --- include/clang/Basic/Attr.td (revision 208638)<br>
>>> +++ include/clang/Basic/Attr.td (working copy)<br>
>>> @@ -1750,3 +1750,64 @@<br>
>>> def Unaligned : IgnoredAttr {<br>
>>> let Spellings = [Keyword<"__unaligned">];<br>
>>> }<br>
>>> +<br>
>>> +def LoopHint : Attr {<br>
>>> + // LoopHint Vectorize:<br>
>>> + // enable - use vector instructions.<br>
>>> + // disable - do not use vector instructions.<br>
>>> + // positive value - use vector instructions of the specified width.<br>
>>> +<br>
>>> + // LoopHint Interleave:<br>
>>> + // enable - interleave multiple loop iterations.<br>
>>> + // disable - do not interleave multiple loop interactions.<br>
>>> + // positive value - interleave the specified number of loop interations.<br>
>>> +<br>
>>> + // FIXME: Add Pragma spelling to tablegen and<br>
>>> + // use it here.<br>
>>> + let Spellings = [Keyword<"loop">];<br>
>>> +<br>
>>> + // State of the loop optimization specified by the spelling.<br>
>>> + let Args = [EnumArgument<"Option", "OptionType",<br>
>>> + ["vectorize", "interleave"],<br>
>>> + ["Vectorize", "Interleave"]>,<br>
>>> + EnumArgument<"Kind", "KindType",<br>
>>> + ["disable", "enable", "value"],<br>
>>> + ["Disable", "Enable", "Value"]>,<br>
>>> + DefaultIntArgument<"Value", 1>];<br>
>>> +<br>
>>> + let AdditionalMembers = [{<br>
>>> + // Kinds are compatible if they are not exclusive.<br>
>>> + static bool isCompatible(int Kind1, int Kind2) {<br>
>>> + return (Kind1 == Disable) == (Kind2 == Disable);<br>
>><br>
>> So if Kind1 = Enable and Kind2 = Value, they are compatible? If so,<br>
>> can the comment be updated to make that a bit more explicit<br>
>> (otherwise, it kind of looks like this code may have a bug).<br>
>><br>
>>> + }<br>
>>> +<br>
>>> + static StringRef getOptionName(int Option) {<br>
>>> + switch (Option) {<br>
>>> + case Vectorize: return "vectorize";<br>
>>> + case Interleave: return "interleave";<br>
>>> + }<br>
>>> + llvm_unreachable("Unhandled LoopHint option.");<br>
>>> + }<br>
>>> +<br>
>>> + static StringRef getKindName(int Kind) {<br>
>>> + switch (Kind) {<br>
>>> + case Disable: return "disable";<br>
>>> + case Enable: return "enable";<br>
>>> + case Value: return "value";<br>
>>> + }<br>
>>> + llvm_unreachable("Unhandled LoopHint kind.");<br>
>>> + }<br>
>>> +<br>
>>> + // FIXME: Modify pretty printer to print this pragma<br>
>>> + void print(raw_ostream &OS, const PrintingPolicy &Policy) const {<br>
>>> + OS << getOptionName(option) << "(";<br>
>>> + if (getKind() == Value)<br>
>>> + OS << value;<br>
>>> + else<br>
>>> + OS << getKindName(kind);<br>
>>> + OS << ")\n";<br>
>>> + }<br>
>>> + }];<br>
>>> +<br>
>>> + let Documentation = [Undocumented];<br>
>>> +}<br>
>>> Index: include/clang/Basic/DiagnosticParseKinds.td<br>
>>> ===================================================================<br>
>>> --- include/clang/Basic/DiagnosticParseKinds.td (revision 208638)<br>
>>> +++ include/clang/Basic/DiagnosticParseKinds.td (working copy)<br>
>>> @@ -884,6 +884,14 @@<br>
>>> "unexpected OpenMP clause '%0' in directive '#pragma omp %1'">;<br>
>>> def err_omp_more_one_clause : Error<<br>
>>> "directive '#pragma omp %0' cannot contain more than one '%1' clause">;<br>
>>> +<br>
>>> +// Pragma loop support.<br>
>>> +def err_pragma_loop_invalid_option : Error<<br>
>>> + "%select{invalid|missing}0 option%select{ '%1'|}0 in directive "<br>
>>> + "'#pragma loop'; expected either vectorize or interleave">;<br>
>>> +def err_pragma_loop_invalid_type : Error<<br>
>>> + "invalid value '%0' in directive '#pragma loop %1'; expected either "<br>
>>> + "'enable', 'disable', or a positive integer">;<br>
>>> } // end of Parse Issue category.<br>
>>><br>
>>> let CategoryName = "Modules Issue" in {<br>
>>> Index: include/clang/Basic/DiagnosticSemaKinds.td<br>
>>> ===================================================================<br>
>>> --- include/clang/Basic/DiagnosticSemaKinds.td (revision 208638)<br>
>>> +++ include/clang/Basic/DiagnosticSemaKinds.td (working copy)<br>
>>> @@ -537,6 +537,13 @@<br>
>>> "#pragma visibility pop with no matching #pragma visibility push">;<br>
>>> def note_surrounding_namespace_starts_here : Note<<br>
>>> "surrounding namespace with visibility attribute starts here">;<br>
>>> +def err_pragma_loop_invalid_value : Error<<br>
>>> + "expected a positive integer in directive '#pragma loop %0'">;<br>
>>> +def err_pragma_loop_incompatible : Error<<br>
>>> + "'%0' and '%1' directive option types are incompatible in '#pragma loop %2'">;<br>
>>> +def err_pragma_loop_precedes_nonloop : Error<<br>
>>> + "expected a for, while, or do-while loop to follow the '#pragma loop' "<br>
>>> + "directive">;<br>
>>><br>
>>> /// Objective-C parser diagnostics<br>
>>> def err_duplicate_class_def : Error<<br>
>>> Index: include/clang/Basic/TokenKinds.def<br>
>>> ===================================================================<br>
>>> --- include/clang/Basic/TokenKinds.def (revision 208638)<br>
>>> +++ include/clang/Basic/TokenKinds.def (working copy)<br>
>>> @@ -701,6 +701,11 @@<br>
>>> ANNOTATION(pragma_openmp)<br>
>>> ANNOTATION(pragma_openmp_end)<br>
>>><br>
>>> +// Annotations for loop pragma directives #pragma loop ...<br>
>>> +// The lexer produces these so that they only take effect when the parser<br>
>>> +// handles #pragma loop ... directives.<br>
>>> +ANNOTATION(pragma_loop_hint)<br>
>>> +<br>
>>> // Annotations for module import translated from #include etc.<br>
>>> ANNOTATION(module_include)<br>
>>> ANNOTATION(module_begin)<br>
>>> Index: include/clang/Parse/Parser.h<br>
>>> ===================================================================<br>
>>> --- include/clang/Parse/Parser.h (revision 208638)<br>
>>> +++ include/clang/Parse/Parser.h (working copy)<br>
>>> @@ -20,6 +20,7 @@<br>
>>> #include "clang/Lex/CodeCompletionHandler.h"<br>
>>> #include "clang/Lex/Preprocessor.h"<br>
>>> #include "clang/Sema/DeclSpec.h"<br>
>>> +#include "clang/Sema/LoopHint.h"<br>
>>> #include "clang/Sema/Sema.h"<br>
>>> #include "llvm/ADT/SmallVector.h"<br>
>>> #include "llvm/Support/Compiler.h"<br>
>>> @@ -160,6 +161,7 @@<br>
>>> std::unique_ptr<PragmaHandler> MSConstSeg;<br>
>>> std::unique_ptr<PragmaHandler> MSCodeSeg;<br>
>>> std::unique_ptr<PragmaHandler> MSSection;<br>
>>> + std::unique_ptr<PragmaHandler> LoopHintHandler;<br>
>>><br>
>>> std::unique_ptr<CommentHandler> CommentSemaHandler;<br>
>>><br>
>>> @@ -518,6 +520,10 @@<br>
>>> /// #pragma clang __debug captured<br>
>>> StmtResult HandlePragmaCaptured();<br>
>>><br>
>>> + /// \brief Handle the annotation token produced for<br>
>>> + /// #pragma vectorize...<br>
>>> + LoopHint HandlePragmaLoopHint();<br>
>>> +<br>
>>> /// GetLookAheadToken - This peeks ahead N tokens and returns that token<br>
>>> /// without consuming any tokens. LookAhead(0) returns 'Tok', LookAhead(1)<br>
>>> /// returns the token after Tok, etc.<br>
>>> @@ -1600,6 +1606,10 @@<br>
>>> StmtResult ParseReturnStatement();<br>
>>> StmtResult ParseAsmStatement(bool &msAsm);<br>
>>> StmtResult ParseMicrosoftAsmStatement(SourceLocation AsmLoc);<br>
>>> + StmtResult ParsePragmaLoopHint(StmtVector &Stmts,<br>
>>> + bool OnlyStatement,<br>
>>> + SourceLocation *TrailingElseLoc,<br>
>>> + ParsedAttributesWithRange &Attrs);<br>
>>><br>
>>> /// \brief Describes the behavior that should be taken for an __if_exists<br>
>>> /// block.<br>
>>> Index: include/clang/Sema/LoopHint.h<br>
>>> ===================================================================<br>
>>> --- include/clang/Sema/LoopHint.h (revision 0)<br>
>>> +++ include/clang/Sema/LoopHint.h (working copy)<br>
>>> @@ -0,0 +1,32 @@<br>
>>> +//===--- LoopHint.h - Types for LoopHint ------------------------*- C++ -*-===//<br>
>>> +//<br>
>>> +// The LLVM Compiler Infrastructure<br>
>>> +//<br>
>>> +// This file is distributed under the University of Illinois Open Source<br>
>>> +// License. See LICENSE.TXT for details.<br>
>>> +//<br>
>>> +//===----------------------------------------------------------------------===//<br>
>>> +<br>
>>> +<br>
>>> +#ifndef LLVM_CLANG_SEMA_LOOPHINT_H<br>
>>> +#define LLVM_CLANG_SEMA_LOOPHINT_H<br>
>>> +<br>
>>> +#include "clang/Basic/IdentifierTable.h"<br>
>>> +#include "clang/Basic/SourceLocation.h"<br>
>>> +#include "clang/Sema/AttributeList.h"<br>
>>> +#include "clang/Sema/Ownership.h"<br>
>>> +<br>
>>> +namespace clang {<br>
>>> +<br>
>>> +/// \brief Loop hint specified by a pragma loop directive.<br>
>>> +struct LoopHint {<br>
>>> + SourceRange Range;<br>
>>> + Expr *ValueExpr;<br>
>>> + IdentifierLoc *LoopLoc;<br>
>>> + IdentifierLoc *ValueLoc;<br>
>>> + IdentifierLoc *OptionLoc;<br>
>>> +};<br>
>>> +<br>
>>> +} // end namespace clang<br>
>>> +<br>
>>> +#endif // LLVM_CLANG_SEMA_LOOPHINT_H<br>
>>> Index: lib/AST/StmtPrinter.cpp<br>
>>> ===================================================================<br>
>>> --- lib/AST/StmtPrinter.cpp (revision 208638)<br>
>>> +++ lib/AST/StmtPrinter.cpp (working copy)<br>
>>> @@ -168,19 +168,32 @@<br>
>>> }<br>
>>><br>
>>> void StmtPrinter::VisitAttributedStmt(AttributedStmt *Node) {<br>
>>> - OS << "[[";<br>
>>> bool first = true;<br>
>>> - for (ArrayRef<const Attr*>::iterator it = Node->getAttrs().begin(),<br>
>>> - end = Node->getAttrs().end();<br>
>>> - it != end; ++it) {<br>
>>> - if (!first) {<br>
>>> - OS << ", ";<br>
>>> - first = false;<br>
>>> + std::string raw_attr_os;<br>
>>> + llvm::raw_string_ostream AttrOS(raw_attr_os);<br>
>>> + for (auto I = Node->getAttrs().rbegin(), E = Node->getAttrs().rend();<br>
>>> + I != E; ++I) {<br>
>>> + // FIXME: This hack will be removed when printPretty<br>
>>> + // has been modified to print pretty pragmas.<br>
>>> + if (dyn_cast<LoopHintAttr>(*I)) {<br>
>>> + const LoopHintAttr *LHA = cast<LoopHintAttr>(*I);<br>
>>> + OS << "#pragma loop ";<br>
>>> + LHA->print(OS, Policy);<br>
>>> + } else {<br>
>>> + if (!first) {<br>
>>> + AttrOS << ", ";<br>
>>> + first = false;<br>
>>> + }<br>
>>> + // TODO: check this<br>
>>> + (*I)->printPretty(AttrOS, Policy);<br>
>>> }<br>
>>> - // TODO: check this<br>
>>> - (*it)->printPretty(OS, Policy);<br>
>>> }<br>
>>> - OS << "]] ";<br>
>>> +<br>
>>> + // Check to see if any attributes were printed.<br>
>>> + StringRef AttrStr = AttrOS.str();<br>
>>> + if (!AttrStr.empty())<br>
>>> + OS << "[[" << AttrStr << "]] ";<br>
>>> +<br>
>>> PrintStmt(Node->getSubStmt(), 0);<br>
>>> }<br>
>>><br>
>>> Index: lib/CodeGen/CGStmt.cpp<br>
>>> ===================================================================<br>
>>> --- lib/CodeGen/CGStmt.cpp (revision 208638)<br>
>>> +++ lib/CodeGen/CGStmt.cpp (working copy)<br>
>>> @@ -18,6 +18,7 @@<br>
>>> #include "clang/AST/StmtVisitor.h"<br>
>>> #include "clang/Basic/PrettyStackTrace.h"<br>
>>> #include "clang/Basic/TargetInfo.h"<br>
>>> +#include "clang/Sema/LoopHint.h"<br>
>>> #include "clang/Sema/SemaDiagnostic.h"<br>
>>> #include "llvm/ADT/StringExtras.h"<br>
>>> #include "llvm/IR/CallSite.h"<br>
>>> @@ -396,7 +397,23 @@<br>
>>> }<br>
>>><br>
>>> void CodeGenFunction::EmitAttributedStmt(const AttributedStmt &S) {<br>
>>> - EmitStmt(S.getSubStmt());<br>
>>> + const Stmt *SubStmt = S.getSubStmt();<br>
>>> + switch (SubStmt->getStmtClass()) {<br>
>>> + case Stmt::DoStmtClass:<br>
>>> + EmitDoStmt(cast<DoStmt>(*SubStmt), S.getAttrs());<br>
>>> + break;<br>
>>> + case Stmt::ForStmtClass:<br>
>>> + EmitForStmt(cast<ForStmt>(*SubStmt), S.getAttrs());<br>
>>> + break;<br>
>>> + case Stmt::WhileStmtClass:<br>
>>> + EmitWhileStmt(cast<WhileStmt>(*SubStmt), S.getAttrs());<br>
>>> + break;<br>
>>> + case Stmt::CXXForRangeStmtClass:<br>
>>> + EmitCXXForRangeStmt(cast<CXXForRangeStmt>(*SubStmt), S.getAttrs());<br>
>>> + break;<br>
>>> + default:<br>
>>> + EmitStmt(SubStmt);<br>
>>> + }<br>
>>> }<br>
>>><br>
>>> void CodeGenFunction::EmitGotoStmt(const GotoStmt &S) {<br>
>>> @@ -502,7 +519,57 @@<br>
>>> EmitBlock(ContBlock, true);<br>
>>> }<br>
>>><br>
>>> -void CodeGenFunction::EmitWhileStmt(const WhileStmt &S) {<br>
>>> +void CodeGenFunction::EmitCondBrHints(llvm::LLVMContext &Context,<br>
>>> + llvm::BranchInst *CondBr,<br>
>>> + ArrayRef<const Attr *> &Attrs) {<br>
>>> + // Do not continue if there are not hints.<br>
>>> + if (Attrs.empty())<br>
>>> + return;<br>
>>> +<br>
>>> + // Add vectorize hints to the metadata on the conditional branch.<br>
>>> + // Iterate in reverse so hints are put in the same order they appear.<br>
>>> + SmallVector<llvm::Value*, 2> Metadata(1);<br>
>>> + for (auto I = Attrs.rbegin(), E = Attrs.rend(); I != E; ++I) {<br>
>>> + const LoopHintAttr *LH = dyn_cast<LoopHintAttr>(*I);<br>
>>> +<br>
>>> + // Skip non loop hint attributes<br>
>>> + if (!LH)<br>
>>> + continue;<br>
>>> +<br>
>>> + LoopHintAttr::OptionType Option = LH->getOption();<br>
>>> + int ValueInt = LH->getValue();<br>
>>> + int Kind = LH->getKind();<br>
>>> +<br>
>>> + llvm::Value *Value;<br>
>>> + llvm::MDString *Name;<br>
>>> + const char *MetadataNames[] = { "llvm.vectorizer.width",<br>
>>> + "llvm.vectorizer.unroll" };<br>
>>> + if (Kind == LoopHintAttr::Enable) {<br>
>>> + Name = llvm::MDString::get(Context, "llvm.vectorizer.enable");<br>
>>> + Value = Builder.getTrue();<br>
>>> + } else {<br>
>>> + // No need for the disable case because ValueInt is 1 if Kind is disable.<br>
>>> + Name = llvm::MDString::get(Context, MetadataNames[Option]);<br>
>>> + Value = llvm::ConstantInt::get(Int32Ty, ValueInt);<br>
>>> + }<br>
>>> +<br>
>>> + SmallVector<llvm::Value*, 2> OpValues;<br>
>>> + OpValues.push_back(Name);<br>
>>> + OpValues.push_back(Value);<br>
>>> +<br>
>>> + // Set or overwrite metadata indicated by Name.<br>
>>> + Metadata.push_back(llvm::MDNode::get(Context, OpValues));<br>
>>> + }<br>
>>> +<br>
>>> + // Add llvm.loop MDNode to CondBr.<br>
>>> + llvm::MDNode *LoopID = llvm::MDNode::get(Context, Metadata);<br>
>>> + LoopID->replaceOperandWith(0, LoopID); // First op points to itself.<br>
>>> +<br>
>>> + CondBr->setMetadata("llvm.loop", LoopID);<br>
>>> +}<br>
>>> +<br>
>>> +void CodeGenFunction::EmitWhileStmt(const WhileStmt &S,<br>
>>> + ArrayRef<const Attr *> WhileAttrs) {<br>
>>> RegionCounter Cnt = getPGORegionCounter(&S);<br>
>>><br>
>>> // Emit the header for the loop, which will also become<br>
>>> @@ -547,13 +614,17 @@<br>
>>> llvm::BasicBlock *ExitBlock = LoopExit.getBlock();<br>
>>> if (ConditionScope.requiresCleanups())<br>
>>> ExitBlock = createBasicBlock("while.exit");<br>
>>> - Builder.CreateCondBr(BoolCondVal, LoopBody, ExitBlock,<br>
>>> - PGO.createLoopWeights(S.getCond(), Cnt));<br>
>>> + llvm::BranchInst *CondBr = Builder.CreateCondBr(<br>
>>> + BoolCondVal, LoopBody, ExitBlock,<br>
>>> + PGO.createLoopWeights(S.getCond(), Cnt));<br>
>><br>
>> Formatting.<br>
>><br>
>>><br>
>>> if (ExitBlock != LoopExit.getBlock()) {<br>
>>> EmitBlock(ExitBlock);<br>
>>> EmitBranchThroughCleanup(LoopExit);<br>
>>> }<br>
>>> +<br>
>>> + // Attach metadata to loop body conditional branch.<br>
>>> + EmitCondBrHints(LoopBody->getContext(), CondBr, WhileAttrs);<br>
>>> }<br>
>>><br>
>>> // Emit the loop body. We have to emit this in a cleanup scope<br>
>>> @@ -582,7 +653,8 @@<br>
>>> SimplifyForwardingBlocks(LoopHeader.getBlock());<br>
>>> }<br>
>>><br>
>>> -void CodeGenFunction::EmitDoStmt(const DoStmt &S) {<br>
>>> +void CodeGenFunction::EmitDoStmt(const DoStmt &S,<br>
>>> + ArrayRef<const Attr *> DoAttrs) {<br>
>>> JumpDest LoopExit = getJumpDestInCurrentScope("do.end");<br>
>>> JumpDest LoopCond = getJumpDestInCurrentScope("do.cond");<br>
>>><br>
>>> @@ -619,10 +691,15 @@<br>
>>> EmitBoolCondBranch = false;<br>
>>><br>
>>> // As long as the condition is true, iterate the loop.<br>
>>> - if (EmitBoolCondBranch)<br>
>>> - Builder.CreateCondBr(BoolCondVal, LoopBody, LoopExit.getBlock(),<br>
>>> - PGO.createLoopWeights(S.getCond(), Cnt));<br>
>>> + if (EmitBoolCondBranch) {<br>
>>> + llvm::BranchInst *CondBr = Builder.CreateCondBr(<br>
>>> + BoolCondVal, LoopBody, LoopExit.getBlock(),<br>
>>> + PGO.createLoopWeights(S.getCond(), Cnt));<br>
>><br>
>> Formatting.<br>
>><br>
>>><br>
>>> + // Attach metadata to loop body conditional branch.<br>
>>> + EmitCondBrHints(LoopBody->getContext(), CondBr, DoAttrs);<br>
>>> + }<br>
>>> +<br>
>>> // Emit the exit block.<br>
>>> EmitBlock(LoopExit.getBlock());<br>
>>><br>
>>> @@ -632,7 +709,8 @@<br>
>>> SimplifyForwardingBlocks(LoopCond.getBlock());<br>
>>> }<br>
>>><br>
>>> -void CodeGenFunction::EmitForStmt(const ForStmt &S) {<br>
>>> +void CodeGenFunction::EmitForStmt(const ForStmt &S,<br>
>>> + ArrayRef<const Attr *> ForAttrs) {<br>
>>> JumpDest LoopExit = getJumpDestInCurrentScope("for.end");<br>
>>><br>
>>> RunCleanupsScope ForScope(*this);<br>
>>> @@ -686,9 +764,13 @@<br>
>>> // C99 6.8.5p2/p4: The first substatement is executed if the expression<br>
>>> // compares unequal to 0. The condition must be a scalar type.<br>
>>> llvm::Value *BoolCondVal = EvaluateExprAsBool(S.getCond());<br>
>>> - Builder.CreateCondBr(BoolCondVal, ForBody, ExitBlock,<br>
>>> - PGO.createLoopWeights(S.getCond(), Cnt));<br>
>>> + llvm::BranchInst *CondBr = Builder.CreateCondBr(<br>
>>> + BoolCondVal, ForBody, ExitBlock,<br>
>>> + PGO.createLoopWeights(S.getCond(), Cnt));<br>
>>><br>
>>> + // Attach metadata to loop body conditional branch.<br>
>>> + EmitCondBrHints(ForBody->getContext(), CondBr, ForAttrs);<br>
>>> +<br>
>>> if (ExitBlock != LoopExit.getBlock()) {<br>
>>> EmitBlock(ExitBlock);<br>
>>> EmitBranchThroughCleanup(LoopExit);<br>
>>> @@ -728,7 +810,8 @@<br>
>>> EmitBlock(LoopExit.getBlock(), true);<br>
>>> }<br>
>>><br>
>>> -void CodeGenFunction::EmitCXXForRangeStmt(const CXXForRangeStmt &S) {<br>
>>> +void CodeGenFunction::EmitCXXForRangeStmt(const CXXForRangeStmt &S,<br>
>>> + ArrayRef<const Attr *> ForAttrs) {<br>
>>> JumpDest LoopExit = getJumpDestInCurrentScope("for.end");<br>
>>><br>
>>> RunCleanupsScope ForScope(*this);<br>
>>> @@ -761,9 +844,13 @@<br>
>>> // The body is executed if the expression, contextually converted<br>
>>> // to bool, is true.<br>
>>> llvm::Value *BoolCondVal = EvaluateExprAsBool(S.getCond());<br>
>>> - Builder.CreateCondBr(BoolCondVal, ForBody, ExitBlock,<br>
>>> - PGO.createLoopWeights(S.getCond(), Cnt));<br>
>>> + llvm::BranchInst *CondBr = Builder.CreateCondBr(BoolCondVal, ForBody,<br>
>>> + ExitBlock,<br>
>>> + PGO.createLoopWeights(S.getCond(), Cnt));<br>
>><br>
>> Formatting.<br>
>><br>
>>><br>
>>> + // Attach metadata to loop body conditional branch<br>
>>> + EmitCondBrHints(ForBody->getContext(), CondBr, ForAttrs);<br>
>>> +<br>
>>> if (ExitBlock != LoopExit.getBlock()) {<br>
>>> EmitBlock(ExitBlock);<br>
>>> EmitBranchThroughCleanup(LoopExit);<br>
>>> Index: lib/CodeGen/CodeGenFunction.h<br>
>>> ===================================================================<br>
>>> --- lib/CodeGen/CodeGenFunction.h (revision 208638)<br>
>>> +++ lib/CodeGen/CodeGenFunction.h (working copy)<br>
>>> @@ -1846,9 +1846,16 @@<br>
>>> void EmitGotoStmt(const GotoStmt &S);<br>
>>> void EmitIndirectGotoStmt(const IndirectGotoStmt &S);<br>
>>> void EmitIfStmt(const IfStmt &S);<br>
>>> - void EmitWhileStmt(const WhileStmt &S);<br>
>>> - void EmitDoStmt(const DoStmt &S);<br>
>>> - void EmitForStmt(const ForStmt &S);<br>
>>> +<br>
>>> + void EmitCondBrHints(llvm::LLVMContext &Context,<br>
>>> + llvm::BranchInst *CondBr,<br>
>>> + ArrayRef<const Attr *> &Attrs);<br>
>>> + void EmitWhileStmt(const WhileStmt &S,<br>
>>> + ArrayRef<const Attr *> Attrs = ArrayRef<const Attr *>());<br>
>>> + void EmitDoStmt(const DoStmt &S,<br>
>>> + ArrayRef<const Attr *> Attrs = ArrayRef<const Attr *>());<br>
>>> + void EmitForStmt(const ForStmt &S,<br>
>>> + ArrayRef<const Attr *> Attrs = ArrayRef<const Attr *>());<br>
>>> void EmitReturnStmt(const ReturnStmt &S);<br>
>>> void EmitDeclStmt(const DeclStmt &S);<br>
>>> void EmitBreakStmt(const BreakStmt &S);<br>
>>> @@ -1872,7 +1879,8 @@<br>
>>><br>
>>> void EmitCXXTryStmt(const CXXTryStmt &S);<br>
>>> void EmitSEHTryStmt(const SEHTryStmt &S);<br>
>>> - void EmitCXXForRangeStmt(const CXXForRangeStmt &S);<br>
>>> + void EmitCXXForRangeStmt(const CXXForRangeStmt &S,<br>
>>> + ArrayRef<const Attr *> Attrs = ArrayRef<const Attr *>());<br>
>><br>
>> Formatting.<br>
>><br>
>>><br>
>>> llvm::Function *EmitCapturedStmt(const CapturedStmt &S, CapturedRegionKind K);<br>
>>> llvm::Function *GenerateCapturedStmtFunction(const CapturedDecl *CD,<br>
>>> Index: lib/Parse/ParsePragma.cpp<br>
>>> ===================================================================<br>
>>> --- lib/Parse/ParsePragma.cpp (revision 208638)<br>
>>> +++ lib/Parse/ParsePragma.cpp (working copy)<br>
>>> @@ -15,6 +15,7 @@<br>
>>> #include "clang/Lex/Preprocessor.h"<br>
>>> #include "clang/Parse/ParseDiagnostic.h"<br>
>>> #include "clang/Parse/Parser.h"<br>
>>> +#include "clang/Sema/LoopHint.h"<br>
>>> #include "clang/Sema/Scope.h"<br>
>>> #include "llvm/ADT/StringSwitch.h"<br>
>>> using namespace clang;<br>
>>> @@ -131,6 +132,12 @@<br>
>>> Token &FirstToken) override;<br>
>>> };<br>
>>><br>
>>> +struct PragmaLoopHintHandler : public PragmaHandler {<br>
>>> + PragmaLoopHintHandler() : PragmaHandler("loop") {}<br>
>>> + void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,<br>
>>> + Token &FirstToken) override;<br>
>>> +};<br>
>>> +<br>
>>> } // end namespace<br>
>>><br>
>>> void Parser::initializePragmaHandlers() {<br>
>>> @@ -195,6 +202,9 @@<br>
>>> MSSection.reset(new PragmaMSPragma("section"));<br>
>>> PP.AddPragmaHandler(MSSection.get());<br>
>>> }<br>
>>> +<br>
>>> + LoopHintHandler.reset(new PragmaLoopHintHandler());<br>
>>> + PP.AddPragmaHandler(LoopHintHandler.get());<br>
>>> }<br>
>>><br>
>>> void Parser::resetPragmaHandlers() {<br>
>>> @@ -249,6 +259,10 @@<br>
>>><br>
>>> PP.RemovePragmaHandler("STDC", FPContractHandler.get());<br>
>>> FPContractHandler.reset();<br>
>>> +<br>
>>> + PP.RemovePragmaHandler(LoopHintHandler.get());<br>
>>> + LoopHintHandler.reset();<br>
>>> +<br>
>>> }<br>
>>><br>
>>> /// \brief Handle the annotation token produced for #pragma unused(...)<br>
>>> @@ -570,6 +584,40 @@<br>
>>> DiagnosticsEngine::Error, "'#pragma %0' not implemented.");<br>
>>> }<br>
>>><br>
>>> +struct PragmaLoopHintInfo {<br>
>>> + Token Loop;<br>
>>> + Token Value;<br>
>>> + Token Option;<br>
>>> +};<br>
>>> +<br>
>>> +LoopHint Parser::HandlePragmaLoopHint() {<br>
>>> + assert(Tok.is(tok::annot_pragma_loop_hint));<br>
>>> + PragmaLoopHintInfo *Info =<br>
>>> + static_cast<PragmaLoopHintInfo *>(Tok.getAnnotationValue());<br>
>>> +<br>
>>> + LoopHint Hint;<br>
>>> + Hint.LoopLoc = IdentifierLoc::create(Actions.Context,<br>
>>> + Info->Loop.getLocation(),<br>
>>> + Info->Loop.getIdentifierInfo());<br>
>>> + Hint.OptionLoc = IdentifierLoc::create(Actions.Context,<br>
>>> + Info->Option.getLocation(),<br>
>>> + Info->Option.getIdentifierInfo());<br>
>>> + Hint.ValueLoc = IdentifierLoc::create(Actions.Context,<br>
>>> + Info->Value.getLocation(),<br>
>>> + Info->Value.getIdentifierInfo());<br>
>>> + Hint.Range = SourceRange(Info->Option.getLocation(),<br>
>>> + Info->Value.getLocation());<br>
>>> +<br>
>>> + // FIXME: We should support template parameters for the loop hint value.<br>
>>> + // See bug report #19610<br>
>>> + if (Info->Value.is(tok::numeric_constant))<br>
>>> + Hint.ValueExpr = Actions.ActOnNumericConstant(Info->Value).get();<br>
>>> + else<br>
>>> + Hint.ValueExpr = nullptr;<br>
>>> +<br>
>>> + return Hint;<br>
>>> +}<br>
>>> +<br>
>>> // #pragma GCC visibility comes in two variants:<br>
>>> // 'push' '(' [visibility] ')'<br>
>>> // 'pop'<br>
>>> @@ -1531,3 +1579,108 @@<br>
>>><br>
>>> Actions.ActOnPragmaMSComment(Kind, ArgumentString);<br>
>>> }<br>
>>> +<br>
>>> +/// \brief Handle the \#pragma vectorize hint.<br>
>>> +/// #pragma 'loop' loop-hints<br>
>>> +///<br>
>>> +/// loop-hints:<br>
>>> +/// loop-hint loop-hints[opt]<br>
>>> +///<br>
>>> +/// loop-hint:<br>
>>> +/// 'vectorize' '(' loop-hint-value ')'<br>
>>> +/// 'interleave' '(' loop-hint-value ')'<br>
>>> +///<br>
>>> +/// loop-hint-value:<br>
>>> +/// 'enable'<br>
>>> +/// 'disable'<br>
>>> +/// constant-expression<br>
>>> +///<br>
>>> +/// Specifying vectorize(enable) or vectorize(_value_) instructs llvm to<br>
>>> +/// try vectorizing the instructions of the loop it precedes. Specifying<br>
>>> +/// interleave(enable) or interleave(_value_) instructs llvm to try interleaving<br>
>>> +/// multiple iterations of the loop it precedes. The _value_ indicates the<br>
>>> +/// width of the vector instructions or the number of iterations of the loop<br>
>>> +/// that should be interleaved. Consequently, a value of 1 or disable prevents<br>
>>> +/// the optimization, even if it is possible and profitable, and 0 is invalid.<br>
>>> +/// The loop vectorizer currently only works on inner loops.<br>
>>> +///<br>
>>> +void PragmaLoopHintHandler::HandlePragma(Preprocessor &PP,<br>
>>> + PragmaIntroducerKind Introducer,<br>
>>> + Token &Tok) {<br>
>>> + Token Loop = Tok;<br>
>>> + SmallVector <Token, 1> TokenList;<br>
>>> +<br>
>>> + // Lex the optimization option and verify it is an identifier.<br>
>>> + PP.Lex(Tok);<br>
>>> + if (Tok.isNot(tok::identifier)) {<br>
>>> + PP.Diag(Tok.getLocation(), diag::err_pragma_loop_invalid_option)<br>
>>> + << /*InvalidOption*/true << "";<br>
>>> + return;<br>
>>> + }<br>
>>> +<br>
>>> + while(Tok.is(tok::identifier)) {<br>
>>> + Token Option = Tok;<br>
>>> + StringRef OptionName = Tok.getIdentifierInfo()->getName();<br>
>>> +<br>
>>> + if (OptionName != "vectorize" && OptionName != "interleave") {<br>
>>> + PP.Diag(Tok.getLocation(), diag::err_pragma_loop_invalid_option)<br>
>>> + << /*InvalidOption*/false << OptionName;<br>
>>> + return;<br>
>>> + }<br>
>>> +<br>
>>> + // Read '('<br>
>>> + PP.Lex(Tok);<br>
>>> + if (Tok.isNot(tok::l_paren)) {<br>
>>> + PP.Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren;<br>
>>> + return;<br>
>>> + }<br>
>>> +<br>
>>> + PP.Lex(Tok);<br>
>>> + if (Tok.isNot(tok::identifier) && Tok.isNot(tok::numeric_constant)) {<br>
>>> + PP.Diag(Tok.getLocation(), diag::err_pragma_loop_invalid_type)<br>
>>> + << Tok.getName();<br>
>>> + return;<br>
>>> + }<br>
>>> +<br>
>>> + Token Value = Tok;<br>
>>> +<br>
>>> + // Read ')'<br>
>>> + PP.Lex(Tok);<br>
>>> + if (Tok.isNot(tok::r_paren)) {<br>
>>> + PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;<br>
>>> + return;<br>
>>> + }<br>
>>> +<br>
>>> + // Get next optimization option.<br>
>>> + PP.Lex(Tok);<br>
>>> +<br>
>>> + PragmaLoopHintInfo *Info =<br>
>>> + (PragmaLoopHintInfo*) PP.getPreprocessorAllocator().Allocate(<br>
>>> + sizeof(PragmaLoopHintInfo), llvm::alignOf<PragmaLoopHintInfo>());<br>
>>> +<br>
>>> + Info->Loop = Loop;<br>
>>> + Info->Option = Option;<br>
>>> + Info->Value = Value;<br>
>>> +<br>
>>> + // Generate the vectorization hint token.<br>
>>> + Token LoopHintTok;<br>
>>> + LoopHintTok.startToken();<br>
>>> + LoopHintTok.setKind(tok::annot_pragma_loop_hint);<br>
>>> + LoopHintTok.setLocation(Loop.getLocation());<br>
>>> + LoopHintTok.setAnnotationValue(static_cast<void*>(Info));<br>
>>> + TokenList.push_back(LoopHintTok);<br>
>>> + }<br>
>>> +<br>
>>> + if (Tok.isNot(tok::eod)) {<br>
>>> + PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)<br>
>>> + << "loop";<br>
>>> + return;<br>
>>> + }<br>
>>> +<br>
>>> + Token *TokenArray = new Token[TokenList.size()];<br>
>>> + std::copy(TokenList.begin(), TokenList.end(), TokenArray);<br>
>>> +<br>
>>> + PP.EnterTokenStream(TokenArray, TokenList.size(),<br>
>>> + /*DisableMacroExpansion=*/false,<br>
>>> + /*OwnsTokens=*/true);<br>
>>> +}<br>
>>> Index: lib/Parse/ParseStmt.cpp<br>
>>> ===================================================================<br>
>>> --- lib/Parse/ParseStmt.cpp (revision 208638)<br>
>>> +++ lib/Parse/ParseStmt.cpp (working copy)<br>
>>> @@ -15,11 +15,13 @@<br>
>>> #include "clang/Parse/Parser.h"<br>
>>> #include "RAIIObjectsForParser.h"<br>
>>> #include "clang/AST/ASTContext.h"<br>
>>> +#include "clang/Basic/Attributes.h"<br>
>>> #include "clang/Basic/Diagnostic.h"<br>
>>> #include "clang/Basic/PrettyStackTrace.h"<br>
>>> #include "clang/Basic/SourceManager.h"<br>
>>> #include "clang/Basic/TargetInfo.h"<br>
>>> #include "clang/Sema/DeclSpec.h"<br>
>>> +#include "clang/Sema/LoopHint.h"<br>
>>> #include "clang/Sema/PrettyDeclStackTrace.h"<br>
>>> #include "clang/Sema/Scope.h"<br>
>>> #include "clang/Sema/TypoCorrection.h"<br>
>>> @@ -357,6 +359,10 @@<br>
>>> ProhibitAttributes(Attrs);<br>
>>> HandlePragmaMSPragma();<br>
>>> return StmtEmpty();<br>
>>> +<br>
>>> + case tok::annot_pragma_loop_hint:<br>
>>> + ProhibitAttributes(Attrs);<br>
>>> + return ParsePragmaLoopHint(Stmts, OnlyStatement, TrailingElseLoc, Attrs);<br>
>>> }<br>
>>><br>
>>> // If we reached this code, the statement must end in a semicolon.<br>
>>> @@ -1751,6 +1757,43 @@<br>
>>> return Actions.ActOnReturnStmt(ReturnLoc, R.take(), getCurScope());<br>
>>> }<br>
>>><br>
>>> +StmtResult Parser::ParsePragmaLoopHint(StmtVector &Stmts,<br>
>>> + bool OnlyStatement,<br>
>>> + SourceLocation *TrailingElseLoc,<br>
>>> + ParsedAttributesWithRange &Attrs) {<br>
>>> + // Create temporary attribute list.<br>
>>> + ParsedAttributesWithRange TempAttrs(AttrFactory);<br>
>>> +<br>
>>> + // Get vectorize hints and consume annotated token.<br>
>>> + while (Tok.is(tok::annot_pragma_loop_hint)) {<br>
>>> + LoopHint Hint = HandlePragmaLoopHint();<br>
>>> + ConsumeToken();<br>
>>> +<br>
>>> + if (!Hint.LoopLoc ||<br>
>>> + !Hint.OptionLoc ||<br>
>>> + !Hint.ValueLoc)<br>
>>> + continue;<br>
>>> +<br>
>>> + ArgsUnion ArgHints[] = {Hint.OptionLoc,<br>
>>> + Hint.ValueLoc,<br>
>>> + ArgsUnion(Hint.ValueExpr)};<br>
>>> + // FIXME: Replace AS_Keyword with Pragma spelling AS_Pragma.<br>
>>> + TempAttrs.addNew(Hint.LoopLoc->Ident, Hint.Range,<br>
>>> + 0, Hint.LoopLoc->Loc,<br>
>>> + ArgHints, 3,<br>
>>> + AttributeList::AS_Keyword);<br>
>>> + }<br>
>>> +<br>
>>> + // Get the next statement.<br>
>>> + MaybeParseCXX11Attributes(Attrs);<br>
>>> +<br>
>>> + StmtResult S = ParseStatementOrDeclarationAfterAttributes(Stmts,<br>
>>> + OnlyStatement, TrailingElseLoc, Attrs);<br>
>>> +<br>
>>> + Attrs.takeAllFrom(TempAttrs);<br>
>>> + return S;<br>
>>> +}<br>
>>> +<br>
>>> namespace {<br>
>>> class ClangAsmParserCallback : public llvm::MCAsmParserSemaCallback {<br>
>>> Parser &TheParser;<br>
>>> Index: lib/Sema/SemaStmtAttr.cpp<br>
>>> ===================================================================<br>
>>> --- lib/Sema/SemaStmtAttr.cpp (revision 208638)<br>
>>> +++ lib/Sema/SemaStmtAttr.cpp (working copy)<br>
>>> @@ -16,6 +16,7 @@<br>
>>> #include "clang/Basic/SourceManager.h"<br>
>>> #include "clang/Sema/DelayedDiagnostic.h"<br>
>>> #include "clang/Sema/Lookup.h"<br>
>>> +#include "clang/Sema/LoopHint.h"<br>
>>> #include "clang/Sema/ScopeInfo.h"<br>
>>> #include "llvm/ADT/StringExtras.h"<br>
>>><br>
>>> @@ -42,7 +43,83 @@<br>
>>> A.getAttributeSpellingListIndex());<br>
>>> }<br>
>>><br>
>>> +static Attr *handleLoopHintAttr(Sema &S, Stmt *St, const AttributeList &A,<br>
>>> + SourceRange Range) {<br>
>>> + if (St->getStmtClass() != Stmt::DoStmtClass &&<br>
>>> + St->getStmtClass() != Stmt::ForStmtClass &&<br>
>>> + St->getStmtClass() != Stmt::CXXForRangeStmtClass &&<br>
>>> + St->getStmtClass() != Stmt::WhileStmtClass) {<br>
>>> + S.Diag(St->getLocStart(), diag::err_pragma_loop_precedes_nonloop);<br>
>>> + return nullptr;<br>
>>> + }<br>
>>><br>
>>> + IdentifierLoc *OptionLoc = A.getArgAsIdent(0);<br>
>>> + IdentifierInfo *OptionInfo = OptionLoc->Ident;<br>
>>> + IdentifierLoc *ValueLoc = A.getArgAsIdent(1);<br>
>>> + IdentifierInfo *ValueInfo = ValueLoc->Ident;<br>
>>> + Expr *ValueExpr = A.getArgAsExpr(2);<br>
>>> +<br>
>>> + assert(OptionInfo && "Attribute must have valid option info.");<br>
>>> +<br>
>>> + LoopHintAttr::OptionType Option = LoopHintAttr::Vectorize;<br>
>>> + if (OptionInfo->getName() == "vectorize")<br>
>>> + Option = LoopHintAttr::Vectorize;<br>
>>> + else if (OptionInfo->getName() == "interleave")<br>
>>> + Option = LoopHintAttr::Interleave;<br>
>>> +<br>
>>> + LoopHintAttr::KindType Kind = LoopHintAttr::Value;<br>
>>> + if (ValueInfo && ValueInfo->getName() == "enable")<br>
>>> + Kind = LoopHintAttr::Enable;<br>
>>> + else if (ValueInfo && ValueInfo->getName() == "disable")<br>
>>> + Kind = LoopHintAttr::Disable;<br>
>>> +<br>
>>> + // FIXME: We should support template parameters for the loop hint value.<br>
>>> + // See bug report #19610<br>
>>> + int ValueInt = 1; // No vectorization/interleaving when kind set to disable.<br>
>>> + if (Kind == LoopHintAttr::Value) {<br>
>>> + llvm::APSInt ValueAPS;<br>
>>> + if(!ValueExpr ||<br>
>>> + !ValueExpr->isIntegerConstantExpr(ValueAPS, S.Context) ||<br>
>>> + (ValueInt = ValueAPS.getSExtValue()) < 1) {<br>
>>> + S.Diag(ValueLoc->Loc, diag::err_pragma_loop_invalid_value)<br>
>>> + << LoopHintAttr::getOptionName(Option);<br>
>>> + return nullptr;<br>
>>> + }<br>
>>> + }<br>
>>> +<br>
>>> + return LoopHintAttr::CreateImplicit(S.Context,<br>
>>> + Option, Kind, ValueInt, A.getRange());<br>
>>> +}<br>
>>> +<br>
>>> +static void CheckForIncompatibleAttributes(Sema &S,<br>
>>> + SmallVectorImpl<const Attr*> &Attrs) {<br>
>><br>
>> Formatting.<br>
>><br>
>>> + int PrevKind[2] = {-1, -1};<br>
>>> +<br>
>>> + // FIXME: Attrs are stored in the reverse order than they appear.<br>
>>> + for (auto I = Attrs.rbegin(), E = Attrs.rend(); I != E; ++I) {<br>
>>> + const LoopHintAttr *LH = dyn_cast<LoopHintAttr>(*I);<br>
>>> +<br>
>>> + // Skip non loop hint attributes<br>
>>> + if (!LH)<br>
>>> + continue;<br>
>>> +<br>
>>> + int Option = LH->getOption();<br>
>>> + int Kind = LH->getKind();<br>
>>> + SourceLocation ValueLoc = LH->getRange().getEnd();<br>
>>> +<br>
>>> + // We only need to check that a loop hint is compatible with the<br>
>>> + // previous loop hint to ensure that all hints are compatible.<br>
>>> + if (PrevKind[Option] != -1 &&<br>
>>> + !LoopHintAttr::isCompatible(PrevKind[Option], Kind)) {<br>
>>> + S.Diag(ValueLoc, diag::err_pragma_loop_incompatible)<br>
>>> + << LoopHintAttr::getKindName(PrevKind[Option])<br>
>>> + << LoopHintAttr::getKindName(Kind)<br>
>>> + << LoopHintAttr::getOptionName(Option);<br>
>>> + }<br>
>>> + PrevKind[Option] = Kind;<br>
>>> + }<br>
>>> +}<br>
>>> +<br>
>>> static Attr *ProcessStmtAttribute(Sema &S, Stmt *St, const AttributeList &A,<br>
>>> SourceRange Range) {<br>
>>> switch (A.getKind()) {<br>
>>> @@ -53,6 +130,8 @@<br>
>>> return 0;<br>
>>> case AttributeList::AT_FallThrough:<br>
>>> return handleFallThroughAttr(S, St, A, Range);<br>
>>> + case AttributeList::AT_LoopHint:<br>
>>> + return handleLoopHintAttr(S, St, A, Range);<br>
>>> default:<br>
>>> // if we're here, then we parsed a known attribute, but didn't recognize<br>
>>> // it as a statement attribute => it is declaration attribute<br>
>>> @@ -65,11 +144,14 @@<br>
>>> StmtResult Sema::ProcessStmtAttributes(Stmt *S, AttributeList *AttrList,<br>
>>> SourceRange Range) {<br>
>>> SmallVector<const Attr*, 8> Attrs;<br>
>>> + // FIXME: Attrs are stored in the reverse order than they appear.<br>
>>> for (const AttributeList* l = AttrList; l; l = l->getNext()) {<br>
>>> if (Attr *a = ProcessStmtAttribute(*this, S, *l, Range))<br>
>>> Attrs.push_back(a);<br>
>>> }<br>
>>><br>
>>> + CheckForIncompatibleAttributes(*this, Attrs);<br>
>>> +<br>
>>> if (Attrs.empty())<br>
>>> return S;<br>
>>><br>
>>> Index: test/CodeGen/pragma-loop.cpp<br>
>>> ===================================================================<br>
>>> --- test/CodeGen/pragma-loop.cpp (revision 0)<br>
>>> +++ test/CodeGen/pragma-loop.cpp (working copy)<br>
>>> @@ -0,0 +1,120 @@<br>
>>> +// RUN: %clang_cc1 -std=c++11 -emit-llvm -o - %s | FileCheck %s<br>
>>> +<br>
>>> +// CHECK: br i1 %cmp, label %while.body, label %while.end, !llvm.loop !1<br>
>>> +// CHECK: br i1 %cmp, label %do.body, label %do.end, !llvm.loop !5<br>
>>> +// CHECK: br i1 %cmp, label %for.body, label %for.end, !llvm.loop !7<br>
>>> +// CHECK: br i1 %cmp, label %for.body, label %for.end, !llvm.loop !8<br>
>>> +// CHECK: br i1 %cmp, label %for.body, label %for.end, !llvm.loop !11<br>
>>> +// CHECK: br i1 %cmp, label %for.body, label %for.end, !llvm.loop !13<br>
>>> +// CHECK: br i1 %cmp, label %for.body, label %for.end, !llvm.loop !14<br>
>>> +// CHECK: br i1 %cmp, label %for.body, label %for.end, !llvm.loop !16<br>
>>> +<br>
>>> +// CHECK: !1 = metadata !{metadata !1, metadata !2, metadata !3, metadata !4}<br>
>>> +// CHECK: !2 = metadata !{metadata !"llvm.vectorizer.enable", i1 true}<br>
>>> +// CHECK: !3 = metadata !{metadata !"llvm.vectorizer.unroll", i32 4}<br>
>>> +// CHECK: !4 = metadata !{metadata !"llvm.vectorizer.width", i32 4}<br>
>>> +// CHECK: !5 = metadata !{metadata !5, metadata !6, metadata !3}<br>
>>> +// CHECK: !6 = metadata !{metadata !"llvm.vectorizer.width", i32 8}<br>
>>> +// CHECK: !7 = metadata !{metadata !7, metadata !2, metadata !3}<br>
>>> +// CHECK: !8 = metadata !{metadata !8, metadata !9, metadata !10}<br>
>>> +// CHECK: !9 = metadata !{metadata !"llvm.vectorizer.width", i32 2}<br>
>>> +// CHECK: !10 = metadata !{metadata !"llvm.vectorizer.unroll", i32 2}<br>
>>> +// CHECK: !11 = metadata !{metadata !11, metadata !12}<br>
>>> +// CHECK: !12 = metadata !{metadata !"llvm.vectorizer.width", i32 1}<br>
>>> +// CHECK: !13 = metadata !{metadata !13, metadata !9, metadata !10}<br>
>>> +// CHECK: !14 = metadata !{metadata !14, metadata !6, metadata !15}<br>
>>> +// CHECK: !15 = metadata !{metadata !"llvm.vectorizer.unroll", i32 8}<br>
>>> +// CHECK: !16 = metadata !{metadata !16, metadata !9, metadata !10}<br>
>>> +<br>
>>> +// Verify while loop is recognized after sequence of pragma loop directives.<br>
>>> +void while_test(int *List, int Length) {<br>
>>> + int i = 0;<br>
>>> +<br>
>>> + #pragma loop vectorize(enable)<br>
>>> + #pragma loop interleave(4)<br>
>>> + #pragma loop vectorize(4)<br>
>>> + while(i < Length) {<br>
>>> + List[i] = i*2;<br>
>>> + i++;<br>
>>> + }<br>
>>> +}<br>
>>> +<br>
>>> +// Verify do loop is recognized after multi-option pragma loop directive.<br>
>>> +void do_test(int *List, int Length) {<br>
>>> + int i = 0;<br>
>>> +<br>
>>> + #pragma loop vectorize(8) interleave(4)<br>
>>> + do {<br>
>>> + List[i] = i*2;<br>
>>> + i++;<br>
>>> + } while (i < Length);<br>
>>> +}<br>
>>> +<br>
>>> +// Verify for loop is recognized after sequence of pragma loop directives.<br>
>>> +void for_test(int *List, int Length) {<br>
>>> + #pragma loop interleave(enable)<br>
>>> + #pragma loop interleave(4)<br>
>>> + for(int i = 0; i < Length; i++) {<br>
>>> + List[i] = i*2;<br>
>>> + }<br>
>>> +}<br>
>>> +<br>
>>> +// Verify c++11 for range loop is recognized after<br>
>>> +// sequence of pragma loop directives.<br>
>>> +void for_range_test() {<br>
>>> + double List[100];<br>
>>> +<br>
>>> + #pragma loop vectorize(2) interleave(2)<br>
>>> + for (int i : List) {<br>
>>> + List[i] = i;<br>
>>> + }<br>
>>> +}<br>
>>> +<br>
>>> +// Verify disable pragma loop directive generates correct metadata<br>
>>> +void disable_test(int *List, int Length) {<br>
>>> + #pragma loop vectorize(disable)<br>
>>> + for(int i = 0; i < Length; i++) {<br>
>>> + List[i] = i*2;<br>
>>> + }<br>
>>> +}<br>
>>> +<br>
>>> +#define VECWIDTH 2<br>
>>> +#define INTERLEAVE 2<br>
>>> +<br>
>>> +// Verify defines are correctly resolved in pragma loop directive<br>
>>> +void for_define_test(int *List, int Length, int Value) {<br>
>>> + #pragma loop vectorize(VECWIDTH) interleave(INTERLEAVE)<br>
>>> + for(int i = 0; i < Length; i++) {<br>
>>> + List[i] = i*Value;<br>
>>> + }<br>
>>> +}<br>
>>> +<br>
>>> +// Verify metadata is generated when template is used.<br>
>>> +template <typename A><br>
>>> +void for_template_test(A *List, int Length, A Value) {<br>
>>> +<br>
>>> + #pragma loop vectorize(8) interleave(8)<br>
>>> + for(int i = 0; i < Length; i++) {<br>
>>> + List[i] = i*Value;<br>
>>> + }<br>
>>> +}<br>
>>> +<br>
>>> +// Verify define is resolved correctly when template is used.<br>
>>> +template <typename A><br>
>>> +void for_template_define_test(A *List, int Length, A Value) {<br>
>>> + #pragma loop vectorize(VECWIDTH) interleave(INTERLEAVE)<br>
>>> + for(int i = 0; i < Length; i++) {<br>
>>> + List[i] = i*Value;<br>
>>> + }<br>
>>> +}<br>
>>> +<br>
>>> +#undef VECWIDTH<br>
>>> +#undef INTERLEAVE<br>
>>> +<br>
>>> +// Use templates defined above. Test verifies metadata is generated correctly.<br>
>>> +void template_test(double *List, int Length) {<br>
>>> + double Value = 10;<br>
>>> +<br>
>>> + for_template_test<double>(List, Length, Value);<br>
>>> + for_template_define_test<double>(List, Length, Value);<br>
>>> +}<br>
>>> Index: test/PCH/pragma-loop.cpp<br>
>>> ===================================================================<br>
>>> --- test/PCH/pragma-loop.cpp (revision 0)<br>
>>> +++ test/PCH/pragma-loop.cpp (working copy)<br>
>>> @@ -0,0 +1,59 @@<br>
>>> +// RUN: %clang_cc1 -emit-pch -o %t.a %s<br>
>>> +// RUN: %clang_cc1 -include-pch %t.a %s -ast-print -o - | FileCheck %s<br>
>>> +<br>
>>> +// CHECK: #pragma loop vectorize(8)<br>
>>> +// CHECK: #pragma loop interleave(4)<br>
>>> +// CHECK: #pragma loop vectorize(disable)<br>
>>> +// CHECK: #pragma loop interleave(enable)<br>
>>> +// CHECK: #pragma loop vectorize(enable)<br>
>>> +// CHECK: #pragma loop interleave(disable)<br>
>>> +<br>
>>> +#ifndef HEADER<br>
>>> +#define HEADER<br>
>>> +<br>
>>> +class pragma_test {<br>
>>> +public:<br>
>>> + inline void run1(int *List, int Length) {<br>
>>> + int i = 0;<br>
>>> + #pragma loop vectorize(8)<br>
>>> + #pragma loop interleave(4)<br>
>>> + while (i < Length) {<br>
>>> + List[i] = i;<br>
>>> + i++;<br>
>>> + }<br>
>>> + }<br>
>>> +<br>
>>> + inline void run2(int *List, int Length) {<br>
>>> + int i = 0;<br>
>>> + #pragma loop vectorize(disable)<br>
>>> + #pragma loop interleave(enable)<br>
>>> + while (i-1 < Length) {<br>
>>> + List[i] = i;<br>
>>> + i++;<br>
>>> + }<br>
>>> + }<br>
>>> +<br>
>>> + inline void run3(int *List, int Length) {<br>
>>> + int i = 0;<br>
>>> + #pragma loop vectorize(enable)<br>
>>> + #pragma loop interleave(disable)<br>
>>> + while (i-3 < Length) {<br>
>>> + List[i] = i;<br>
>>> + i++;<br>
>>> + }<br>
>>> + }<br>
>>> +};<br>
>>> +<br>
>>> +#else<br>
>>> +<br>
>>> +void test() {<br>
>>> + int List[100];<br>
>>> +<br>
>>> + pragma_test pt;<br>
>>> +<br>
>>> + pt.run1(List, 100);<br>
>>> + pt.run2(List, 100);<br>
>>> + pt.run3(List, 100);<br>
>>> +}<br>
>>> +<br>
>>> +#endif<br>
>>> Index: test/Parser/pragma-loop-ast.cpp<br>
>>> ===================================================================<br>
>>> --- test/Parser/pragma-loop-ast.cpp (revision 0)<br>
>>> +++ test/Parser/pragma-loop-ast.cpp (working copy)<br>
>>> @@ -0,0 +1,33 @@<br>
>>> +// RUN: %clang_cc1 -ast-print %s | FileCheck %s<br>
>>> +<br>
>>> +// CHECK: #pragma loop vectorize(4)<br>
>>> +// CHECK: #pragma loop interleave(8)<br>
>>> +// CHECK: #pragma loop vectorize(enable)<br>
>>> +// CHECK: #pragma loop interleave(disable)<br>
>>> +// CHECK: #pragma loop vectorize(disable)<br>
>>> +// CHECK: #pragma loop interleave(enable)<br>
>>> +<br>
>>> +void test(int *List, int Length)<br>
>>> +{<br>
>>> + int i = 0;<br>
>>> + #pragma loop vectorize(4)<br>
>>> + #pragma loop interleave(8)<br>
>>> + while (i < Length) {<br>
>>> + List[i] = i * 2;<br>
>>> + i++;<br>
>>> + }<br>
>>> +<br>
>>> + #pragma loop vectorize(enable)<br>
>>> + #pragma loop interleave(disable)<br>
>>> + while (i-1 < Length) {<br>
>>> + List[i] = i * 2;<br>
>>> + i++;<br>
>>> + }<br>
>>> +<br>
>>> + #pragma loop vectorize(disable)<br>
>>> + #pragma loop interleave(enable)<br>
>>> + while (i-2 < Length) {<br>
>>> + List[i] = i * 2;<br>
>>> + i++;<br>
>>> + }<br>
>>> +}<br>
>>> Index: test/Parser/pragma-loop.cpp<br>
>>> ===================================================================<br>
>>> --- test/Parser/pragma-loop.cpp (revision 0)<br>
>>> +++ test/Parser/pragma-loop.cpp (working copy)<br>
>>> @@ -0,0 +1,105 @@<br>
>>> +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s<br>
>>> +<br>
>>> +// Note that this puts the expected lines before the directives to work around<br>
>>> +// limitations in the -verify mode.<br>
>>> +<br>
>>> +void test(int *List, int Length)<br>
>>> +{<br>
>>> + int i = 0;<br>
>>> +<br>
>>> + #pragma loop vectorize(4)<br>
>>> + #pragma loop interleave(8)<br>
>>> + while (i+1 < Length) {<br>
>>> + List[i] = i;<br>
>>> + }<br>
>>> +<br>
>>> + #pragma loop vectorize(enable)<br>
>>> + #pragma loop interleave(enable)<br>
>>> + while (i < Length) {<br>
>>> + List[i] = i;<br>
>>> + }<br>
>>> +<br>
>>> + #pragma loop vectorize(disable)<br>
>>> + #pragma loop interleave(disable)<br>
>>> + while (i-1 < Length) {<br>
>>> + List[i] = i;<br>
>>> + }<br>
>>> +<br>
>>> + #pragma loop vectorize(4) interleave(8)<br>
>>> + while (i-2 < Length) {<br>
>>> + List[i] = i;<br>
>>> + }<br>
>>> +<br>
>>> + #pragma loop interleave(16)<br>
>>> + while (i-3 < Length) {<br>
>>> + List[i] = i;<br>
>>> + }<br>
>>> +<br>
>>> + int VList[Length];<br>
>>> + #pragma loop vectorize(disable) interleave(disable)<br>
>>> + for (int j : VList) {<br>
>>> + VList[j] = List[j];<br>
>>> + }<br>
>>> +<br>
>>> +/* expected-error {{expected '('}} */ #pragma loop vectorize<br>
>>> +/* expected-error {{expected '('}} */ #pragma loop interleave<br>
>>> +<br>
>>> +/* expected-error {{expected ')'}} */ #pragma loop vectorize(4<br>
>>> +/* expected-error {{expected ')'}} */ #pragma loop interleave(4<br>
>>> +<br>
>>> +/* expected-error {{missing option in directive '#pragma loop'}} */ #pragma loop<br>
>>> +/* expected-error {{invalid option 'badkeyword' in directive '#pragma loop'}} */ #pragma loop badkeyword<br>
>>> +/* expected-error {{invalid option 'badkeyword' in directive '#pragma loop'}} */ #pragma loop badkeyword(2)<br>
>>> +/* expected-error {{invalid option 'badkeyword' in directive '#pragma loop'}} */ #pragma loop vectorize(4) badkeyword(4)<br>
>>> +/* expected-warning {{extra tokens at end of '#pragma loop'}} */ #pragma loop vectorize(4) ,<br>
>>> +<br>
>>> + while (i-4 < Length) {<br>
>>> + List[i] = i;<br>
>>> + }<br>
>>> +<br>
>>> +/* expected-error {{expected a positive integer in directive '#pragma loop vectorize'}} */ #pragma loop vectorize(0)<br>
>>> +/* expected-error {{expected a positive integer in directive '#pragma loop interleave'}} */ #pragma loop interleave(0)<br>
>>> + while (i-5 < Length) {<br>
>>> + List[i] = i;<br>
>>> + }<br>
>>> +<br>
>>> +/* expected-error {{expected a positive integer in directive '#pragma loop vectorize'}} */ #pragma loop vectorize(3000000000)<br>
>>> +/* expected-error {{expected a positive integer in directive '#pragma loop interleave'}} */ #pragma loop interleave(3000000000)<br>
>>> + while (i-6 < Length) {<br>
>>> + List[i] = i;<br>
>>> + }<br>
>>> +<br>
>>> +/* expected-error {{expected a positive integer in directive '#pragma loop vectorize'}} */ #pragma loop vectorize(badvalue)<br>
>>> +/* expected-error {{expected a positive integer in directive '#pragma loop interleave'}} */ #pragma loop interleave(badvalue)<br>
>>> + while (i-7 < Length) {<br>
>>> + List[i] = i;<br>
>>> + }<br>
>>> +<br>
>>> +#pragma loop vectorize(enable)<br>
>>> +/* expected-error {{expected a for, while, or do-while loop to follow the '#pragma loop' directive}} */ int j = Length;<br>
>>> + List[0] = List[1];<br>
>>> +<br>
>>> + while (j-1 < Length) {<br>
>>> + List[j] = j;<br>
>>> + }<br>
>>> +<br>
>>> +#pragma loop vectorize(4)<br>
>>> +/* expected-error {{'value' and 'disable' directive option types are incompatible in '#pragma loop vectorize'}} */ #pragma loop vectorize(disable)<br>
>>> + while (i-8 < Length) {<br>
>>> + List[i] = i;<br>
>>> + }<br>
>>> +<br>
>>> +#pragma loop interleave(enable)<br>
>>> +/* expected-error {{'enable' and 'disable' directive option types are incompatible in '#pragma loop interleave'}} */ #pragma loop interleave(disable)<br>
>>> + while (i-9 < Length) {<br>
>>> + List[i] = i;<br>
>>> + }<br>
>>> +<br>
>>> +#pragma loop vectorize(disable)<br>
>>> +/* expected-error {{'disable' and 'value' directive option types are incompatible in '#pragma loop vectorize'}} */ #pragma loop vectorize(4)<br>
>>> + while (i-10 < Length) {<br>
>>> + List[i] = i;<br>
>>> + }<br>
>>> +<br>
>>> +#pragma loop interleave(enable)<br>
>>> +/* expected-error {{expected statement}} */ }<br>
>>><br>
>><br>
>> ~Aaron<br>
<br>
_______________________________________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@cs.uiuc.edu">cfe-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits</a><br>
</blockquote></div><br></div>