summaryrefslogtreecommitdiff
path: root/lib/Sema/SemaStmtAttr.cpp
diff options
context:
space:
mode:
authorMark Heffernan <meheff@google.com>2015-08-10 17:29:39 +0000
committerMark Heffernan <meheff@google.com>2015-08-10 17:29:39 +0000
commit1476822dedfb8de49257c925d42be01676d226fd (patch)
tree36f2fe5237d008d9d55001d7dc89d9e7b7507b75 /lib/Sema/SemaStmtAttr.cpp
parent8aef53c9eb29fe479227c6b408150c939fbf1259 (diff)
downloadclang-1476822dedfb8de49257c925d42be01676d226fd.tar.gz
Add new llvm.loop.unroll.enable metadata for use with "#pragma unroll".
This change adds the new unroll metadata "llvm.loop.unroll.enable" which directs the optimizer to unroll a loop fully if the trip count is known at compile time, and unroll partially if the trip count is not known at compile time. This differs from "llvm.loop.unroll.full" which explicitly does not unroll a loop if the trip count is not known at compile time With this change "#pragma unroll" generates "llvm.loop.unroll.enable" rather than "llvm.loop.unroll.full" metadata. This changes the semantics of "#pragma unroll" slightly to mean "unroll aggressively (fully or partially)" rather than "unroll fully or not at all". The motivating example for this change was some internal code with a loop marked with "#pragma unroll" which only sometimes had a compile-time trip count depending on template magic. When the trip count was a compile-time constant, everything works as expected and the loop is fully unrolled. However, when the trip count was not a compile-time constant the "#pragma unroll" explicitly disabled unrolling of the loop(!). Removing "#pragma unroll" caused the loop to be unrolled partially which was desirable from a performance perspective. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@244467 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaStmtAttr.cpp')
-rw-r--r--lib/Sema/SemaStmtAttr.cpp70
1 files changed, 41 insertions, 29 deletions
diff --git a/lib/Sema/SemaStmtAttr.cpp b/lib/Sema/SemaStmtAttr.cpp
index 5b71c11b52..02d562852f 100644
--- a/lib/Sema/SemaStmtAttr.cpp
+++ b/lib/Sema/SemaStmtAttr.cpp
@@ -65,19 +65,32 @@ static Attr *handleLoopHintAttr(Sema &S, Stmt *St, const AttributeList &A,
return nullptr;
}
- LoopHintAttr::OptionType Option;
LoopHintAttr::Spelling Spelling;
- if (PragmaUnroll) {
- Option = ValueExpr ? LoopHintAttr::UnrollCount : LoopHintAttr::Unroll;
- Spelling = LoopHintAttr::Pragma_unroll;
- } else if (PragmaNoUnroll) {
- Option = LoopHintAttr::Unroll;
+ LoopHintAttr::OptionType Option;
+ LoopHintAttr::LoopHintState State;
+ if (PragmaNoUnroll) {
+ // #pragma nounroll
Spelling = LoopHintAttr::Pragma_nounroll;
+ Option = LoopHintAttr::Unroll;
+ State = LoopHintAttr::Disable;
+ } else if (PragmaUnroll) {
+ Spelling = LoopHintAttr::Pragma_unroll;
+ if (ValueExpr) {
+ // #pragma unroll N
+ Option = LoopHintAttr::UnrollCount;
+ State = LoopHintAttr::Numeric;
+ } else {
+ // #pragma unroll
+ Option = LoopHintAttr::Unroll;
+ State = LoopHintAttr::Enable;
+ }
} else {
+ // #pragma clang loop ...
+ Spelling = LoopHintAttr::Pragma_clang_loop;
assert(OptionLoc && OptionLoc->Ident &&
"Attribute must have valid option info.");
- IdentifierInfo *OptionInfo = OptionLoc->Ident;
- Option = llvm::StringSwitch<LoopHintAttr::OptionType>(OptionInfo->getName())
+ Option = llvm::StringSwitch<LoopHintAttr::OptionType>(
+ OptionLoc->Ident->getName())
.Case("vectorize", LoopHintAttr::Vectorize)
.Case("vectorize_width", LoopHintAttr::VectorizeWidth)
.Case("interleave", LoopHintAttr::Interleave)
@@ -85,31 +98,29 @@ static Attr *handleLoopHintAttr(Sema &S, Stmt *St, const AttributeList &A,
.Case("unroll", LoopHintAttr::Unroll)
.Case("unroll_count", LoopHintAttr::UnrollCount)
.Default(LoopHintAttr::Vectorize);
- Spelling = LoopHintAttr::Pragma_clang_loop;
- }
-
- LoopHintAttr::LoopHintState State = LoopHintAttr::Default;
- if (PragmaNoUnroll) {
- State = LoopHintAttr::Disable;
- } else if (Option == LoopHintAttr::VectorizeWidth ||
- Option == LoopHintAttr::InterleaveCount ||
- Option == LoopHintAttr::UnrollCount) {
- assert(ValueExpr && "Attribute must have a valid value expression.");
- if (S.CheckLoopHintExpr(ValueExpr, St->getLocStart()))
- return nullptr;
- } else if (Option == LoopHintAttr::Vectorize ||
- Option == LoopHintAttr::Interleave ||
- Option == LoopHintAttr::Unroll) {
- // Default state is assumed if StateLoc is not specified, such as with
- // '#pragma unroll'.
- if (StateLoc && StateLoc->Ident) {
+ if (Option == LoopHintAttr::VectorizeWidth ||
+ Option == LoopHintAttr::InterleaveCount ||
+ Option == LoopHintAttr::UnrollCount) {
+ assert(ValueExpr && "Attribute must have a valid value expression.");
+ if (S.CheckLoopHintExpr(ValueExpr, St->getLocStart()))
+ return nullptr;
+ State = LoopHintAttr::Numeric;
+ } else if (Option == LoopHintAttr::Vectorize ||
+ Option == LoopHintAttr::Interleave ||
+ Option == LoopHintAttr::Unroll) {
+ assert(StateLoc && StateLoc->Ident && "Loop hint must have an argument");
if (StateLoc->Ident->isStr("disable"))
State = LoopHintAttr::Disable;
else if (StateLoc->Ident->isStr("assume_safety"))
State = LoopHintAttr::AssumeSafety;
- else
+ else if (StateLoc->Ident->isStr("full"))
+ State = LoopHintAttr::Full;
+ else if (StateLoc->Ident->isStr("enable"))
State = LoopHintAttr::Enable;
- }
+ else
+ llvm_unreachable("bad loop hint argument");
+ } else
+ llvm_unreachable("bad loop hint");
}
return LoopHintAttr::CreateImplicit(S.Context, Spelling, Option, State,
@@ -183,7 +194,8 @@ CheckForIncompatibleAttributes(Sema &S,
CategoryState.StateAttr->getState() == LoopHintAttr::Disable)) {
// Disable hints are not compatible with numeric hints of the same
// category. As a special case, numeric unroll hints are also not
- // compatible with "enable" form of the unroll pragma, unroll(full).
+ // compatible with enable or full form of the unroll pragma because these
+ // directives indicate full unrolling.
S.Diag(OptionLoc, diag::err_pragma_loop_compatibility)
<< /*Duplicate=*/false
<< CategoryState.StateAttr->getDiagnosticName(Policy)